AgentFieldquick-guides

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_KEY and pre-install with af codeaf ensure or allow a first-call download.
  • CodeAF exec maps max_turns to --max-turns. CodeAF enforces turn and time limits only: max_budget_usd, tools, and permission_mode are ignored. Set AGENTFIELD_HARNESS_TIMEOUT_SECONDS (default 1800) for the outer time limit. AGENTFIELD_CODEAF_COMMAND=do opts into the routed workflow, which does not forward max_turns.
  • failure_type distinguishes 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):

providerInstallCredential
codeaf (default)af codeaf ensure or first-call downloadOPENROUTER_API_KEY
claude-codePython: 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
codexnpm install -g @openai/codexOPENAI_API_KEY
gemininpm install -g @google/gemini-cliGEMINI_API_KEY
opencodecurl -fsSL https://opencode.ai/install | bashopencode auth login
pinpm install -g --ignore-scripts @earendil-works/pi-coding-agentProvider login or API key
ompcurl -fsSL https://omp.sh/install | shProvider 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