Integrations

Running Claude Code as a dispatched agent

3 min read

Claude Code is the agent DevPilot runs today. It executes on your machine, and the hosted plane never sees your repository — it dispatches an issue and receives status back.

How that dispatch works is decided by the orchestrator adapter, which has four modes:

export type OrchestratorMode = 'claude-session' | 'http' | 'ao-cli' | 'disabled';

claude-session — the default

Session-native dispatch. The orchestrator spawns or resumes a managed Claude Code session and receives progress through pushed callbacks rather than polling.

The two words carrying weight there are resumes and callbacks.

Resuming matters because a dispatched task is not always a fresh start. A session that already has context on a repository — files it has read, decisions it has made — is worth continuing rather than recreating, and recreating it means paying to re-establish context that existed a minute ago.

Callbacks rather than polling is the more consequential difference, and it is worth understanding why the legacy mode worked the other way.

Why polling was replaced

ao-cli shells out to the ao CLI and scrapes ao status on a poll loop. It is explicitly retained for backward compatibility and explicitly superseded.

Scraping a status command has three problems that compound. You learn about state changes one poll interval late, so a fast task can start and finish between polls and appear never to have run. You are parsing human-readable output, so a formatting change in the upstream tool breaks your integration silently. And you pay for the polling whether anything is happening or not — a hundred idle agents is a hundred pointless subprocess invocations a minute.

Pushed callbacks invert all three: the agent reports when something changes, the payload is structured, and idle costs nothing.

There is a live example of the second failure mode in this repository. The ao-cli adapter was written against a format that no longer exists — ao list and ao status <id> are both gone, and ao spawn no longer takes a prompt. The adapter now throws with an actionable message rather than pretending to work. The test harness that had been "passing" was checking the adapter against a fake that spoke the format the adapter expected, which confirmed our internal consistency and nothing about the world.

http — bring your own orchestrator

Dispatch to a remote orchestrator over HTTP. This is the extension point: the wire contract is published under MIT as @devpilot.sh/bridge-protocol, so anything that honours those shapes can receive dispatches. DevPilot neither knows nor cares that it is not ours.

Worth a caution learned the hard way — "speaks HTTP" is not a contract. A service that exposes different paths than the adapter calls will fail in confusing ways rather than obvious ones. Check the shapes, not the protocol.

disabled

No orchestrator. Useful when running the CLI purely locally, and worth having as an explicit mode rather than an absent configuration, because "no orchestrator" and "orchestrator misconfigured" should not look the same.

What this does not do

DevPilot does not modify Claude Code, wrap its prompts, or interpose on its reasoning. It decides what gets dispatched and where, and reads back status. The agent's behaviour is the agent's.

It also does not currently let you watch a dispatched session work. Today the runner keeps the result envelope — cost, tokens, files touched — and the reasoning is gone when the process exits. That is a real limitation and it is the orchestrator's known gap rather than a design preference.

Practical notes

Claude Code is the only agent wired today. The adapter interface exists so others can be added, and that work happens in the open source repository — but "planned" and "shipped" are different words and this page will keep them separate.

Concurrency is controlled separately from the adapter: there are two independent limits, one protecting your machine and one protecting the plan from itself.