nextv2.0.0
Agents and harnesses

Switch a task to another harness

Run some or all of a chain's agent tasks on Codex, Cursor, OpenCode, Gemini, Antigravity or Amp instead of Claude Code, and what changes when you do.

Every agent task Kraft ships runs on Claude Code. Move tasks to another agent CLI, which Kraft calls a harness, and end with a chain that runs on it. The examples use Codex. The steps are the same for the other shipped harnesses.

The harness is a property of the task in your templates. There is no per-item harness switch: kraft item set-overrides changes the model and effort only. To run one item on another harness, give it a chain that sets the harness, as in step 3.

Before you start

  • The CLI is installed, on the PATH of the shell that starts Kraft, and logged in. Give a worker its login has each harness's login.
  • You have read the harness's row in the comparison table. It shows what that CLI cannot do, and whether it reports a dollar cost.
  • For Gemini models on an individual Google account, use antigravity, not gemini: see Gemini details.

1. Add the harness profile

A task names a harness profile from $KRAFT_HOME/config/harnesses.yaml, not a CLI. The shipped file has two harness profiles, claude and codex:

config/harnesses.yaml
harnesses:
  codex:
    provider: codex
    enabled: true
    executable: codex
    defaults:
      effort: medium

For another shipped harness, add a harness profile the same way, with provider set to its id (cursor, opencode, gemini, antigravity or amp). See harnesses.yaml.

2. Give each agent profile a model for the new provider

A task with profile: strong gets its model from the profiles: section of the same file, keyed by provider. These are agent profiles, the model tiers.

The shipped strong and deep agent profiles name a Codex model. fast does not, so a fast task on Codex cannot start. No shipped agent profile names a model for the other harnesses.

Add the provider to each agent profile a moved task uses before you move it. The shipped implementer uses strong, so moving it to Antigravity needs one more line in the shipped providers: block:

config/harnesses.yaml
profiles:
  strong:
    providers:
      claude: { model: sonnet, effort: high }
      codex: { model: gpt-5.6-terra, effort: high }
      antigravity: { model: gemini-3.8-flash, effort: high }

Keep the providers: shape. A model: or effort: beside providers: is refused, and an unreadable harnesses.yaml stops every agent task. See Agent profiles.

Amp takes no model, so a task on Amp sets effort: itself instead of an agent profile.

3. Pick which tasks move

List the tasks each harness profile runs:

kraft admin harnesses
kraft admin harnesses claude

Then choose how far the change reaches:

  • Every chain. Change harness: claude to harness: codex on the tasks you want to move in library.yaml. Every chain that extends them follows.
  • One chain. Leave the library alone and override the task in the chain file. A key set next to extends wins over the library's:
    config/chains/codex-impl.yaml
    id: codex-impl
    nodes:
      - id: implementation
        kind: exec
        tasks:
          - id: implement
            extends: implementer
            harness: codex
    
  • One item. File it on a chain like that one, with kraft item create "title" --chain codex-impl. To switch an item that has not started, run kraft item set-chain ID --chain codex-impl.

Kraft's own kraft: skills, such as kraft:code-review, are sent to the agent in its instructions, so they work on any harness. A skill from another plugin (plugin:skill) needs that plugin installed for the new CLI. If it cannot load, the task stops and asks for it.

4. Load it

kraft admin templates lint
kraft admin reload

If an agent profile has no model for the new provider, lint reports it. Go back to step 2:

chains/codex-fast.yaml:1:1: chain 'codex-fast' task 'implementation.main.implement': profile 'fast' has no model for provider 'codex' (harness 'codex')

Check it worked

kraft admin harnesses
kraft admin templates show codex-impl --resolved
kraft admin doctor
  • kraft admin harnesses lists the moved library tasks under the new harness profile, and in its CHAINS column every chain that selects it, a chain-level override included. For the one-chain example above, kraft admin harnesses codex prints:
    id          codex
    provider    codex
    enabled     yes
    executable  codex
    defaults    effort=medium
    used by     no library task
    chains      codex-impl
    
  • show --resolved prints harness: codex on each task you moved.
  • kraft admin doctor has an agent: codex row once a chain selects the harness profile. It fails when the executable is not on PATH, naming the chains that cannot run without it.

File a small item on the chain. kraft view show ID shows its token count, and no dollar figure when the harness reports none, once a session has run. Harnesses that report no cost says how the caps then count it.

If the item stops

The harness is not allowed

If allowed_harnesses is set, it must include the new harness profile. It can appear in policy.yaml under defaults: or maxima:, in a repo's policy: in repos.yaml, or in a chain, node or task policy:. Otherwise Kraft refuses the item when you file it:

kraft: 422: policy.allowed_harnesses: implementation.main.implement: harness 'codex' is not in its allowed_harnesses ['claude']

Add the harness profile to the list. Skip this if nothing in your policy sets allowed_harnesses.

A tool list blocks the launch

An allowed_tools or deny_tools list in the task's policy can stop the new harness from launching:

  • Kraft refuses to launch a gemini or antigravity task under any allowed_tools or deny_tools list, because those CLIs cannot restrict tools.
  • Kraft refuses a codex task whose allowed_tools leaves out WebSearch, or whose deny_tools names it: the permission hook never sees Codex's web search.
  • Kraft refuses a cursor task whose allowed_tools leaves out WebFetch or WebSearch, or whose deny_tools names either, for the same reason.

The refusal happens at launch. The item stops and waits for you, and the stop reason names the harness and the missing tools. Add the tools to the list, or keep that task on Claude. See Policy fields and, for each harness's refusals, the Permission gate.

Move escalation turns too

An escalation turn runs on claude unless policy says otherwise. To move it too, set escalation_harness in policy.yaml:

config/policy.yaml
defaults:
  escalation_harness: codex   # or `item`: the harness the item's last agent task ran on

Next steps

Copyright © 2026