Harness as config (answer first)
A harness is the coding agent that executes your worker's task
— Claude Code, Codex, and their successors. On this platform it is selected by
a single field. When you create a
cog (a managed task
worker), you write the task in plain language and set
"harness": "claude-code". Everything else about the worker — its
trigger, its box, its tool grants, its autonomy limits, its run history — is
harness-independent. Swapping brains is editing one field, not migrating a stack.
# The harness is one line of the worker's record POST /api/cogs { "name": "changelog-writer", "task": "Summarize this week's merged PRs into CHANGELOG.md and open a draft PR.", "harness": "claude-code", # the swappable part "target_sandbox_id": "sandbox_ab12cd34", "trigger": { "cron": "0 17 * * 5" } } GET /api/cogs/harnesses # the registry: what runs today, what is coming
Under the hood there is no proprietary runtime to be loyal to. The platform renders
the harness's own headless command — for Claude Code, claude -p
with your task delivered through the environment — as a plain step on your own
box, via the same
workflow engine that
installs everything else. The harness is a given; the machine and the management
around it are the product.
Why portability matters more every quarter
Because the frontier does not hold still, and your leverage depends on being able to follow it. The best agent for a given job flips with each model generation; pricing moves; a vendor has an outage the week your quarter closes; procurement standardizes on a different provider. None of those events should be a rewrite. An operator who encoded fifty jobs inside one vendor's agent ecosystem renegotiates from a position of weakness. An operator whose fifty jobs are harness-independent records re-points them.
| Worker built inside one vendor's stack | Worker with harness as config | |
|---|---|---|
| A better model ships | Evaluate a migration project | Edit one field on the workers you choose |
| Where the job is defined | Vendor-specific format, vendor's cloud | Plain-language task in a record you own |
| Run history and audit | Lives with the vendor | Lives with the platform, spans harness changes |
| Safety rails (budget, draft-not-push, timeout) | Per-vendor, re-learned each time | Platform-level, identical across harnesses |
| Negotiating position | Locked in | Portable |
This is the same argument that made teams keep CI definitions in their own repos rather than inside a vendor's UI, one abstraction later. The job outlives the tool that executes it — so the job's definition should live with you.
What stays, what swaps
The clean split is the whole design. When a new harness becomes available, here is
the migration checklist for an existing worker: change the harness
field. Everything in the left column below is untouched.
| Stays (yours, portable) | Swaps (the harness's) |
|---|---|
| The task, in plain language | The headless run command |
| The trigger: cron, webhook, on-demand | Which model key it reads |
| The box it runs on, and its workspace | The agent's internal loop and toolformer style |
| Tool grants (MCP servers), delivered per run | — |
| Autonomy defaults: draft-not-push, dry-run first, budget, timeout | — |
| The runs view and its full history | — |
A worked example: your Friday changelog cog has run on Claude Code for six months. Codex becomes available and benchmarks better on your codebase. You change one field on one worker, watch two runs side by side in the same runs view you have always used, and either keep it or change it back. That is the entire cost of trying a new brain: one field, two runs, a comparison.
Model-key sovereignty
Portability is hollow if a vendor holds your credentials. Here the model key is your key, on your box: delivered off-band into a root-owned secret file that the harness reads at startup — never a command-line argument, never a log line, never a value stored in the worker's record. You pay your model provider directly for inference; the platform never proxies your tokens through its own account, so switching providers is switching which of your keys sits on the box.
Tools travel with the worker, not the harness
The other half of portability is that a worker's capabilities are granted through an
open protocol, not a vendor's plugin system. Tool grants are MCP servers — the
cross-vendor standard that Claude Code, Codex, and the rest of the modern harness
generation all speak. Grant a worker acp-mcp and it can
coordinate with its team;
grant it your action gateway and it reaches your connected systems. Those grants are
properties of the worker, delivered to the box per run as locked-down
configuration — so when the harness changes, the toolbelt follows the worker
automatically.
The honest roadmap
What runs today, and what is registered but not yet live — the harness registry tells you the truth rather than faking availability:
| Harness | Status | Notes |
|---|---|---|
claude-code | Available now | Headless claude -p, your Anthropic key on your box; the proven path end to end |
codex | Registered, coming soon | Selecting it returns an honest "not yet available" — not a silent fallback |
hermes | Registered, coming soon | Same contract |
pi | Registered, coming soon | Same contract |
The registry existing before the harnesses do is the point, not an embarrassment: the seam is built, tested, and holding a real harness today, so each addition is a new entry behind a stable field — not a re-architecture. Define the job once, keep the keys on your box, and let the brains compete for it.