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. For what each field means, see Agent harnesses.
Add a harness
- Create
$KRAFT_HOME/templates/harnesses/mytool.yaml(~/.kraft/templates/harnesses/by default). Make the directory if it doesn't exist. The file name's stem must equal theid. - Start with the three required capabilities:
id: mytool # must match the file name's stem kind: cli # the only kind implemented command: [mytool] # argv prefix capabilities: prompt: { cli: ["-p", "{value}"] } context: { channel: prompt } # or: { channel: system_prompt, cli: [...] } usage: { source: result_file } # or: { source: envelope, reader: <parser name> } - Add each optional capability the CLI supports (
model,effort,permission_mode, and so on) with thecli:fragment that sets it. Leave out what the CLI can't do. A task that asks for a capability you left out is rejected at load, pointing at this file. - Add a profile for the harness in
~/.kraft/templates/harnesses.yaml, then select it from a task. The profile'sprovideris your harnessid:harnesses: mytool: provider: mytool enabled: true executable: mytool
Inlibrary.yaml, a task that should run on it setsharness: mytool. See the harnesses file for every profile field. - Reload the templates so a running server rereads them:
kraft admin reload
Verify
Run the install check:
kraft admin doctor
Expect a PATH row for your harness once a chain selects it, and no load
error for your file. A load error names the file and the field to fix. To see
which library tasks select each harness profile, run
kraft admin harnesses.
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 whole, so start from the shipped definition,
src/kraft/harnesses/claude.yaml
(one file per harness), and change only what you need, such as claude's
--model allowlist.
Verify with kraft admin doctor, as above.
Set up harness credentials
A worker has no one to answer a login prompt, so give each CLI credentials it can use without one.
Each CLI is covered in more detail in Agent harnesses. The steps here are the short path.
Amp
- On a machine where you ran
amp login, do nothing more. The login lives under your home directory, which a worker keeps. A sandboxed repository never sees it: its workers get a home of their own, so use steps 2-4. - Elsewhere, create an access token (
sgamp_...) at ampcode.com/settings. - Name
AMP_API_KEYin the repo'senv_passthrough, because a worker's environment is an allowlist:# repos.yaml repos: - path: /path/to/repo env_passthrough: [AMP_API_KEY] - Export
AMP_API_KEYin the shell that starts the Kraft server, then restart the server.
Cursor
- On a machine where you ran
agent login, do nothing more. The login lives in the OS keychain, which a sandboxed worker cannot reach. - With an API key instead (the only way under a sandbox), name
CURSOR_API_KEYin the repo'senv_passthrough, export it in the shell that starts the server, and restart the server.
Antigravity
- On the machine that runs Kraft, run
agyonce in a terminal and sign in with your Google account. A headless run never signs in by itself: it needs that cached sign-in. The tokens live in the OS keychain and the CLI's state under~/.gemini/antigravity-cli/, both of which a worker keeps. A sandboxed worker reaches neither, and Kraft has not run Antigravity in a sandbox. - With a Gemini API key instead, set
"modelProvider": "gemini"in~/.gemini/antigravity-cli/settings.json, nameGEMINI_API_KEYin the repo'senv_passthrough, export it in the shell that starts the server, and restart the server. This path is untested in Kraft.
Verify
File a small work item with a task on the harness, or run the CLI's own headless command by hand as the same user. Without credentials, Amp prints a device-login prompt and waits about five minutes for a browser before it exits 1, so a hang on that prompt means the credentials didn't reach the worker.