Agentic-AI-Eval-Harness

Portfolio Write-Up — agent-eval-harness

The FDE field guide’s presentation contract (portfolio/03-presenting-projects.md) prescribes eight sections, in this order. This write-up follows it literally. The guide also says hiring managers spend minutes, not hours — so: the one-paragraph version is in the README’s first screen; the two-minute version is make demo; the ninety-second spoken version is 90-SECOND-STORY.md. Everything below is the depth behind those.


1. Problem

The brief as it arrived (fictional composite customer, verbatim, frozen before any spec work — see 00-ENGAGEMENT-BRIEF.md):

“three teams shipped AI agents in the last two quarters. the demos all looked great… last month somebody tweaked a prompt and the billing-triage agent got worse — quietly. we found out from a support volume spike NINE DAYS later… we need to know the moment they stop working. before our customers tell us. and whatever you build — ops has to actually run it. they will not learn a new tool.”

Rejected problem statements (visible on purpose — the guide wants “a problem statement that starts vague and ends specific, with the rejected versions visible”):

2. Constraints discovered

The ones we did not choose (the guide’s definition):

3. What you built

In the operator’s vocabulary (the guide: “named in the operator’s vocabulary rather than the vendor’s”): a CI gate for AI agents. Three teams ship agents; this platform runs each against 280 frozen, hash-pinned golden cases; scores outcomes and behavior; compares against committed baselines; fails the merge when quality drops beyond the team’s own threshold; and tells you whether to blame the agent, the evaluator, or the infrastructure.

Agent → Adapter → Harness (tool gateway: permissions · retry · verification ·
       sandbox · resource caps) → Benchmark Runner → Trajectory capture
       → Evaluators (10 deterministic · 6 trajectory/behavioral · 4 judge
       criteria, κ-calibrated) → Metrics (Wilson CI · p50/p95 · cost)
       → Baselines → Regression Gates (fail closed) → Reports (3-bucket)
       → CLI (13 commands) · Web Dashboard (`agent-eval serve`) · pytest bridge · CI · `make demo`

Components: 16-package Python library (stdlib-first), 5 deterministic reference agents (ReAct / Plan-and-Execute / Supervisor / Swarm / Map-Reduce), 3 framework adapters (LangGraph / OpenAI Agents SDK / CrewAI), 20 evaluators, regression engine with exact McNemar comparison, 132 tests, zero-dependency Web Dashboard, and production Docker containerization.

4. Decisions and trade-offs

The guide calls this the section that matters most — “the reason the second-best option lost is what proves an engineer was present.” Five here; all 13 in DECISIONS.md:

  1. Deterministic backend for all measured numbers — rejected silent live-LLM fallback; cost: no live latency/cost/κ figures in this build, everything live is labeled Not measured yet.
  2. Gates fail closed on insufficient data — rejected pass-open; cost: occasional false blocks on tiny runs, correctness in exactly the small- diff cases where regressions hide.
  3. No dashboard — rejected a web UI (ops: “dead on arrival”); cost: no visual trending; the weekly view is one CLI command.
  4. Adapter protocol, not framework instrumentation — rejected deep per-framework hooks; cost: boundary visibility only, framework internals invisible.
  5. κ ≥ 0.6 before any judge verdict gates CI — rejected judge-out-of-the-box; cost: a calibration experiment and hand labels before value — which then caught our own rubric v1.0 scoring κ = 0.082 (INC-4) before it could gate anything.

5. Evaluation

The guide’s rule: dataset size and provenance, metrics, thresholds, and the failures you could not fix.

Benchmark Pass rate 95% CI
react_basic 89.3% (50/56) [78.5%, 95.0%]
swarm_basic 82.1% (46/56) [70.2%, 90.0%]
supervisor_basic 80.4% (45/56) [68.2%, 88.7%]
map_reduce_basic 76.8% (43/56) [64.2%, 85.9%]
plan_execute_basic 73.2% (41/56) [60.4%, 83.0%]

6. Deployment and operations

7. Outcomes

Defined in writing before the build (03-ACCEPTANCE-CRITERIA.md), reported after — the guide’s rule, not our habit:

8. What I would do differently

Specific and technical, per the guide’s ban on “I would plan better”:

  1. Hand-label more calibration samples before writing any rubric. The κ = 0.082 incident (INC-4) came from a rubric written against my own intuitions; 56 labels was the floor, not a comfortable margin. I would label ~150 and stratify by category before rubric v1 exists.
  2. Make run ids include a sequence salt for display runs while keeping content-hash ids for canonical runs. The determinism guarantee and the “new file per run” operational expectation collided twice (INC-8, runbook sharp edge #4); a two-tier id scheme would have avoided both without weakening byte-identical reproducibility.
  3. Start the clean-room validator on day one, not at release. INC-7 (plugin missing from clean clones) existed for the entire build and was only caught when the zip was validated. The validator that found it should have been the second thing written, after the skeleton.
  4. Emit OTLP-shaped events even without a trace backend. The no-trace-vendor decision (D-07 scope cut) was right for the customer, but serializing to the OTel-compatible shape from the start would make the future integration a config change instead of a refactor.
  5. Buy the latency p95 budget explicitly in the spec. We record p50/p95 per case, but the suite wall-time budget got all the negotiation attention; the per-case tail budget (where cold-starts live, per the guide) was implicit. Cheap to have written down; expensive to retrofit.

Depth artifacts, per the guide’s five signals: rejected problem statements (§1) · decision records (DECISIONS.md, 13 ADRs) · evaluation table with dataset size, thresholds, and unfixed failures (§5) · incident log (INCIDENTS.md, 10 real incidents) · runbook executed by another process (RUNBOOK.md + clean-room validator). The repo links back: README → this file; this file → every artifact it claims.