Skip to Content
Technical walkthroughsCLI to Production

Scenario: CLI to Production

Technical reference. This page is for integrations, advanced configuration, or platform operations. For portal tasks, start with the user guide.

In this scenario, you use orqestractl to author, validate, and deploy a workflow entirely from the terminal — then set up GitOps sync for ongoing deployments.

What you’ll do

  1. Author assets and a flow as local YAML files
  2. Validate the flow structure
  3. Deploy to Orqestra via the CLI
  4. Promote through the release lifecycle
  5. Set up GitOps sync for continuous deployment

Prerequisites

  • orqestractl installed (pip install orqestra-cli)
  • Orqestra running locally (make dev)
  • API credentials configured:
    export ORQESTRA_API_URL=http://localhost:8000 export ORQESTRA_API_KEY=your-key

Step 1: Author Resources Locally

Create a project directory with your Orqestra resources:

mkdir -p orqestra-project/{assets,flows}

assets/classifier-prompt.yaml:

kind: asset slug: classifier-prompt asset_kind: prompt_template owner_ref: team:support version: label: v1 content: system_message: "You are a ticket classification system. Classify each ticket as low, medium, or high urgency." user_template: "Classify this ticket: {{ query }}"

assets/model-policy.yaml:

kind: asset slug: ticket-model-policy asset_kind: model_policy owner_ref: team:support version: label: v1 content: provider_route: route_id: your-provider-classifier-us provider: your-provider model: your-provider/your-model account_slot: your-provider-prod region: us-east-1 residency: us state: approved sensitivity_tiers: [public, internal] capability_tags: [chat, classification] cost_class: standard prompt_caching: allowed logging: redacted fallback_routes: [] temperature: 0.1 max_tokens: 100

assets/workload-profile.yaml:

kind: asset slug: ticket-workload-profile asset_kind: workload_profile owner_ref: team:support version: label: v1 content: category: chat audience: internal autonomy_level: assistive data_sensitivity: internal retrieval_needs: { required: false } memory_needs: { required: true } tool_needs: { required: false } egress_needs: { posture: none } evidence_expectations: { trace_level: detailed }

assets/sandbox-profile.yaml:

kind: asset slug: ticket-sandbox-profile asset_kind: sandbox_profile owner_ref: team:support version: label: v1 content: isolation_class: process capabilities: { code_execution: true, tool_use: true, retrieval: true, memory: true } resource_limits: { timeout_seconds: 60 } network_posture: { egress: none } data_access: { max_sensitivity: internal } secret_posture: none tool_posture: { allowed: true, families: [http_request], max_side_effect_class: read_write } evidence_requirements: { trace_level: detailed } lifecycle_posture: workspace_scoped

assets/harness.yaml:

kind: asset slug: ticket-harness asset_kind: workload_harness owner_ref: team:support version: label: v1 content: # Scenario assertions are empty for the quickstart; the harness # still pins the release to a governed harness asset version. scenarios: [] negative_scenarios: [] retrieval_assertions: [] memory_assertions: [] tool_assertions: [] egress_assertions: [] evidence_checks: [] evaluation_refs: []

flows/classify-ticket.yaml:

kind: flow slug: classify-ticket owner_ref: team:support version: label: v1 content: name: Ticket Classifier description: Classifies support tickets by urgency trigger: type: api_request inputs_schema: type: object required: [query] properties: query: type: string entry_step: classify steps: - id: classify type: llm_call config: prompt_template_ref: classifier-prompt

Step 2: Validate the Flow

Check for structural errors before deploying:

orqestractl flow validate --file flows/classify-ticket.yaml

Expected output:

Flow validation: PASSED Steps: 1 Entry step: classify (valid) Trigger: api_request (valid) References: prompt_template_ref=classifier-prompt

Step 3: Deploy with Sync

Use orqestractl sync to create all resources in one command:

# Preview what will be created orqestractl sync preview --dir ./orqestra-project # Apply orqestractl sync apply --dir ./orqestra-project

Output:

Sync complete: Created: 2 assets, 1 flow Updated: 0 Unchanged: 0

Declarative asset versions are idempotent by label and content. Re-running orqestractl sync preview --dir ./orqestra-project skips an existing matching version. If you change the content of an immutable version label such as v1, sync stops and asks you to create a new label such as v2.

Step 4: Create the Workload and Release

