eval-first · one core · three orchestrations
A medical-claims line-item auditor built eval-first: the frozen holdout and metrics came before any agent. The same four tools and one deterministic rule core are then orchestrated three ways — claude-agent-sdk, LangGraph, and the Vercel AI SDK — and scored by the identical harness. Any difference is orchestration, not logic drift.
Frozen 25-claim holdout. Every LLM arm runs the cheap open model qwen/qwen3-32b through OpenRouter, so the comparison is apples-to-apples.
The deterministic engine is the CI-gated arm (measured on every push). The LLM arms are reported, not gated.
| SDK / Arm | Thinking | Model | Precision | Recall | F1 | Citation | Fabrication | Latency | $/claim |
|---|---|---|---|---|---|---|---|---|---|
| engine (deterministic) | n/a | n/a | 1.000 | 1.000 | 1.000 | 1.000 | 0.000 | <1 ms | $0.00000 |
| langgraph · openrouter | off | qwen3-32b | 0.750 | 1.000 | 0.857 | 1.000 | 0.000 | 3.6 s | $0.00018 |
| langgraph · openrouter | on | qwen3-32b | 1.000 | 0.600 | 0.750 | 1.000 | 0.000 | 1.5 s | $0.00016 |
| claude-agent-sdk · openrouter | off | qwen3-32b | 1.000 | 1.000 | 1.000 | 1.000 | 0.000 | 54.3 s | $0.00324 |
| vercel-ai-sdk · openrouter new | off | qwen3-32b | 0.714 | 1.000 | 0.833 | 1.000 | 0.000 | 15.3 s | $0.00063 |
| vercel-ai-sdk · openrouter new | on | qwen3-32b | 0.938 | 1.000 | 0.968 | 1.000 | 0.000 | 11.9 s | $0.00059 |
Same tools, same prompt, same holdout. Here's where each one helps and where each one fights you.
Autonomous in-process tool loop
FindingExplicit, fixed graph
evidence_check node makes fabrication structurally impossibleAutonomous loop, TypeScript
Finding, field-for-field with Pydantic; .strict() = extra="forbid"generateText + stopWhen: stepCountIs — the bound is one explicit linesteps[] / usage per call; a first-class offline mock modelevidence_check seam (like the SDK arm, it trusts the model + strict schema); an unknown model id trips a maxOutputTokens compat warning
One tool is also wired through the AI SDK's MCP client to a separate sparql-mcp server
(SSE) — proving an external MCP tool drops into this arm through one standard interface, without
touching the scored audit loop.