Add or override a harness
Add a new agent CLI to Kraft, or change how a shipped one is launched, by dropping a YAML file into a directory. No Python change and no Kraft release are involved. At the end, a chain task runs on your harness.
Before you start
- The CLI is installed, on the
PATHof the shell that starts Kraft, and you can run it headless by hand. - You know its flags for a prompt, and for each option you want Kraft to set (a model, an effort, a permission mode).
- You know how it reports tokens: in a log one of Kraft's readers parses, or in a file the agent writes.
Add a harness
- Create
$KRAFT_HOME/config/harnesses/mytool.yaml(~/.kraft/config/harnesses/by default). Make the directory if it does not exist. The file name without.yamlmust equal theid. - Start with the three required capabilities:config/harnesses/mytool.yaml
id: mytool # must match the file name without .yaml kind: cli # the only kind implemented command: [mytool] # the command and its fixed arguments capabilities: prompt: { cli: ["-p", "{value}"] } context: { channel: prompt } # or: { channel: system_prompt, cli: [...] } usage: { source: result_file } # or: { source: envelope, reader: <parser name> }
Capabilities defines each one and thechannel,sourceandreaderkeys. - Add each optional capability the CLI supports, with the
cli:fragment that sets it. Leave out what the CLI cannot do. A task that asks for a capability you left out is rejected at load, pointing at this file. For a CLI with--modeland--effortflags, add these two lines undercapabilities::config/harnesses/mytool.yamlmodel: { cli: ["--model", "{value}"] } effort: { cli: ["--effort", "{value}"], values: [low, high] } - Add a harness profile for the harness in
~/.kraft/config/harnesses.yaml. The profile'sprovideris your harnessid. Seeharnesses.yamlfor every profile field.config/harnesses.yamlharnesses: mytool: provider: mytool enabled: true executable: mytool - In
library.yaml, setharness: mytoolon a task that should run on it. - Reload so a running server rereads
library.yaml:kraft admin reload
Kraft readsharnesses.yamland the harness file again at every agent launch, so those two need no reload.
Override a shipped harness
Use the same steps, with a file named after a shipped harness: claude.yaml, codex.yaml, cursor.yaml, opencode.yaml, gemini.yaml, antigravity.yaml, or amp.yaml.
Your file replaces the shipped one entirely. Copy the shipped definition from src/kraft/harnesses/ (one file per harness) and change only what you need. For example, edit claude.yaml to change which effort values it allows.
Check it worked
kraft admin doctor
Once a chain selects your harness profile, the output has an agent: mytool row that gives the path where Kraft found the executable. Kraft pads the name column to the widest check name:
ok agent: mytool /usr/local/bin/mytool
- A failing
harness: mytoolrow means your file did not load. Its detail names the file and the field to fix. kraft admin harnesseslists the library tasks that select each harness profile.- File a small work item on a chain that selects the harness profile, and confirm the task runs on it.
- If the task cannot log in, give the CLI credentials a worker can use. Give a worker its login has each harness's login, and how to check a worker can log in.
Next steps
- Harness definition files: every field of the file you wrote.
- Switch a task to another harness: move tasks to a harness, including the model tiers each needs.
- Agent harnesses: the seven shipped harnesses, to copy a definition from.
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.
Build a worker Kit
Build a Docker Sandbox Kit for Kraft's Claude workers, push it to your registry, and run a repository's sandbox from it, pinned by digest.