# Declare the workload's PII classification up front (the interface config # file is the full interface_config document). echo 'pii_classification: internal' > interface.yaml # Create the application, declaring every runtime-readiness input up front: # an invocation mode, a PII classification (via --interface-config), the # release environment intent, and the three authoring-default asset versions # (workload profile / sandbox profile / harness — captured like the other # version IDs below, from the portal or the JSON APIs). WORKLOAD_ID=$(orqestractl --format json workload create --slug ticket-classifier --owner team:support \ --invocation-mode api --release-environment-intent production \ --interface-config interface.yaml \ --default-workload-profile-id $WL_PROFILE_V1 \ --default-sandbox-profile-id $SBX_PROFILE_V1 \ --default-workload-harness-id $HARNESS_V1 | jq -r '.workload_id') # Bind a service lane — an effective lane binding is required before the # workload can dispatch real runs. orqestractl workload lane-binding add $WORKLOAD_ID --lane standard # Create a release RELEASE_ID=$(orqestractl --format json release create --workload $WORKLOAD_ID --environment production | jq -r '.release_id')

Runtime-readiness activation gate. Activating a release on an operator-managed workload requires the workload to be runtime-ready (invocation mode, PII classification, workload profile / sandbox profile / harness defaults, a service-lane binding, a release environment intent, human oversight when required, and every declared connection requirement). If anything is missing, the --to active transition is refused with a typed 409 workload_not_ready whose blockers list names every missing item — fix the named items and retry. The workload page’s readiness banner shows the same projection, and orqestractl release transition prints the refusal with the missing-readiness list.

# Bind assets (release bind expects asset_version_id values) # Capture these IDs from the portal or the JSON APIs if you do not already # have them from earlier create/version calls. orqestractl release bind $RELEASE_ID --asset-version $PROMPT_V1 --role main_prompt orqestractl release bind-model-policy $RELEASE_ID --asset-version $MODEL_POLICY_V1 orqestractl release bind $RELEASE_ID --asset-version $FLOW_V1 --role orchestration_flow orqestractl release bind $RELEASE_ID --asset-version $POLICY_V1 --role policy_bundle # Promote through the release lifecycle orqestractl release transition $RELEASE_ID --to review_ready # Record at least one approval via the portal or API before approving curl -X POST http://localhost:8000/v1/releases/$RELEASE_ID/approvals \ -H "Content-Type: application/json" \ -d '{ "outcome": "approved", "subject_kind": "release", "subject_ref": "'"$RELEASE_ID"'" }' orqestractl release transition $RELEASE_ID --to approved orqestractl release transition $RELEASE_ID --to active

Step 5: Test the Deployment

orqestractl release get $RELEASE_ID

At this point the release is live. For a bounded knowledge-query workload you can also use:

orqestractl run <workload-slug> --query "What is Orqestra?"

For non-chat workloads, use the portal or the workload-specific interface you attached to that release.

Step 6: Set Up GitOps for Continuous Deployment

Push your project to Git and add a CI pipeline:

cd orqestra-project git init git add . git commit -m "Initial Orqestra resources" git remote add origin git@github.com:<your-org>/orqestra-resources.git git push -u origin main

.github/workflows/deploy.yml:

name: Deploy to Orqestra on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.13" - run: pip install orqestra-cli - run: orqestractl sync reconcile --dir . env: ORQESTRA_API_URL: ${{ secrets.ORQESTRA_API_URL }} ORQESTRA_API_KEY: ${{ secrets.ORQESTRA_API_KEY }}

Now every push to main automatically syncs your resource definitions to Orqestra.

For separate Orqestra instances, export the governed release shape from the source instance and import it into the target after the referenced asset versions and target connection instances exist:

orqestractl release export-manifest $RELEASE_ID \ --workspace $SOURCE_WORKSPACE_ID \ --file release-manifest.yaml orqestractl release import-manifest \ --workspace $TARGET_WORKSPACE_ID \ --file release-manifest.yaml

The manifest contains the release policy bundle slug, pinned asset versions, and logical connection bindings. It does not contain secrets; connection parameters must be non-secret configuration, and each target instance keeps its own Vault secrets.

Step 7: Make a Change

Update the prompt and push:

# Edit the prompt vim assets/classifier-prompt.yaml # Change version label to v2, update the system_message git add -A git commit -m "Improve classifier prompt" git push

The CI pipeline runs orqestractl sync reconcile --dir ., creating or updating the declared resources. Create a new release to activate new versions.

What you’ve learned

  • How to author Orqestra resources as local YAML files
  • How to validate flows before deployment
  • How to deploy with orqestractl sync
  • How to promote releases through the actual release lifecycle (review_ready -> approved -> active)
  • How to set up GitOps for continuous deployment from Git