Skip to Content
Task guidesTechnical: GitOps & Terraform

GitOps & Terraform

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

Orqestra supports declarative delivery two ways. GitOps sync via the CLI is the primary, fully supported mechanism: it manages the full declarative package — workloads, assets, flows, releases, and bindings — with validation, diff/preview, idempotent apply, and reconcile. A Terraform provider is also available as a secondary option for teams standardizing on Terraform; it now covers the launch Orqestra resource model, while guardrail configuration and underlying infrastructure modules remain separate work. When in doubt, use GitOps sync for first deployments and migrations.

GitOps Sync

apply and reconcile submit the complete mutation plan to the control plane once before the first writer. Any denial or unavailable/malformed response fails closed with zero domain writes. The result is not a reservation or token: writers re-check current authorization, so a post-allow change can still leave the existing resumable partial apply.

orqestractl sync reads a bundle of YAML resource definitions from a directory and applies the desired current state to the Orqestra control plane. Resources that already exist are updated when their mutable metadata changes; immutable asset and flow versions are reused by content hash or created when the declared content changes.

Directory Structure

Organize each workload bundle in a Git repository:

orqestra-resources/ workload.yaml release.dev.yaml resources/ qa-prompt.prompt-template.yaml gpt4-standard.model-config.yaml docs.knowledge-base.yaml restricted-runtime.policy-bundle.yaml pii-filter.guardrail.yaml knowledge-api.connection.yaml flows/ knowledge-qa.flow.yaml

For reviewable packages that should carry the full desired state in one document, orqestractl sync also accepts orqestra.package.yaml at the bundle root. The package schema lives at packages/contracts/schemas/declarative_package.schema.json and validates the known sections before sync performs any live API lookups. When a package file is present, split files in resources/, flows/, and release.*.yaml are not read. The current sync apply path handles workloads, assets, connection instances, flows, releases, asset release bindings, Hermes runtime release bindings, and supplier proposal submissions; apps, policies, tool_permissions, and knowledge_configs are validated and shown as skipped until the follow-up reconciliation slices apply them.

# orqestra.package.yaml api_version: orqestra.ai/v1alpha1 kind: DeclarativePackage metadata: name: knowledge-assistant-package owner_ref: team:ai-platform environment_metadata: default_environment: dev environments: - name: dev approval_required: false workloads: - slug: knowledge-assistant display_name: Knowledge Assistant owner_ref: team:ai-platform flows: - slug: knowledge-qa display_name: Knowledge Q&A steps: [] assets: - kind: prompt_template slug: qa-prompt owner_ref: team:ai-platform content: system_message: "You are a helpful assistant..." policies: [] tool_permissions: [] knowledge_configs: [] releases: - slug: dev workload_slug: knowledge-assistant environment: dev target_lane: all bindings: orchestration_flow: knowledge-qa prompt_template: qa-prompt runtime_bindings: - runtime_profile_id: 90c14a9e-4c33-4c6b-a11a-f78ad4b7d55d adapter_config_ref: adapter-config:knowledge-assistant-dev tool_profile_ref: knowledge-readonly

The same package schema also accepts supplier requirement and claim proposals with explicit provider IDs and revision/generation counters. A requirement proposal must be reviewed separately by an authorized human before a claim can be proposed. Claim proposals keep a fixed finite valid_until; sync retries never refresh it. See Governed Providers for the YAML examples and separate human-review steps. Proposals do not set outcomes or establish certification.

Resource Definition Format

The bundle root defines the workload and releases. resources/ contains one file per governed resource. flows/ contains one file per orchestration flow. The file name is for humans; the slug field is authoritative.

# workload.yaml slug: knowledge-assistant display_name: Knowledge Assistant description: Retrieval-grounded assistant for governed workspace knowledge owner_ref: team:ai-platform status: registered invocation_mode: chat interface_config: flow_slug: knowledge-qa domain: knowledge system_of_record: docs service_lane: standard human_decision_required: false pii_classification: internal source_repo: knowledge-assistant release_environment_intent: pilot default_workload_profile_version_id: knowledge-workload-profile default_sandbox_profile_version_id: asset_slug: knowledge-sandbox-profile version: v3 default_workload_harness_version_id: knowledge-harness access: service_lane: standard service_lane_reason: Standard governed assistant lane principal_bindings: - actor_ref: user:alice@orqestra.dev access_mode: interactive - actor_ref: user:ops@orqestra.dev access_mode: interactive

Workload readiness fields

A workload only becomes dispatchable once six fields are set, and all six are declarable here: invocation_mode, interface_config.pii_classification, service_lane, release_environment_intent (pilot | staged | production), and the three default asset versions below.

The three default_*_version_id fields take an asset reference, not an asset-version UUID — a UUID is environment-specific and would make the package non-portable. Either form works:

# bare slug -- resolves to the asset's latest live version default_workload_harness_version_id: knowledge-harness # pinned to one published version label default_sandbox_profile_version_id: asset_slug: knowledge-sandbox-profile version: v3

