Harness customization
Customize a CLI coding harness (Claude Code, Codex, Cursor, Aider) from the agent config.
Sandbox agents that run a CLI coding harness (run_command such as claude -p, codex exec, cursor-agent, or aider) can include an optional harness_config JSON object in agent configuration. The platform detects harness type from the run command binary and applies each supported key through native integration, including flags, config files, and target locations.
Leave it blank for a completely off-the-shelf harness.
What the platform sets up automatically
For a recognized harness, the platform preconfigures execution so minimal commands work without repeated boilerplate:
-
Headless and approval flags are appended automatically unless already provided:
Harness Appended flags Claude Code --print+--dangerously-skip-permissionsCodex --dangerously-bypass-approvals-and-sandboxAider --yes-alwaysCursor --forceExample complete commands: claude -p "$(cat $PIPELINES_TASK_FILE)" codex exec "$(cat $PIPELINES_TASK_FILE)"
-
Codex authentication is prewired. OPENAI_API_KEY is aliased to CODEX_API_KEY, and CODEX_HOME (~/.codex) is created and pinned when trajectory capture is enabled (default behavior). No auth.json prefix or manual export is required.
An unrecognized run command, meaning command position does not resolve to claude, codex, cursor-agent, or aider, still runs but loses harness integration. Trajectory falls back to generic command and file-write capture with no rich transcript. All harness_config keys, all mcp_servers entries, and platform tools are skipped. If a wrapper script invokes a supported CLI, place the CLI binary directly in run command to retain rich tracing and injection behavior.
{
"system_prompt_append": "Prefer small, focused diffs. Never touch CI config.",
"project_doc": "This repo is a FastAPI monolith; tests live in tests/.",
"subagents": [
{
"name": "reviewer",
"description": "Reviews diffs for correctness before finishing.",
"prompt": "You are a strict reviewer. Reject changes without tests.",
"tools": ["Read", "Grep"]
}
],
"mcp_servers": {
"notion": {
"command": "npx",
"args": ["-y", "@notionhq/notion-mcp-server"],
"env": { "NOTION_TOKEN": "…" }
},
"internal-api": {
"url": "https://mcp.example.com/mcp",
"type": "http",
"headers": { "Authorization": "Bearer …" }
}
},
"register_platform_shim": true,
"files": {
"home": { ".config/myharness/settings.json": "{\"telemetry\": false}" }
}
}Keys at a glance
| Key | Type | Harnesses | What it does |
|---|---|---|---|
| system_prompt_append | string | all | Extra system prompt text appended to harness instructions. |
| project_doc | string | all | Project guidance combined with system_prompt_append in the same instruction channel. |
| subagents | list | Claude only | Claude Code subagent definitions passed through --agents. |
| mcp_servers | object | Claude, Codex, Cursor | Additional MCP servers registered with the harness. |
| register_platform_shim | boolean | Claude, Codex, Cursor | Controls platform-tool MCP shim registration. Omit for automatic behavior. |
| files | object | all (even unrecognized commands) | Writes arbitrary files into the sandbox before run start. |
| hooks | object | none | Accepted but reserved. Currently dropped with a warning at dispatch. |
Unknown keys are rejected at save time. Total harness_config size must remain under 256 KB, including files content. subagents is capped at 32 entries and mcp_servers at 16 entries.
Instructions: System Prompt Append and Project Doc
Use system_prompt_append for behavior that should hold on every run for this agent, such as edit style, test expectations, or forbidden files. Use project_doc for repository context, and keep it short: the seeded repository may already carry its own docs, so this field should fill gaps rather than replace them.
Both keys are free-text strings. At dispatch they are joined, separated by a blank line, into one instruction text and delivered through each harness's native channel:
| Harness | Where it lands |
|---|---|
| Claude Code | A platform file outside the repository, passed with --append-system-prompt-file. No CLAUDE.md is written into workspace. |
| Codex | ~/.codex/AGENTS.md, outside the repository. |
| Cursor | .cursor/rules/_pipelines.mdc with alwaysApply: true. This file is inside workspace and appears in graded diff, with warning. |
| Aider | A conventions file outside the repository, passed with --read. |
If the run command isn't a recognized harness, these keys are skipped with a warning (a bespoke CLI has no known instruction channel).
Subagents (Claude Code only)
Each entry requires non-empty name, description, and prompt. name must match the pattern [A-Za-z0-9_-]+ and remain unique. Optional keys are tools, which is the list of permitted Claude tools, and model.
{
"subagents": [
{
"name": "test-writer",
"description": "Writes failing tests for reported bugs.",
"prompt": "Write the minimal failing test first. Never fix the bug yourself.",
"tools": ["Read", "Grep", "Write"],
"model": "haiku"
}
]
}Entries are passed to Claude Code through the inline --agents JSON flag. On other harnesses, subagents is dropped with a dispatch warning.
MCP Servers (Claude, Codex, Cursor)
This key is a map from server name to server definition. Names must match [A-Za-z0-9_-]+. The name pipelines is reserved for the platform shim. Each definition must be exactly one of the following:
- Stdio, with command and optional args and env fields.
- Remote, with url and optional type and headers fields. type defaults to http.
How each harness receives them:
| Harness | Mechanism | Caveats |
|---|---|---|
| Claude Code | Merged JSON config passed with --mcp-config | none |
| Codex | mcp_servers tables in ~/.codex/config.toml | Remote servers must be streamable HTTP. type set to sse is skipped with warning. |
| Cursor | Global ~/.cursor/mcp.json plus --approve-mcps | Registered globally, not project-level, so tokens stay out of graded diff. |
| Aider | none | No upstream MCP support. mcp_servers is dropped with warning. |
Platform tools and Platform Shim
Tools attached in the Tools step reach the harness through one path: a platform-managed MCP server named pipelines, referred to as the shim. This is a small stdio server bundled into the sandbox. Run-scoped credentials are passed through server env, never via command line, and tool calls route through the per-run proxy using simulated or passthrough execution modes.
register_platform_shim controls shim behavior:
- omitted, automatic mode: shim registers only when tools are attached.
- false: never register, even when tools are attached.
- true: always register. On Aider or unrecognized commands this is not supported and emits warning.
Registering the shim is not a substitute for attaching tools. A shim with an empty tools schema gives the harness nothing to call, so Tool Calls can still be zero. Declare the workspace tools as well.
A customer mcp_servers entry named pipelines is rejected at save time. If such an entry appears through other means, the platform shim takes precedence and a warning is emitted.
Files, general escape hatch
Write arbitrary text files into the sandbox before the run, even for harnesses the platform doesn't recognize:
{
"files": {
"home": { ".config/harness/config.yaml": "telemetry: false" },
"cwd": { "CONTRIBUTING.md": "Run make test before committing." }
}
}- home paths are written under /home/user.
- cwd paths are written to workspace repository root. These files become part of graded diff, and dispatch emits warning. Prefer home unless diff changes are intentional.
- Paths must be safe relative POSIX paths. Leading slash, dot-dot segments, single dot segments, and shell prefix expansions are disallowed. Content must be string.
Warnings
Any setting unsupported by the target harness is dropped with warning rather than hard failure. Warnings appear on save in the agent form and at run time in command trace under inject_warnings. Typical cases include subagents on Codex, mcp_servers on Aider, SSE remotes on Codex, and cwd files that affect graded diff.
Environment variables and secrets
Separate from harness_config, sandbox agents can declare environment variables in the Environment variables rows on the agent form. Each row is either:
- Value, stored as plaintext in agent config. On-screen masking is cosmetic. Treat these entries as non-secret configuration.
- From credential, resolved from org credential and decrypted only at dispatch. This is the only encrypted storage path and is required for API keys and tokens.
Secrets in mcp_servers environment fields, remote headers, or files content are part of harness_config and stored in plaintext. Store secrets in org credentials and reference them through environment variables.
Smoke test
Before scaling a pipeline, run one small task and confirm:
- The run command starts the intended harness.
- Any injected files appear in the expected location.
- MCP servers register, or an actionable warning explains why not.
- Platform Tool Calls match your expectation.
- Cost metadata is recorded, or is intentionally unavailable for that harness.