RFC 0024: The agentd evaluation harness — benchmarking the runtime × its paired intelligence
Status: Proposed (2026-07-10)
Author: Andrii Tsok
Date: 2026-07-10
Part of: the quality/credibility track. agentd is an agentic harness; this RFC defines how we measure an agentd × model configuration against public agentic benchmarks, and how we prove agentd is a good harness. References the workflow dialect (RFC 0021), MCP client transport (RFC 0004), telemetry contract (RFC 0016), and the embedding/code-tools surface (RFC 0022).
1. Problem / Context
We ship a harness (agentd) and pair it with an intelligence (an LLM endpoint, RFC 0006/0018). We have no external yardstick for how that pairing performs on real agentic work, and no evidence that agentd is a competitive scaffold rather than merely a working one.
The load-bearing fact from the 2025–26 evaluation literature is that the
harness moves scores more than the model does. Harness-Bench and the Holistic
Agent Leaderboard (HAL) report the same model swinging 34–48 percentage
points on SWE-bench Verified purely from scaffold changes — an order of
magnitude larger than the 2–4 pp deltas papers report as model progress. The
field's conclusion: a score belongs to a model × harness configuration, never
to a model alone.
That reframes benchmarking for us into two experiments, both valuable:
- Model quality, agentd fixed — which paired intelligence is best in our runtime (the buyer's question).
- Harness quality, model fixed — is agentd competitive with a reference
scaffold (e.g.
mini-swe-agent, ~100 lines, >74% on SWE-bench Verified) when both drive the same model? This is the more novel, more defensible claim and the one that markets agentd.
This RFC owns: the benchmark portfolio, the mapping to agentd's surfaces, the workflow-evaluation methodology, the orchestration architecture, the metric set, and a runnable Phase-0 reference. It does not own: the runtime under test (that is the rest of agentd), nor the third-party benchmarks/graders themselves (we integrate them, we do not re-implement them).
2. Design principles
- Measure the configuration. Every result is stamped with
{agentd version, harness config, model id, mode}(the Harness-Bench discipline). A bare number is not a result. - MCP-native ⇒ adapters are tool-bridges, not harnesses. agentd already is the ReAct loop, retries, budgets, subagents, and telemetry. Because it speaks MCP natively, nearly every agentic benchmark reduces to "stand up the right MCP server(s) + capture the deliverable." We write a tool-bridge per environment, not a harness per benchmark. This is the leverage the whole design rests on.
- Report reliability and cost, not just accuracy. Headline pass@1 hides the production picture. We report pass^k (all k i.i.d. trials succeed — a 90% pass@1 collapses to 57% at k=8) and cost-per-solved-task alongside accuracy. These are the metrics production-oriented leaderboards emphasise.
- Coordination must earn its cost. Workflows/subagents are evaluated by ablation against plain ReAct, measured cost-adjusted — because the evidence is mixed (a single agent matches or beats multi-agent on ~64% of tasks at ~half the cost; parallel decomposition wins big on genuinely wide tasks). The honest deliverable is a curve showing where decomposition pays off, not a claim that it always does.
- Contamination hygiene. Prefer
-Verified/v2/ held-out variants; several headline benchmarks have been retired by their maintainers for contamination. Record dataset version + date on every run. - Tooling stays out of the moat. The runner is external tooling (Python —
the benchmark ecosystem's lingua franca, and where the native graders live),
not a runtime dependency. The
agentd-coredependency count is untouched.
3. The benchmark portfolio
Tiered by fit to agentd, not by fame. ⭐ = native fit.
| Benchmark | Measures | Fit | Cost |
|---|---|---|---|
| MCP-Universe / MCP-AgentBench / MCP-Atlas | task completion through real MCP servers (nav, repo, finance, browser, web-search); 231 tasks / 11 servers | ⭐ Native — agentd is the runtime built for exactly this; frontier models score low (GPT-5 ~44%, Sonnet ~29%) → headroom + on-message story | Low–med |
| τ²-bench (tau2) | tool + simulated-user + policy adherence, stateful DB, pass^k; retail/airline/telecom/banking, dual-control | ⭐ domain tools → MCP; simulated user → A2A peer or the RFC 0021 human gate; policy → instruction; reliability → durability story | Low–med |
| BFCL v4 | function-call correctness (AST + executable), multi-turn, +web/memory | ⭐ cheap unit-test of the tool loop — gates the pairing before spending on the big ones | Very low |
| GAIA | generalist assistant Qs (web + files + multi-hop), 3 levels, exact-match | web/file/code MCP; Levels 2–3 are the workflow showcase | Med |
| SWE-bench Verified | resolve real GitHub issues; graded by the repo's own tests | headline credibility; shell+fs MCP over a per-task sandbox; capture the git diff; baseline vs mini-swe-agent | High (Docker, ~120 GB) |
| Terminal-Bench 2 | hard terminal tasks; Harbor framework | de-facto standard; Harbor has a clean custom-agent adapter | Med–high |
Start with the top three — they exercise agentd's actual core (MCP tool-calling, multi-turn, policy) at low cost and infra.
4. Mapping to agentd surfaces
| agentd surface | Benchmark it lights up |
|---|---|
| MCP tool-calling (RFC 0004) | MCP-Universe, MCP-AgentBench, BFCL |
Reactive + A2A + human gate (RFC 0008/0020/0021) | τ²-bench (simulated user, dual-control) |
| Workflows: fan-out, subgraph/join, CEL, durable checkpoint, resume (RFC 0021) | the ablation (§5) across GAIA-L3 / τ² / SWE-bench |
| Subagent tree + context isolation (RFC 0009) | PerspectiveGap-style context-distribution checks |
| Durability / checkpointer (RFC 0021) | pass^k reliability across all of the above |
Budgets: --max-tokens, --budget-tokens-lifetime (RFC 0025) | cost-adjusted scoring; bounded sweeps |
Static FROM scratch binary | trivial per-task container isolation |
| JSON-lines telemetry + metrics (RFC 0016) | tokens/steps/tool-errors/latency capture, free |
5. Evaluating the workflow capability (the ablation)
Most agentic benchmarks test one ReAct loop, so workflows are evaluated by running the same task set through progressively richer configurations and measuring the delta:
- A. Plain —
oncemode, single loop. - B. Workflow — decompose → fan-out subagents → join/synthesize.
- C. Workflow + durability — add the MCP checkpointer + resume; report pass^k.
Every cell is reported cost-adjusted (tokens + wall-clock). The expected — and publishable — result is a curve: decomposition wins on wide/multi-hop tasks (GAIA-L3, τ² multi-step) and loses on simple ones. That "where it pays off" map is more useful and more honest than a single lift number.
6. Orchestration architecture
matrix runner → {benchmark} × {model} × {agentd config} × {N runs}
(fan-out) │ one task
┌────────────────▼─────────────────┐
│ per-task container (isolated) │
model under ──► │ agentd (once|workflow) ◄─MCP─► tool-bridge MCP server
test (--intel) │ │ JSON-lines + report │ env / sandbox
└────────┼───────────────────────────┼──────────────┘
▼ ▼
telemetry capture native grader
(wall-clock, tool-calls, exit, (repo tests / reward /
tokens where surfaced) exact-match / pass^k)
└──────────────┬─────────────┘
▼
unified scorecard
Four pieces, one of them the real investment:
- The tool-bridge (reusable). An MCP server exposing each environment: a shell+fs server for SWE-bench/Terminal-Bench (bash + read/write/patch); a web+file server for GAIA; the domain-API servers for τ² (retail/airline over a stateful DB). Built once per environment; thereafter every benchmark on that environment is a config change, not new harness code. agentd's own mock-MCP scaffolding is the pattern to copy.
- The per-benchmark adapter (thin). Render the task into
--instruction, point--mcpat the bridge and--intelligenceat the model, set budgets, run, capture the deliverable (SWE-bench → git diff →preds.json; τ² → final DB state/actions; GAIA → answer string), hand it to the benchmark's native grader unchanged. - The metric layer. agentd already emits JSON-lines telemetry (RFC 0016), so per run we get tool-call counts, latency, exit code, and — where surfaced — tokens/steps for free. Report pass@1, pass^k, cost-per-solved-task, and the workflow-lift delta.
- The matrix runner + isolation. Sweep the grid, one task per container
(cheap: static binary), fan out across workers. agentd can orchestrate the
sweep itself (reactive/workflow fan-out over a task queue) — a dogfood that
is also a second-order test of the workflow engine at scale. Every result
stamped with
{agentd version, config, model, dataset@version}.
7. Metrics & scorecard
Per {benchmark, model, config} cell:
- pass@1 — mean single-run success.
- pass^k — fraction of tasks solved on every one of k runs (reliability).
- cost — tokens (in/out) and wall-clock per task; cost-per-solved-task.
- tool-call error rate — malformed/failed tool calls / total (from telemetry).
- exit distribution — clean vs budget(7) vs error, per the exit-code contract.
- workflow-lift — Δ(accuracy, cost) of config B/C vs A on the same tasks.
The scorecard is machine-readable JSON + a printed table; it can back a served
agentd:// view or a static report page.
8. Phasing
- Phase 0 (done): the reference runner + offline smoke — cost-adjusted scoring + config comparison (§9).
- Phase 1 (in progress): ✅ BFCL landed — the generic tool-bridge MCP
stub, the tool-call grader, and the BFCL converter (§9). ✅ The τ²-bench
foundation — the tool-bridge is now a stateful environment (tool
effects over a JSON store) and grading can be outcome-based (grade.state: the world must reach the expected end-state), the τ² grading model. ✅ The simulated-user loop — multi-turn agent↔user conversations where both sides are agentdonceruns (the agent with tools + policy; the "user" a second model with a hidden scenario and no tools), the env persisting across turns, outcome-graded, ending on###STOP###ormax_turns. All proven end-to-end offline. Next: point at the real MCP-Universe servers + τ²-retail data with a live model (the cross-org agent-mesh variant maps onto A2A, RFC 0020). - Phase 2 (in progress): ✅ the shell/file environment — the tool-bridge
gained sandboxed
bash/read_file/write_filebuiltins over a per-task workdir, with filesystem + check-command grading (grade.files/grade.command), the SWE-bench / Terminal-Bench substrate (proven offline). Next: seed a real SWE-bench-Verified instance (repo@commit + test command) + the mini-swe-agent baseline; GAIA (web/file bridge). - Phase 3 (in progress): ✅ the workflow-lift ablation (
bench/ablate.py, §5) — runs a suite asoncevs a linear workflow vs a fan-out (foreach) workflow and reports accuracy × cost per config with an honest verdict (extra cost counts only when it buys accuracy). Cost is summed across the whole subagent tree, so a fan-out's N× token cost is visible. Proven offline (outcome-graded tasks, config-agnostic grading). Next: workflow+durability (pass^k) and the ablation across decomposable real-model tasks (GAIA-L3 / τ²).
9. Phase-0 reference implementation (bench/)
A dependency-free (Python stdlib) runner lives at bench/:
bench/run.py— spawnsagentdper task (booting its built-in mock LLM / mock MCP so the rig runs offline, no API keys), captures stdout (the deliverable) + stderr (telemetry) + exit + wall-clock, grades against a per-task matcher, and aggregates pass@1 / pass^k plus cost-adjusted metrics — tokens, steps, cost-per-solved-task (§7) — into a JSON scorecard- a printed table. Cost is real, at no runtime cost: the child loop already
reports per-run usage in its
loop.finaltelemetry, which the runner sums across the subagent tree.
- a printed table. Cost is real, at no runtime cost: the child loop already
reports per-run usage in its
bench/compare.py— diffs two scorecards side-by-side with deltas + per-task regressions/fixes. This is the thesis's core operation (a score is a comparison): model A vs B, agentd vs a reference scaffold, or plainoncevs a fan-outworkflow(the §5 ablation).bench/ablate.py— the workflow-lift ablation (§5): runs a suite asonce/ linear-workflow / fan-out-foreachand reports accuracy × cost per config (cost summed across the subagent tree). agentd's most distinctive evaluation — measuring what decomposition buys, honestly. Needs a--features workflowbuild.- Phase 1 (BFCL):
bench/mcp_stub.py— the generic tool-bridge (§6): a configurable MCP server that serves an arbitrary tool set to agentd, so a benchmark environment is a data file, not harness code. It is stateful — a tool may declare aneffect(set/append/returnover a dotted-path JSON store) and the world is persisted for grading, or abuiltin(bash/read_file/write_file) over a per-task sandbox dir — the SWE-bench / Terminal-Bench substrate, graded bygrade.files(path → contains/exact) andgrade.command(a check command's exit).bench/graders.py— the tool-call grader (BFCL-style name + args match) and the outcome grader (grade_state: the final environment must satisfy an expected subset — the τ²-bench model).bench/bfcl.py— the BFCL converter (functions → tool-bridge tools, question → instruction, ground-truth → matcher). agentd exposes MCP tools by their verbatim catalogue name, so BFCL function names map straight through. bench/tasks/{smoke,bfcl_smoke,tau2_smoke,tau2_convo_smoke,swe_smoke}.jsonl— offline suites: the mechanics (pure-answer + tool-call ReAct), the full BFCL pipeline (tool-bridge serves a function → themcp-callmock model calls it → the grader scores name + args), the τ²-shaped stateful pipeline (a tooleffectmutates the environment → outcome grading on the end-state), the multi-turn simulated-user conversation (agent↔user turns → outcome grading), and the SWE-shaped shell pipeline (abashbuiltin runs in a sandbox → filesystem grading) — all with no keys.- A task's
intelligence/model/tool_server(ormcp) fields make pointing at a real model + real tools a data change, not a code change.
Phase 0 deliberately tests the harness plumbing (drive agentd → capture deliverable → grade → aggregate cost/telemetry → compare configurations), which is the reusable core every later phase builds on, with zero external cost.
10. Non-goals / caveats
- Not a new benchmark — we integrate public ones and their native graders.
- Not a runtime dependency — the runner is external tooling; the moat holds.
- Token/step cost is captured from the child's
loop.finaltelemetry (the loop reports real per-run usage; the runner sums it across the subagent tree), so cost-adjusted scoring works with no runtime change. The durable run report (report.usage, RFC 0016 §6.2) still records honest-absence zeros inoncemode; wiring it to the real total is a separate, optional follow-up (the telemetry path is sufficient for the harness). - SWE-bench full is expensive; the Verified 500 / Mini subset is the default.
11. References (external)
Harness-Bench (arXiv 2605.27922); Holistic Agent Leaderboard (arXiv 2510.11977); MCP-Universe (arXiv 2508.14704); MCP-AgentBench (arXiv 2509.09734); τ-bench (arXiv 2406.12045) + τ²-bench (sierra-research); BFCL (PMLR v267) + BFCL v4; SWE-bench Verified + mini-swe-agent; Terminal-Bench / Harbor; GAIA (arXiv 2311.12983) + HAL leaderboard. Pass^k reliability framing per the τ-bench paper.