Both resolve against live state at plan time, so the referenced asset version must already exist when the workload is created — a package that declares the profile asset and the workload together resolves them on the apply after the asset version is written. An unresolvable reference is a sync conflict, not a silently dropped field.

Binding a sandbox profile on the release does not satisfy sandbox_profile_unset: readiness reads the workload’s own default_sandbox_profile_version_id.

# resources/qa-prompt.prompt-template.yaml kind: prompt_template slug: qa-prompt display_name: QA Prompt owner_ref: team:ai-platform content: system_message: "You are a helpful assistant..." user_template: "Context: {{ context }}\n\nQuestion: {{ query }}"
# flows/knowledge-qa.flow.yaml slug: knowledge-qa display_name: Knowledge Q&A owner_ref: team:ai-platform name: Knowledge Q&A description: RAG-based question answering trigger: type: api_request entry_step: retrieve steps: - id: retrieve type: task config: plugin: knowledge_query next: generate - id: generate type: llm_call config: prompt_template_ref: qa-prompt
# resources/knowledge-api.connection.yaml kind: connector_definition slug: knowledge-api owner_ref: team:ai-platform definition: service_type: https config_fields: - key: base_url label: Base URL required: true secret_slots: - slot: api_key label: API key is_required: true inject_hosts: - knowledge-api.example.com instance: display_name: Knowledge API config: base_url: https://knowledge-api.example.com secret_bindings: api_key: knowledge-api-key
# release.dev.yaml workload: knowledge-assistant environment: dev bindings: orchestration_flow: knowledge-qa model_policy: gpt4-standard policy_bundle: restricted-runtime-policy guardrail_config: pii-filter

Connection sync creates or updates the connection definition asset and the local connection instance from the same manifest. Secret bindings point to secret names, not secret values; operators store the secret values in Vault or the configured secret manager.

Release sync binds by slug only. orqestractl sync resolves each binding to the version created or reused earlier in the same sync run. If live Orqestra already has an identical version, sync reuses it. If the content changed, sync creates a new immutable version and lets the control plane assign the next internal label. Use model_policy for provider-routed release bindings.

Flow sync uses the same content-hash model as governed assets. Source manifests do not carry version labels; Git records authoring history, and Orqestra records immutable runtime history.

Workload access sync creates service-lane and principal bindings from the optional access block in workload.yaml. access.service_lane is the runtime authorization lane; interface_config.service_lane remains workload metadata for portal display and operator context. If no access.service_lane is present, sync falls back to the legacy top-level service_lane and then interface_config.service_lane. access.principal_bindings accepts either a list of actor refs or objects with actor_ref, optional actor_type, access_mode, and optional scope_ref.

Running Sync

orqestractl sync is a command group with four verbs that form a clear progression from local check to live convergence:

# Validate the package locally, no API calls (full schema for the package # layout; structural parse checks for the split-file layout) orqestractl sync validate --dir ./orqestra-resources # Preview the diff against live state without mutating anything orqestractl sync preview --dir ./orqestra-resources # Apply the diff to reach the desired state orqestractl sync apply --dir ./orqestra-resources # Converge to the desired state, reporting drift (idempotent CI/CD entrypoint) orqestractl sync reconcile --dir ./orqestra-resources

The API target and credentials come from ORQESTRA_API_URL / ORQESTRA_API_KEY (or the CLI config). validate never touches the API; preview reads live state but never mutates; apply and reconcile are fail-closed — they change nothing while the diff still contains an unresolved conflict.

Declarative sync prepares resources through review_ready. Approval and activation stay governed CLI/portal actions. Package reconciliation, a pending release candidate, and the release currently selected for execution are distinct: a matching draft or review_ready candidate is not evidence that execution serves those bindings. Unqualified “no drift” / “up to date” is printed only when desired resources are reconciled and the observed effective bindings match, with a point-in-time qualifier. A serving gap, absent active release, or unverified serving read is printed even when the mutation plan is empty. validate remains local and makes no serving claim.

CI/CD Integration

Add sync to your CI/CD pipeline:

# .github/workflows/deploy.yml name: Deploy Orqestra Resources on: push: branches: [main] paths: ["orqestra-resources/**"] 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 ./orqestra-resources env: ORQESTRA_API_URL: ${{ secrets.ORQESTRA_API_URL }} ORQESTRA_API_KEY: ${{ secrets.ORQESTRA_API_KEY }}

Terraform Provider

The Orqestra Terraform provider is a secondary delivery option for teams standardizing on Terraform. It covers the launch Orqestra resource model, but GitOps sync remains the recommended path for first deployments and migration work because it converges the full workload package from source-controlled YAML.

