Skip to content

Automation Platform > Deployment & hosting

Running agents with an external orchestrator

Open in ChatGPT ↗
Ask ChatGPT about this page
Open in Claude ↗
Ask Claude about this page
Copied!

Connect an external job scheduler to self-hosted agents with the Direct backend in one-shot mode or the Command backend.

Use an existing CI system, Kubernetes controller, or internal scheduler to allocate compute while the Automation Platform routes and tracks each run. The worker supports two patterns for this setup: start a Direct worker with --one-shot for each job, or use the Command backend to delegate runs to your runtime.

Both patterns keep execution on your infrastructure and require outbound connectivity to Warp.

PatternExternal orchestrator responsibilityWorker behaviorUse when
Direct backend with --one-shotStarts a worker process and creates a run for its unique worker IDRuns one task on the allocated host, then exitsYour scheduler allocates a VM, pod, or CI runner for each job
Command backendExposes an API or command that can accept a task payload and start the agentStays connected and invokes your dispatch command for each taskYour runtime already has its own job API, queue, or compute lifecycle

One-shot mode works only with the Direct backend. It forces max_concurrent_tasks to 1 and waits for one accepted task’s oz CLI process to exit before the worker exits. If no task arrives, the worker stays connected until your orchestrator stops it.

The Command backend is fire-and-forget. The dispatch command returns after the external runtime durably accepts the task. The remote agent, not the worker process, reports progress and completion to Warp.

This example starts a worker and routes one cloud agent run to it from the same job. Use a unique worker ID so another worker cannot claim the run.

By default, the CLI stays open for 45 minutes after a conversation completes so users can send follow-up prompts. The example sets --idle-on-complete 0s so the CLI and worker exit without that idle period. A task-level config.idle_timeout_minutes value takes precedence, so leave it unset or set it to 0 for these tasks.

  • Self-hosting enabled for your Enterprise teamContact sales if self-hosting is not enabled.
  • The worker and CLI binaries — Install oz-agent-worker from a published release and install the Oz CLI by following the CLI installation instructions.
  • An agent API key — Create one in the Oz web app. Store it in your orchestrator’s secret manager as WARP_API_KEY.

Add the following script to the job your orchestrator starts. Replace CI_JOB_ID with a unique job identifier from your system.

run-agent.sh
#!/usr/bin/env bash
set -euo pipefail
: "${WARP_API_KEY:?Set WARP_API_KEY in the job environment}"
: "${CI_JOB_ID:?Set CI_JOB_ID to a unique job identifier}"
worker_id="external-${CI_JOB_ID}"
oz-agent-worker \
--worker-id "$worker_id" \
--backend direct \
--one-shot \
--idle-on-complete 0s &
worker_pid=$!
trap 'kill "$worker_pid" 2>/dev/null || true' EXIT
oz agent run-cloud \
--host "$worker_id" \
--prompt "Run the test suite, fix failures, and open a pull request."
wait "$worker_pid"
trap - EXIT

The run may enter the queue before the worker finishes connecting. Warp assigns it after the matching worker ID is online. After the conversation completes, the oz CLI exits, then the one-shot worker and job exit.

Use Direct backend setup and teardown commands to prepare the workspace on the allocated host.

Use the Command backend when the external runtime owns job creation and cleanup. The worker invokes dispatch_command once for each assigned task and writes a versioned JSON payload to standard input.

The payload includes:

  • base_args — The oz agent run argument vector for the external runtime.
  • docker_image and sidecars — The task image and required sidecar mounts.
  • env — Task environment variables and credentials. Keep this payload out of logs.
  • run_id and server_root_url — Values the agent uses to report status to Warp.

The public command-backend example includes dependency-free Python dispatch and cancellation scripts for an HTTP runtime. Copy those scripts to the worker host, then configure the worker:

worker.yaml
worker_id: "external-runtime"
backend:
command:
dispatch_command: "python3 /opt/warp/dispatch.py"
cancel_command: "python3 /opt/warp/cancel.py"
dispatch_timeout: "60s"
environment:
- name: OZ_DISPATCH_URL
value: "https://runtime.internal.example.com/agent-runs"
- name: OZ_CANCEL_URL
value: "https://runtime.internal.example.com/agent-runs/cancel"
- name: OZ_DISPATCH_AUTH_HEADER

Start the worker with the authentication header and Warp API key supplied by your secret manager:

Terminal window
export OZ_DISPATCH_AUTH_HEADER="Bearer YOUR_RUNTIME_TOKEN"
export WARP_API_KEY="YOUR_AGENT_API_KEY"
oz-agent-worker --config-file worker.yaml

Adapt the example script’s transform() function to your runtime’s request schema. Your runtime must launch base_args with the supplied task environment, image, and sidecars. After the CLI exits, it must run oz harness-support --run-id RUN_ID report-shutdown so Warp receives the terminal state.

An exit code of 0 from dispatch_command means the external runtime accepted responsibility for the task. A nonzero exit or a dispatch timeout fails the task. max_concurrent_tasks limits simultaneous dispatch calls, not the number of agents running in the external runtime.