AForge — the default harness
AForge is AgentField's native coding harness. It ships with af, needs no CLI install, and runs every app.harness(...) call that does not name a provider.
AForge is AgentField's native coding harness, and it is the default. Every
app.harness(...) call that does not name a provider runs on
AForge — no CLI to install, no per-worker coding-agent account to create, no provider= argument
to remember (just one OPENROUTER_API_KEY).
This page is the canonical reference for the default path. If you would rather drive Claude Code, Codex, Gemini CLI, or OpenCode instead, that is one field — see Choose a different worker below.
Nothing to install
AForge is provisioned alongside the af binary, so if you have AgentField you already have it:
| How you got AgentField | How you got AForge |
|---|---|
curl -sSf https://agentfield.ai/get | sh | Installed by the same script. |
| AgentField Desktop | Downloaded on launch — the app runs af aforge ensure. |
| Official Docker images | Baked in at build time by the python-agent, go-agent, and cloud control-plane images. The plain control-plane image does not carry it. |
The one thing you supply is a key:
export OPENROUTER_API_KEY=sk-or-...That is the entire setup. The first harness call works from there.
from pydantic import BaseModel
from agentfield import Agent
class ReviewResult(BaseModel):
findings: list[str]
severity: str # "low" | "medium" | "high"
app = Agent(node_id="reviewer")
@app.reasoner()
async def review_diff(diff: str) -> dict:
# No provider, no model — this runs on AForge.
result = await app.harness(
f"Review this diff. Be precise, no fluff.\n\n{diff}",
schema=ReviewResult,
)
if result.is_error:
return {"ok": False, "error": result.error_message}
return {"ok": True, "review": result.parsed.model_dump()}Configuration
| Setting | Where | Default | What it does |
|---|---|---|---|
OPENROUTER_API_KEY | env | — | Required. AForge's model access. |
AFORGE_MODEL | env | AForge's own default | Overrides the model AForge runs. Leave it unset unless you have a reason. |
AFORGE_EXEC_BUDGET | env | 150000 tokens | AForge's own per-run token budget. max_budget_usd is not enforced by AForge — bound a run with max_turns (becomes --turns) plus this. |
AGENTFIELD_HARNESS_TIMEOUT_SECONDS | env | 1800 | Wall-clock cap the SDK passes to AForge as --timeout. |
AGENTFIELD_HARNESS_PROVIDER | env | aforge | Switches the default provider process-wide. Accepts aforge, claude-code, codex, gemini, opencode (plus grok, Python SDK only). |
provider | HarnessConfig / per-call option | aforge | Explicit provider for this agent or this call. Highest precedence. |
model | HarnessConfig / per-call option | empty | Empty means "use the provider's own default". Set it to pin a specific model. |
Provider precedence
Provider selection resolves in exactly this order — first match wins:
- An explicit
provideron the call options, then on the agent'sHarnessConfig. - The
AGENTFIELD_HARNESS_PROVIDERenvironment variable. aforge.
model follows the same shape: an explicit value wins, and an empty value means the provider picks
its own default. model no longer defaults to "sonnet" — that was a Claude-specific value, and it
now lives inside the claude-code provider, so explicit claude-code users see no change.
Operating it
# (Re)install or repair the AForge binary in ~/.agentfield/bin.
af aforge ensure
# Check the binary and its version, and report which auth env vars are set.
af harness doctor --provider aforgeaf harness doctor works for every provider — swap --provider for claude-code, codex,
gemini, opencode, or grok to check those instead.
If the binary is missing — a pip install agentfield-only setup, an install with --no-aforge, or
AGENTFIELD_SKIP_AFORGE=1 — the first default-provider harness call fails with a provider-unavailable
error that names the fix. Run af aforge ensure (or set AFORGE_BIN to an existing binary) and retry.
Choose a different worker
The default is a starting point, not a lock-in. AgentField's harness is a uniform loop with a swappable worker, so orchestrating Claude Code — or a fleet of them — is one field.
# Same call, different worker.
plan = await app.harness(prompt, provider="claude-code", permission_mode="plan", schema=ChangePlan)
edits = await app.harness(apply, provider="codex", permission_mode="auto", schema=EditReport)Each override has its own install and credential (Claude Code differs per SDK):
provider | Install | Credential | Docs |
|---|---|---|---|
aforge (default) | ships with af | OPENROUTER_API_KEY | this page |
claude-code | Python: pip install 'agentfield[harness-claude]' · TypeScript: npm install @anthropic-ai/claude-agent-sdk · Go: npm install -g @anthropic-ai/claude-code | ANTHROPIC_API_KEY | Anthropic — Claude Code |
codex | npm install -g @openai/codex | OPENAI_API_KEY (or codex login) | OpenAI — Codex |
gemini | npm install -g @google/gemini-cli | GEMINI_API_KEY or GOOGLE_API_KEY (or sign in by running gemini once) | Google — Gemini CLI |
opencode | curl -fsSL https://opencode.ai/install | bash | whatever opencode auth login configures | OpenCode |
Nothing else in the loop changes: same schema binding, same turn caps, same retry ladder, same
HarnessResult. That is what makes retry-with-fallback, tournaments, and adversarial verifier
patterns cheap — see Harness.
See also
- Harness — the building block, its full option surface, and composition patterns.
- Harness orchestration — the end-to-end quick guide.
- Configuration reference —
HarnessConfigfield-by-field.
Databricks
Verify Databricks notification destination webhooks and expose Databricks SQL, AI Functions, and Model Serving as AgentField capabilities.
Anthropic — Claude Code
Drive Anthropic's Claude Code from inside agent loops — the optional override for AgentField's default AForge harness — with budget caps, schema-bound output, and the official claude_agent_sdk.