{"slug": "60-of-my-312-anthropic-bill-came-from-one-silent-loop-here-s-how-i-found-it", "title": "60% of My $312 Anthropic Bill Came From One Silent Loop — Here's How I Found It", "summary": "An engineer discovered that 60% of a $312 monthly Anthropic bill came from a single retry loop in a Claude Code agent. The culprit was found by shipping Workers logs to R2 via Logpush and querying with DuckDB, revealing that one worker consumed 58% of total input tokens. The engineer recommends using KV counters for multi-agent loops and notes an unresolved issue with intermittent schema drift in tool call responses.", "body_md": "Last month's Anthropic invoice: $312. Sixty percent of it traced back to a single retry pattern I couldn't see anywhere in my normal logs.\n\nThe agent was failing on tool calls, then re-entering the loop with the full context intact — 18K input tokens per invocation on a task that needs 3-4K. Claude Code's UI looked fine. Workers logs showed 200s. D1 writes were clean. The billing dashboard just said \"tokens used\" with no breakdown by worker or call chain.\n\nI found the culprit only after shipping Workers logs to R2 via Logpush and querying with DuckDB:\n\n```\nSELECT\n  worker_name,\n  COUNT(*) as call_count,\n  AVG(input_tokens) as avg_input,\n  SUM(input_tokens) as total_input\nFROM read_parquet('s3://my-logs/workers/2026-05/*.parquet')\nGROUP BY worker_name\nORDER BY total_input DESC;\n```\n\nOne worker — `ad-report-summarizer`\n\n— was eating 58% of total input tokens. That query cost me maybe 20 minutes to set up. The Logpush + R2 + DuckDB stack runs under $5/month.\n\nOnce I had a suspect, I used Claude Code's `--verbose`\n\nflag to reconstruct the tool call chain. Most people treat `--verbose`\n\nas a log-level toggle. It's not — it dumps the full tool input/output JSON for every call in the session. Pipe it to a file, run `jq`\n\non it, and you can replay the exact sequence that blew up your context.\n\nFor multi-agent loops specifically (I run 6 Slack bots coordinated through Workers), KV counters have been the single most reliable safeguard. A counter keyed to the conversation thread, checked on every bot invocation, with a `last_actor`\n\nfield — when the counter approaches the limit, `last_actor`\n\ntells you immediately which bot is driving the chain. Six months in, it's almost always `summarizer-bot`\n\ntriggering `router-bot`\n\ntriggering `summarizer-bot`\n\nagain.\n\nThe harder unsolved problem: I'm still seeing intermittent schema drift in tool call responses — same prompt, same model, valid JSON but different structure. It's non-deterministic, doesn't reproduce on demand, and when it triggers a retry, costs double. I haven't confirmed whether it's a Sonnet serialization quirk or something in my Workers pipeline.\n\nI wrote up the full breakdown — including the `PostToolUse`\n\nhook setup for snapshotting tool call sequences, the `cf-ray`\n\ncorrelation trick for tracing multi-worker chains, and the per-tool production evaluation table — over on riversealab.com.", "url": "https://wpnews.pro/news/60-of-my-312-anthropic-bill-came-from-one-silent-loop-here-s-how-i-found-it", "canonical_source": "https://dev.to/riversea/60-of-my-312-anthropic-bill-came-from-one-silent-loop-heres-how-i-found-it-4oak", "published_at": "2026-06-22 01:11:26+00:00", "updated_at": "2026-06-22 01:40:01.838647+00:00", "lang": "en", "topics": ["large-language-models", "developer-tools", "ai-agents", "ai-infrastructure"], "entities": ["Anthropic", "Claude Code", "Workers", "R2", "DuckDB", "Logpush", "KV", "Sonnet"], "alternates": {"html": "https://wpnews.pro/news/60-of-my-312-anthropic-bill-came-from-one-silent-loop-here-s-how-i-found-it", "markdown": "https://wpnews.pro/news/60-of-my-312-anthropic-bill-came-from-one-silent-loop-here-s-how-i-found-it.md", "text": "https://wpnews.pro/news/60-of-my-312-anthropic-bill-came-from-one-silent-loop-here-s-how-i-found-it.txt", "jsonld": "https://wpnews.pro/news/60-of-my-312-anthropic-bill-came-from-one-silent-loop-here-s-how-i-found-it.jsonld"}}