Utkrushta · Engineering Experiment Report

Verifying task-solvability on prod: what we tested, found, and should build

A hands-on measurement study — 2 agentic harnesses, 11 models, 3 real tasks, 60+ solve runs on real E2B sandboxes with real charges — to make task verification cheap and reliable at prod scale.

date 2026-07-07 providers tested OpenRouter · Anthropic · Ollama Cloud grading real cargo test / pytest
TL;DR
  • The interface, not the model, is the bottleneck. With structured tool-calling, cheap open-weight models solve the same tasks a frontier model does — including infra tasks with live services.
  • A real agentic solve costs ~$0.50 on Sonnet (infra), ~$0.02–0.07 (non-infra) — but the same solve is $0 marginal on an Ollama Cloud flat plan, and ~$0.01 on cheap API models. Roughly 10–50× cheaper than Sonnet.
  • Best model for us: kimi-k2.7-code (Ollama Cloud) — solved every task we threw at it, fast and token-efficient. glm-5.2 is the efficiency runner-up; nemotron-3-super fails infra; Devstral isn't on Ollama.
  • Solver runtime: Pi headless. Model-agnostic, tool-calling, driven from the backend; provisions an E2B sandbox for infra tasks and calls Ollama for the model.
  • Biggest cost lever is architectural: don't re-audit. Cache the verdict in a task_audits row; re-run only when the task's content_hash changes (there is no updated timestamp on tasks). Position creation reads the cache.
  • Governance is fine: the strong coders are Chinese-origin but US-hosted by Ollama with zero retention — data never leaves to China. Origin ≠ hosting.
Core finding
Interface > model
Tool-calling decides whether cheap models can solve — proven on infra.
Best model
kimi-k2.7-code
Solved all 3 tasks; $0 marginal on Ollama Pro.
Cost lever
Cache verdict
Re-audit only when the task's content_hash changes.
Solver runtime
Pi headless
Model-agnostic tool-calling + E2B for infra.

01The question & hypothesis

PR #37's task-audit bundle verifies the end-to-end task flow (task-repo-checktask-solvabilitytask-verify). It works from local Claude Code; we want it on prod, triggered by a backend DAG, on the tasks of every new position — without a runaway bill.

Only one of the four skills spends real money: task-solvability runs a full coding agent that solves each task RED→GREEN. task-audit itself is a zero-LLM Python linter. So "audit every task" means "run a coding agent to solve every task" — and that's what we measured. (The original idea of running it on a Claude subscription is a non-starter — Anthropic's 2026 ToS bans subscription tokens for automated/headless prod use.)

02What we tested

Two agentic harnesses, three real tasks, three providers, 60+ solve runs — each graded by the task's own test suite with real charges.

HarnessWhat it doesEdit interface
solve_bench_tools.pyagentic loop, local OR E2B sandboxstructured tool-calling
pi_bench.py + Pidrives the real Pi coding-agent harness headlessPi's native tool-calling
DimensionCoverage
Tasks (3, real, ship RED)live-watch-stats-aggregator & summarize-viewer-engagement (non-infra Rust, cargo test) · streamflix-watchlist-mutation-repair (infra: FastAPI + Strawberry GraphQL + live Postgres, pytest in a real E2B sandbox)
Providers (3)OpenRouter (pay-per-token: Gemini, DeepSeek, Devstral, MiniMax, GLM) · Anthropic (Sonnet-5) · Ollama Cloud (flat plan: kimi, glm-5.2, qwen3.5, gpt-oss, nemotron, gemma4)
Models (11)Sonnet-5, Gemini-2.5-flash-lite, DeepSeek-V4-Pro, GLM-5.2, Kimi-K2.7-Code, Qwen3.5, gpt-oss:120b, MiniMax-M3, Nemotron-3-Super, Devstral-2, Gemma 4
Solve runs60+ across text-protocol and tool-calling, non-infra and infra

03Findings

