QUESTPIE Autopilot

Architecture

Orchestrator, workers, truth boundaries, and the execution model.

Autopilot splits into three layers:

  • Orchestrator — the control plane. Owns tasks, runs, workflow progression, events, artifacts, and durable previews.
  • Workers — execution nodes. Run on real machines with real repo access, toolchains, and credentials.
  • .autopilot/ — repo-authored policy. Agents, workflows, environments, providers, and handlers — all versioned in git.

Every client (CLI, bound conversations, future Worker App) operates over the same primitives. The orchestrator is the system of record. Workers execute. The repo defines the rules.

At a glance

LayerOwnsDoes not own
OrchestratorTasks, runs, workflow progression, events, artifacts, durable previewsRuntime sessions, worktrees, local credentials
WorkerRuntime execution, repo access, per-run worktrees, raw local session stateWorkflow truth, shared operational state
Repo configAgents, workflows, environments, providers, handlersMutable runtime state

Orchestrator

The orchestrator is the system of record for operational state. It:

  • Stores tasks, runs, workers, leases, events, and artifacts
  • Advances workflows based on explicit step outputs
  • Serves durable preview URLs from stored artifacts
  • Exposes the API used by the CLI and future clients
  • Dispatches notification and conversation-provider flows when configured

It does not execute AI sessions itself.

Start it with:

autopilot server start

Worker

A worker is a long-running execution node on a host machine. It:

  • Claims pending runs from the orchestrator
  • Executes through a runtime adapter
  • Uses real repo access, toolchain access, and machine-local credentials
  • Creates isolated git worktrees per run
  • Stores raw transcript/session state locally
  • Reports summaries, outputs, and artifacts back to the orchestrator

Start it with:

autopilot worker start

For local development, autopilot start still exists as a convenience shortcut that boots both processes.

Repo-authored config

Autopilot policy lives in .autopilot/ and stays reviewable in git:

.autopilot/
├── company.yaml
├── project.yaml
├── agents/
├── workflows/
├── environments/
├── providers/
└── handlers/

That keeps workflows and operator policy:

  • versioned
  • diffable
  • branchable
  • editable without a separate admin UI

Truth boundaries

Use this mental model when deciding where something belongs:

PlacePut here
Repo filesystemAuthored config and reviewable policy
Orchestrator DB/APIShared operational state and durable artifact metadata/content
Worker-local stateRaw transcripts, local sessions, worktrees, resolved secrets

This is the key architectural boundary: the orchestrator owns shared truth, while workers own machine-local runtime reality.

Execution flow

The normal path is:

  1. A task is created
  2. A workflow attaches and selects the current step
  3. The orchestrator creates a run
  4. A worker claims the run
  5. The worker executes through its runtime adapter
  6. The worker reports summary, outputs, and artifacts
  7. The orchestrator stores results and advances the workflow
  8. If the next step is human_approval, the task blocks until an operator acts

This is intentionally explicit. Autopilot is not hiding a giant chat loop behind the scenes.

Workflow I/O

Workflows declare step outputs directly in YAML. The engine adds the machine-readable output suffix automatically, then routes using named output fields.

Current capabilities:

  • explicit next
  • ordered transitions
  • on_approve, on_reply, on_reject
  • source-run summary forwarding
  • explicit input.artifacts

That is enough for plan/review/implement loops without turning the workflow engine into a rules platform.

Runtime adapters

Autopilot does not ship its own AI runtime. Workers execute runs through adapters that wrap existing AI tools you already have installed and subscribed to.

The adapter model works like this:

  1. The worker resolves a binary on the host machine (e.g. claude, codex, opencode)
  2. The adapter spawns that binary as a subprocess with the run's prompt and instructions
  3. The adapter feeds the run context (task, instructions, MCP config) to the subprocess
  4. The subprocess does the actual AI work using your existing subscription
  5. The adapter parses the result back into Autopilot's structured format (summary, outputs, artifacts)

This means:

  • No new AI vendor. Autopilot reuses the AI tools and subscriptions you already pay for.
  • No API key management for models. The adapter delegates to the CLI tool, which handles its own auth.
  • New runtimes are just new adapters. Adding Codex or OpenCode support means implementing the same start → parse → return contract against a different binary.