Coverage today: The provider supports workloads, assets, asset versions, flows, releases, release bindings, and environment-scoped connection instances. Orqestra records without API delete endpoints use state-only destroy; this includes workloads, assets, asset versions, flows, releases, and release bindings. Update support is per-resource: workloads, flows, and connection instances support provider-managed updates; asset versions require replacement for asset_id or content changes; asset slug, asset_kind, or owner_ref changes require replacement; flow content changes create a new immutable version, while flow slug or owner_ref changes require replacement; release binding changes return an immutable-update diagnostic; releases do not expose mutable fields. orqestra_connection_instance supports API delete. orqestra_guardrail_config is not implemented yet; Terraform operations return a not-yet-implemented diagnostic. Terraform infrastructure modules for PostgreSQL, Redis, object storage, ingress, or cloud networking are not part of this provider.

Provider Configuration

terraform { required_providers { orqestra = { source = "orqestra/orqestra" } } } provider "orqestra" { api_url = "https://api.orqestra.example.com" # or ORQESTRA_API_URL api_key = var.orqestra_api_key # or ORQESTRA_API_KEY workspace_id = var.orqestra_workspace_id # or ORQESTRA_WORKSPACE_ID }

Available Resources

ResourceDescriptionStatus
orqestra_workloadManage workloadsCreate, read/import, update, state-only destroy
orqestra_assetManage governed assetsCreate, read/import, slug, asset_kind, or owner_ref changes require replacement, state-only destroy
orqestra_asset_versionManage asset versions with contentCreate, read/import, asset_id or content changes require replacement, state-only destroy
orqestra_flowManage orchestration flowsCreate, read/import, content update creates a new immutable version; slug or owner_ref changes require replacement, state-only destroy
orqestra_releaseManage releasesCreate, read/import, update not supported, state-only destroy
orqestra_release_bindingBind asset/flow versions to releasesCreate, read/import, immutable update error, state-only destroy
orqestra_connection_instanceManage environment-scoped connectionsCreate, read/import, update, API delete
orqestra_guardrail_configGuardrail configuration schemaNot implemented; Terraform operations return a not-yet-implemented diagnostic

Lookup data sources are available for stable authoring references: orqestra_workload_by_slug, orqestra_asset_by_slug, orqestra_flow_by_slug, and orqestra_release_by_environment.

Example Configuration

The example below creates a workload, prompt asset version, flow, release, and release bindings without manually authoring internal version labels.

resource "orqestra_workload" "knowledge_assistant" { slug = "knowledge-assistant" display_name = "Knowledge Assistant" description = "Retrieval-grounded assistant for governed workspace knowledge." owner_ref = "team:ai-platform" status = "registered" invocation_mode = "chat" } resource "orqestra_asset" "qa_prompt" { slug = "qa-prompt" asset_kind = "prompt_template" owner_ref = "team:ai-platform" } resource "orqestra_asset_version" "qa_prompt_v1" { asset_id = orqestra_asset.qa_prompt.id content = jsonencode({ system_message = "You are a helpful assistant..." user_template = "Context: {{ context }}\n\nQuestion: {{ query }}" }) } resource "orqestra_flow" "knowledge_qa" { slug = "knowledge-qa" owner_ref = "team:ai-platform" content = jsonencode({ name = "Knowledge Q&A" entry_step = "retrieve" steps = [] }) } resource "orqestra_release" "production" { workload_id = orqestra_workload.knowledge_assistant.id environment = "production" target_lane = "all" } resource "orqestra_release_binding" "prompt" { release_id = orqestra_release.production.id asset_version_id = orqestra_asset_version.qa_prompt_v1.id role = "prompt_template" } # Release bindings use asset_version_id for both asset versions and flow # version IDs; this flow binding references the provider-managed latest version. resource "orqestra_release_binding" "flow" { release_id = orqestra_release.production.id asset_version_id = orqestra_flow.knowledge_qa.latest_version_id role = "orchestration_flow" }

Terraform Workflow

# Initialize and plan terraform init terraform plan # Create resources terraform apply # Remove Terraform state for records without API delete endpoints; connection # instances use API delete terraform destroy

Use terraform import for existing Orqestra objects when adopting Terraform state. For append-only or immutable records, terraform destroy forgets the remote object instead of deleting historical Orqestra evidence. Terraform marks immutable fields as replacement at plan time. If a provider operation is not implemented, such as orqestra_guardrail_config, Terraform operations return a not-yet-implemented diagnostic. Use GitOps sync for package-level reconciliation from one directory when you need update behavior outside the provider’s launch coverage.

Choosing Between GitOps and Terraform

FactorGitOps SyncTerraform
CoverageFull declarative packageCore launch resources; guardrail config excluded
Best forFirst deployments and migrationsTeams standardizing on Terraform state
State managementStateless idempotent syncState file tracks resource lifecycle
Dependency orderingAutomatic sync orderingExplicit Terraform graph
Dry runsync previewterraform plan
Learning curveLow, YAML bundle orientedMedium, HCL and state concepts
DeletionAPI behavior per resourceAPI delete for connections; state-only destroy for append-only records

GitOps sync is the recommended path for full, governed delivery. The Terraform provider is a supported secondary option for Terraform-standardized teams; use GitOps sync for package-level convergence and for guardrail configuration or update paths that the provider does not yet cover.