1 The edit interface — not the model — is the bottleneck the big one
With a naïve text-delimiter protocol, cheap models fail non-deterministically (same task, temperature 0, solved one run, unparseable the next), worse as context grows — on the infra task, only Sonnet completed it. Swap to structured tool-calling and all of them solve. Devstral (72% SWE-bench) "failed" purely because its edit format couldn't be parsed; via tool-calling it solves cleanly. This is why the prod runtime must be a real tool-calling agent (Pi), not a hand-rolled text loop.
2 A real agent loop costs ~4–7× a one-shot rewrite cost
Tool-calling reads files, edits, runs tests, iterates over 20–40 calls with growing context. Sonnet's infra solve: $0.496 via tool-calling vs $0.114 one-shot. Budget ~$0.50/infra-task on Sonnet — it's how a real agent actually works.
3 Cheap open-weight coders match Sonnet's correctness at a fraction of the cost headline
On tool-calling, the strong Ollama coders solved every non-infra task (2/2) and 4 of 5 infra runs — at $0 marginal on the flat plan. Cheap API models (DeepSeek, MiniMax, Gemini) solved for ~$0.01. Sonnet remains the most consistent, but at 10–50× the price.
4 Origin ≠ hosting governance
GLM/Kimi/Qwen are Chinese-origin but open-weight; run via Ollama Cloud they execute on US infra with zero data retention — data never touches China. The rule is "no Chinese hosting," not "no Chinese model."
5 Reliability still varies → keep a reference gate reliability
Lite models (Gemini-2.5-flash-lite) sometimes decline to use tools and defer to the human; even strong ones flip run-to-run. A single cheap "unsolvable" isn't trustworthy — validate against a Sonnet reference before relying on it.

04The measured data — deeper

Interface proof — infra task, same task, two ways

Model (provider)Text protocolTool-calling$ tool-calling
gemini-2.5-flash-lite OpenRouter✘ unparseable✔ solved0.010
devstral-2 OpenRouter✘ unparseable✔ solved0.057
claude-sonnet-5 Anthropic✔ 0.114✔ solved0.496

Non-infra Rust tasks — cost per solve (tool-calling, real charges)

ModelProviderSolved$ / solve
claude-sonnet-5Anthropic✔ reliable0.02–0.07
deepseek-v4-proOpenRouter~0.011
minimax-m3OpenRouter~0.005
devstral-2OpenRouter~0.005
gemini-2.5-flash-liteOpenRouterflaky~0.001
kimi / glm / qwen / gpt-ossOllama✔ 2/2 each (via Pi)flat ($0)

Ollama Cloud coding models — non-infra (via Pi) & infra (tool-calling)

ModelOriginNon-infraInfraInfra speedInfra tokens
kimi-k2.7-codeCN·🇺🇸-host2/2102s52.7k
glm-5.2CN·🇺🇸-host2/2128s31.5k
gpt-oss:120b🇺🇸2/298s70k
qwen3.5CN·🇺🇸-host2/2163s123k
nemotron-3-super🇺🇸✘ gave up33s17k

All Ollama runs = $0 marginal on the $20/mo Pro plan. Sonnet reference (Anthropic): ~$0.50/infra-solve, ~$0.47/non-infra via Pi. Devstral is not on Ollama Cloud (local-only). Lower tokens = less GPU-time = stretches the flat plan further, so glm-5.2 (31.5k) and kimi (52.7k) are the most plan-efficient.

05Provider landscape

ProviderAccessPricingGovernance
Ollama Cloudopen-weight coders (kimi, glm, qwen, gpt-oss)flat $20/$100 mo, $0 marginal🇺🇸, zero-retention
OpenRoutereverything (Gemini, DeepSeek, Devstral, Sonnet)pay-per-token (~$0.001–0.06)routes to US hosts
AnthropicClaude (the reliability reference)API per-token (~$0.5/infra solve)🇺🇸

06Production architecture — the DAG

A backend DAG fires with a batch of task IDs (e.g. 10 when a position is created) and must return a per-task shippable/not verdict. Skills are interactive runbooks — on prod you implement their logic as a service: the deterministic linter (a direct port of task_audit.py) plus the agentic solver.