Today: Claude Code

The shipping adapter spawns the claude CLI. It supports:

  • One run per worker at a time
  • Per-run git worktrees for isolation
  • Structured outputs and artifacts
  • Session resumption via local session refs (for same-worker continuation)
  • MCP integration — the worker injects Autopilot's task/run tools so the AI can inspect and create tasks during execution

Works with any Claude plan that includes CLI access (Pro, Team, Enterprise).

Codex, OpenCode

The same adapter model applies to Codex and OpenCode. The worker spawns codex or opencode instead of claude, feeds the same RunContext, and parses the result back into the same structured format.

The adapter interface is intentionally minimal — start(context), onEvent(handler), stop(). Adding a new runtime means:

  1. Map the runtime kind to a binary name
  2. Build the CLI arguments from the RunContext
  3. Parse the output into RuntimeResult

Worker routing, capability advertisement, and run targeting already support multiple runtimes per worker. You can run a Claude Code worker and a Codex worker side by side, and the orchestrator routes runs based on the required_runtime field in workflow steps.

Durable previews

Preview URLs are orchestrator-backed, not worker-hosted.

Current flow:

  1. The worker collects previewable files from the run worktree
  2. Those files are sent back as preview_file artifacts
  3. The orchestrator stores them durably
  4. The orchestrator serves them via /api/previews/:runId/*path
  5. A preview_url artifact points to the entry page

That means previews survive worker shutdown. If the worker laptop goes offline, the orchestrator can still serve the preview.

Important: preview URLs are not automatically public. They are served through the orchestrator's normal access model.

Pack distribution

Reusable integration material — providers, handlers, workflows, skills, context — is distributed through packs.

  • Desired packs are declared in .autopilot/company.yaml
  • Packs are resolved from git-backed registries
  • autopilot sync materializes pack files into .autopilot/ and writes a lockfile
  • Installed files are normal repo config — editable, reviewable, version-controlled

This keeps integrations installable without hardcoding them into the core. See Packs and Distribution for the full model.

Providers, handlers, and surfaces

Autopilot extends through a provider/handler model:

  • Providers are authored YAML under .autopilot/providers/ — integration instances that declare capabilities and secret refs
  • Handlers are Bun scripts under .autopilot/handlers/ — executable adapters that do protocol-specific work
  • Surfaces are human-facing channels (Telegram, Slack, email) built over providers, handlers, and conversation bindings
  • The orchestrator invokes handlers with typed envelopes, validates results, and executes the real primitives

Current operations:

OperationPurpose
notify.sendSend an outbound notification
intent.ingestTurn inbound payload into task creation
conversation.ingestTurn inbound conversation payload into task actions

Surface integrations arrive as packs, not hardcoded features. See Providers and Handlers for the extension model and Telegram Surface for the first real example.

Security model

Auth and verification live at the orchestrator boundary:

  • Inbound webhooks are verified by provider-declared auth_secret refs
  • Surface-specific headers (e.g., Telegram's X-Telegram-Bot-Api-Secret-Token) are recognized natively
  • Generic providers use X-Provider-Secret for webhook auth
  • Workers authenticate via join tokens during enrollment
  • Better Auth capabilities are reused for session management and OAuth flows where they fit

Handlers normalize provider-specific details but do not invent private auth subsystems. Webhook signatures, headers, and verification steps are always explicit and inspectable in the provider config and handler code.

Provider secrets are declared as references, not values. The orchestrator resolves them at handler invocation time and passes only the scoped subset needed for that operation.

Async operator model

The current product is still CLI-first.

The intended async loop is:

  1. A task or run reaches an actionable state
  2. An operator is notified out of band
  3. The operator inspects via CLI or a bound external conversation
  4. The operator replies, approves, or rejects
  5. The workflow continues

Current operator surfaces:

  • autopilot inbox and autopilot inbox --watch
  • autopilot tasks approve|reject|reply
  • autopilot runs show
  • durable preview_url artifacts
  • optional provider-driven notifications and conversation bindings

That is the current architecture in practice: control plane on the orchestrator, execution on workers, and a CLI-first async loop over explicit workflow primitives.

For deployment topology, multi-worker patterns, and the cloud-first model, see Cloud and Deployment.

On this page