toryo docs
Documentation navigation

Harnesses

A harness is the coding agent that does the work. toryo drives one; it is not one. Four are supported: Claude Code, Codex, GitHub Copilot and Cursor.

You bring your own, signed in under your own account. toryo licenses toryo and takes no margin on model usage, which is also why switching harness changes nothing about what you pay us.

They are not equivalent, and toryo does not pretend they are#

Every harness declares what it can and cannot do, feature by feature, and toryo asks that declaration rather than assuming. A step that needs something a harness lacks is refused where it was configured, not discovered halfway through a run.

The gaps worth knowing before you choose:

CapabilityClaude CodeCodexCopilotCursor
Enforcing a tool deny listyesemulatedemulatedyes
MCP serversyesyesyesyes
Streaming progressyesemulatedyesyes
Reporting usageyesemulatedyesyes
Estimating costyesyesyesyes
Structured JSON outputyesnonono
Execution modesyesnonono
Subagentsyesnonono
Context optimizationemulatedemulatednono
Cancelling a runyesyesyesyes
Continuing an earlier sessionyes (print, completion)nonono

Emulated means toryo delivers the outcome the harness does not offer natively, by doing the work itself. The result is the same; the mechanism is toryo's rather than the harness's.

Claude's compact column represents interactive, print, and completion modes in the generated matrix. All three support execution-mode selection, but only completion provides structured output and only interactive provides an interactive session. Codex, Copilot and Cursor do not expose that execution-mode family.

A Claude Code session runs at most three subagents at once by default. The agents a Claude Workflow starts count toward that limit, though a workflow started beside running subagents can exceed it. The Worker setting maxSubagents changes that (0 removes the limit).

A retry does not resume: a failed step restarts from the beginning rather than picking up inside the session that died, on every harness. A dispatch job can ask to continue an earlier Claude Code session by id, in print and completion modes only; the shipped sequences do not use it.

Cost has three sources: Claude can report its own figure; newly completed Codex and Copilot jobs on known priced models receive an API-equivalent token estimate; and Cursor jobs are priced against Cursor's own published per-token rates, which is what it genuinely bills usage-based against a request pool, so that figure is closer to a real charge without being one (it models neither the allowance a seat starts with nor team surcharges). No estimate is a subscription charge or a Copilot AI-credit balance. Unknown models omit it, and old jobs are not backfilled.

Claude estimates price Opus 5 and Sonnet 5 at their own published rates, and bill one-hour cache writes at the one-hour rate.

Cursor's usage gauge is a different mechanism from that job-cost estimate. It reads included-plan utilisation, the Cursor-models and other-models buckets Cursor's Plan & Usage pane shows, plus an on-demand budget and headroom when the account configures a cap, from the undocumented, unversioned dashboard Connect RPC authenticated by the signed-in Cursor desktop session on macOS. This is not an official personal-usage API. Missing or expired credentials and endpoint or response changes make the reading unavailable rather than zero.

The table above is the short version. toryo generates the precise matrix from the code itself, so if a run is refused for a capability reason the message names the feature and the harness rather than leaving you to guess.

Choosing which ones this machine offers#

Most people run one or two. Offering all four in every picker, and letting a job queue against a harness whose CLI was never installed, is worth turning off:

toryo worker settings set --provider-codex false

One switch per harness, all on by default. Board has the same switches on the Settings screen.

Two rules hold this together:

  • At least one stays on. A write that would leave none is refused, as is one that turns off the harness your default names. A machine in either state accepts no work at all, and the failure would otherwise surface job by job rather than where you configured it.
  • A job naming a disabled harness is refused when you queue it, with the flag that re-enables it named in the message. Not three steps into the run.

toryo sequence validate warns about the same thing earlier: a sequence whose steps name a harness this machine has switched off draws a warning naming the steps. It is a warning rather than a failure, because which harnesses a machine offers is a property of the machine and the file may be perfectly good on a colleague's.

Picking a harness per step#

A sequence step can name the harness it wants. code-task exposes this for each of its five agent roles, so planning can run on one harness and implementation on another. It is a providers object in the run input, keyed by role:

{
  "brief": "...",
  "workingDir": "ABSOLUTE_REPOSITORY_PATH",
  "branchName": "feat/thing",
  "baseBranch": "main",
  "maxImplementAttempts": 3,
  "providers": {"plan": "claude", "implement": "codex"}
}

Replace ABSOLUTE_REPOSITORY_PATH with the absolute path to your repository before submitting this input.

The five roles are plan, implement, selfReview, review and reflect. Any role you leave out runs on Claude Code. Board's run form offers the same choice as a set of pickers, so this is only the shape if you are launching from a terminal with --input.

Each picker also accepts harness:model, which pins the model for that role. A bare harness keeps the role's default model. Unsupported pairs are rejected by the run input before a worker starts.

code-task's pickers include claude-opus-5, claude-opus-5[1m] and claude-sonnet-5. Board's enqueue and schedule forms also list any model a harness's own catalog reports, so a model its vendor shipped after your toryo build is selectable there; the code-task pickers stay limited to the models code-task names.

review-task and research-task take a single provider for the whole run. Choosing cursor there now runs on Cursor; before v1.2.0 it quietly ran on Claude Code.

Your own sequences can do the same, and can go further: a step can decide its harness from the run's own input, so a field you fill in at launch picks it. See Writing your own sequences.

Outside a sequence, a job that names no harness uses this machine's default, and a default that names nothing resolves to the first harness you have left enabled.

Where the work runs#

Every agent session runs inside its own tmux session on your machine, whichever harness it is. That is what lets a long task keep going after you close the window, and lets you attach to a running one. Nothing is uploaded and no session runs in a cloud sandbox.

What a Claude Code worker loads#

A worker session does not load your personal Claude Code configuration: not ~/.claude/settings.json (its model, effort level, hooks, plugins, env and apiKeyHelper), not ~/.claude/CLAUDE.md or ~/.claude/rules, and not your user-level or claude.ai MCP servers. It does load the target repository's .claude/settings.json, .claude/settings.local.json and .mcp.json, plus toryo's own hooks and tools. A sequence that depends on your personal setup can set userConfig: inherit in a step's llm block to load it as before.

Harnesses are also MCP clients#

The same four programs are places toryo's own tools can be installed, which is a separate question from which one runs your jobs. A machine can drive work on Claude Code while also exposing toryo's tools inside Codex. See MCP.

Cursor is both: a dispatch harness and an inbound MCP client. Claude Desktop is inbound only, so it can search Brain and steer work while dispatch cannot queue a worker session on it.

Where things go wrong#

  • A job is refused at the queue naming a harness. That harness is switched off on this machine. The message names the flag.
  • A Claude job cannot authenticate or misses a tool it had before. Workers no longer read ~/.claude/settings.json, so an apiKeyHelper or env value set there does not apply, and user-level MCP servers are excluded too. Move settings into the repository's .claude/settings.json and MCP servers into its .mcp.json, or set userConfig: inherit.
  • Cost is blank on a job. Its model is unknown to the pricing table, it predates estimation, or the harness supplied no usable usage.
  • A capability you expected is missing. Check the table above before assuming a bug. Structured output, subagents and execution modes are exclusive to Claude Code.
  • A run failed and restarting resumes nothing. Expected: a retry never resumes. Use retry, which keeps the run's worktree, PR and history.

Full command surface: CLI & contract reference.