DAG trigger
[10 task ids]
cache gate
content_hash?
queue
(only changed)
Pi audit worker
cheap-first + gate
insert row
task_audits
  1. Cache gate — a content hash. tasks has no updated timestamp, so for each id we compute a content_hash (sha256 of task_blob + criterias + pre_requisites + answer + template_id) and look for a task_audits row with that exact hash. Match → return that row's verdict instantly (no Fargate). Only tasks whose audited content actually changed (or were never audited) get re-audited — more precise than a timestamp (an incidental row touch doesn't trigger a re-run). Position creation reads this cache and never triggers a fresh audit on its own.
  2. Enqueue the changed ones. Each becomes one audit job on a queue, decoupling the trigger from the (minutes-long) solve. With the cache gate, this is usually a small number.
  3. Pi audit worker (headless). Per job, a containerized worker runs Pi headless — model-agnostic, tool-calling. It provisions an E2B sandbox for infra tasks (via the E2B key) and drives an Ollama Cloud model (via the Ollama key) to solve RED→GREEN. It grades against the task's tests and also runs the deterministic integrity linter, emitting a combined verdict.
  4. Escalation ladder for cost. Cheap model first (kimi-k2.7-code, $0 marginal). A PASS is self-validating — the tests really went green, so it's SOLVABLE regardless of model. Only a FAIL escalates to Sonnet to separate "genuinely unsolvable" from "cheap model too weak." Frontier price only on the minority that fail the cheap pass.
  5. Write the audit row. INSERT one row into task_audits {verdict, findings, solvable, solved_by, failure_reason, trace_url, detail, content_hash, cost_usd, …} — one row per audit run (full history, "failed → fixed → passed"), stamped with the content_hash it was verified at, so the next trigger's cache gate is an exact hash match.
Handling the 10-at-once trigger
Don't block the DAG on 10 minutes-long audits. The service returns immediately with {cached:[...], queued:[...]}; audits run in workers and INSERT a task_audits row per task; the DAG polls or takes a webhook. Because the cache gate skips every task whose content_hash already matches a prior audit, a typical batch resolves mostly from cache with only the changed tasks actually re-audited.

Deployment topology — where each piece runs

Mirrors the existing v2-grader Fargate pattern: an Airflow DAG launches one ephemeral Fargate task per job via EcsRunTaskOperator. What's new is the sandbox-agent worker (Pi + Ollama Cloud) and a sandbox for isolated test execution. Build it as one generic worker parameterized by job-type (audit / code-grade / auto-fix / regression-sweep).

