Harness orchestration
Dispatch a coding agent as a typed worker with turn caps and schema-validated output. CodeAF runs by default; Claude Code, Codex, Gemini CLI, OpenCode, Pi, and OMP are one field away.
Use a harness as a step inside a regular reasoner. The harness runs a coding agent, gives it tool access, bounds the run with a turn cap, and returns a schema-validated object -- not free-form text.
The default worker is CodeAF. Set OPENROUTER_API_KEY; the installer, Desktop, or first SDK execution provisions the binary. Run af codeaf ensure to pre-install. Claude Code, Codex, Gemini CLI, OpenCode, Pi, and OMP are provider overrides; see Bring your own coding agent.
from pydantic import BaseModel
from agentfield import Agent, HarnessConfig
# No provider, no model -- this agent's harness calls run on CodeAF.
app = Agent(node_id="migrator", harness_config=HarnessConfig())
class MigrationPlan(BaseModel):
sql_statements: list[str]
rollback_steps: list[str]
risk_assessment: str
@app.reasoner()
async def plan_migration(description: str) -> dict:
# Harness reads the schema, writes SQL, validates against the Pydantic model
result = await app.harness(
f"Analyze the database schema and produce a migration plan for: {description}",
schema=MigrationPlan,
max_turns=20, # turn cap -- CodeAF exec receives --max-turns
)
if result.is_error:
return {"error": result.failure_type, "message": result.error_message}
plan: MigrationPlan = result.parsed
return {
"sql": plan.sql_statements,
"rollback": plan.rollback_steps,
"cost_usd": result.cost_usd,
"turns": result.num_turns,
}
# Swap workers per-call -- Codex for test generation, Gemini for big refactors
@app.reasoner()
async def write_tests(module: str) -> dict:
result = await app.harness(
f"Write a comprehensive test suite for {module}.",
provider="codex",
model="o4-mini",
max_turns=40,
)
return {"output": result.text, "cost_usd": result.cost_usd}
app.run()What this gives you
- A multi-turn harness looks like a regular function call -- input goes in, validated object comes out.
- The default worker is CodeAF. Set
OPENROUTER_API_KEYand pre-install withaf codeaf ensureor allow a first-call download. - CodeAF
execmapsmax_turnsto--max-turns. CodeAF enforces turn and time limits only:max_budget_usd,tools, andpermission_modeare ignored. SetAGENTFIELD_HARNESS_TIMEOUT_SECONDS(default1800) for the outer time limit.AGENTFIELD_CODEAF_COMMAND=doopts into the routed workflow, which does not forwardmax_turns. failure_typedistinguishes timeouts, crashes, schema-validation failures, and API errors.
Bring your own coding agent
The loop above is worker-agnostic. Set provider and the identical call drives Claude Code, Codex,
Gemini CLI, or OpenCode instead -- which is how you orchestrate a fleet of Claude Codes (or mix
workers) from a single AgentField reasoner.
# Same reasoner, different worker -- and claude-code is the provider that enforces max_budget_usd.
plan = await app.harness(
prompt, schema=MigrationPlan, provider="claude-code", max_budget_usd=1.00
)
# Or set it once for the whole agent.
app = Agent(node_id="migrator", harness_config=HarnessConfig(provider="claude-code"))Each override brings its own install and credential (Claude Code differs per SDK):
provider | Install | Credential |
|---|---|---|
codeaf (default) | af codeaf ensure or first-call download | OPENROUTER_API_KEY |
claude-code | Python: pip install 'agentfield[harness-claude]' · TypeScript: npm install @anthropic-ai/claude-agent-sdk · Go: the claude CLI (npm install -g @anthropic-ai/claude-code) | ANTHROPIC_API_KEY |
codex | npm install -g @openai/codex | OPENAI_API_KEY |
gemini | npm install -g @google/gemini-cli | GEMINI_API_KEY |
opencode | curl -fsSL https://opencode.ai/install | bash | opencode auth login |
pi | npm install -g --ignore-scripts @earendil-works/pi-coding-agent | Provider login or API key |
omp | curl -fsSL https://omp.sh/install | sh | Provider login or API key |
AGENTFIELD_HARNESS_PROVIDER shifts the default for a whole process without touching code; an
explicit provider on the config or the call still wins. Verify a worker before you depend on it:
af harness doctor --provider codeaf # or claude-code / codex / gemini / opencode / pi / omp
Next