Position createdBackend · FastAPI
POST /v2/tasks/audit
— trigger_dag →Airflow DAG
audit_task
Cache gate — compute content_hash; does a task_audits row with that hash exist?   match → return cached verdict (no Fargate)  ·  miss → audit ↓
EcsRunTaskOperator → ecs.run_task() — launches an ephemeral Fargate task
the changed-id list is passed as the container command: runner.py --task-id id1,id2,… --env prod --persist db
Batch — 1 container loops the ids serially (1 cold start; default for a position's ~10 tasks)  ·  Fan-out.expand() → 1 container per id, parallel (few heavy tasks)
Fargate task · runner.py — one generic worker, two legs per task (AUDIT = the umbrella)
LEG 1 · INTEGRITY — data + content checks (no sandbox, seconds)
task_audit
mechanical — fields · counts · repo/gist reachability (GitHub API)
+llm_audit
interpretive — SKILL.md verbatim as system prompt over task_blob · README · starter source
findings
LEG 2 · SOLVABILITY
Pi headless+Ollama Cloud
glm-5.2 / kimi · flat $0
solve loop →read · edit · run tests · iterate
▼ deploy + sync files + run pytest / cargo
Sandbox — task repo + live services (Postgres, Kafka…)
via sandbox_manager abstraction → E2B now · CubeSandbox later (pluggable)
PASS → solvable (self-validating)  ·  FAIL → escalate to Sonnet (reference gate)
verdict = combine(solvable, findings) → PASS · PASS_WITH_FINDINGS · FAIL
AUDIT TRAIL — one task_audits row per run  (local: files  ·  prod: DB + object store)
INSERT task_audits (Supabase)
{verdict, findings, solvable, solved_by, failure_reason, content_hash, detail, cost}
+trace.json → S3 · THE RECORDING
trace_url on the row · every tool call + test output — replayable (e.g. 46 entries / 27 tool calls)

What to build (reusing the grader scaffolding): a runner package (python runner.py --task-id … --persist db) → a slim arm64 Dockerfile → an ECR CI workflow → an audit_task DAG with EcsRunTaskOperator → the ECS task-def utkrusht-task-audit-{dev,prod} + IAM (E2B/Ollama keys in Secrets Manager, egress to e2b.app + ollama.com). Codify the AWS side in IaC (the grader's is hand-created in the console) and keep one shared core (the grader paid a "lift-duplication tax" copying compute).

Do we need E2B? Yes — and here's the sandbox call

A sandbox is required for infra tasks: ECS Fargate can't run nested containers, so the Postgres/Kafka service stack needs a real VM. The question is which VM — and we have $20k E2B credits.

Decision: E2B
Use E2B — the $20k credits make it effectively free (verification is low-volume with dedup), it's the exact environment candidates run in (faithful verification), and it's managed (zero ops, reuses sandbox_manager + templates). Our slow step is dep-install + service-start, not sandbox boot, so a faster runtime wouldn't move the needle. Kept behind the sandbox_manager abstraction, so swapping to a self-hosted microVM runtime later is a one-place change if cost ever forces it post-credits — not now (YAGNI).
Always use the sandbox — even for non-infra
Non-infra tasks (pure logic — Rust, self-contained Python) need no services and could run their tests right in the worker container (the solvability skill's --local mode). But the runner uses the E2B sandbox for every task, uniformly. Why: one code path, and the worker image stays slim (just pi + python + node + harness) because the sandbox already carries the task's toolchain (cargo / pytest / npm…) from its template. It costs a few cents extra per non-infra task (E2B credits cover it) and deletes a whole branch of image + branching complexity. Non-infra gets verified the same way — it just has no services running. Running non-infra in-container is a speed/cost optimization → add it only if cost bites.

07Recommendation

  1. Cache the verdict; re-audit only when content_hash changes. The single biggest lever — turns "10 audits per position × M positions" into "each task audited once until its content changes."
  2. Solver = Pi headless, driving an Ollama Cloud model, provisioning an E2B sandbox for infra tasks. Real tool-calling is what makes cheap models work.
  3. Escalation ladder: kimi-k2.7-code first ($0 marginal) → Sonnet only on failure. Reference-gate cheap verdicts before trusting an "unsolvable."
  4. Model pick: kimi-k2.7-code (solved all 3 tasks, fast, efficient). glm-5.2 for max plan-efficiency; gpt-oss:120b for US-origin + speed. Drop nemotron (fails infra); Devstral isn't on Ollama.

08Caveats & sources

Read the numbers honestly
Reliability is measured on 1–2 runs per model per task — indicative, not conclusive; a harder task or more runs could still surface variance (hence the reference gate). Ollama token counts are high via agentic loops (GPU-time toward plan caps, though not per-token billed). Speeds are end-to-end wall (include tool exec + test runs). One integration step remains for a fully-Pi infra path: wiring Pi's Ollama-cloud provider inside the sandbox — the model ranking is unaffected.
Anthropic Agent SDK + subscription policy — support.claude.com/en/articles/15036540 OpenRouter live pricing — openrouter.ai/api/v1/models · Ollama pricing — ollama.com/pricing Devstral (72% SWE-bench) — tessl.io/blog/devstral · Pi harness — github.com/earendil-works/pi

Harnesses: solve_bench_tools.py · pi_bench.py + Pi · 11 models · 3 tasks · 60+ solve runs · real E2B · real OpenRouter / Anthropic / Ollama charges