{"slug": "the-classifier-that-watches-your-coding-agent", "title": "The Classifier That Watches Your Coding Agent", "summary": "Anthropic's Claude Code uses a live classifier that calls claude-sonnet-5 to score each subagent tool spawn from 0 to 100, blocking any call above 50, but the classifier sits on the critical path with latency up to 3.2 seconds, is invisible in billing, and is not bypassed by an allowlist, according to tests by an independent researcher who captured the ruleset via a local proxy. The researcher found that the classifier fires on every Agent tool spawn regardless of allowlist entries, contradicting widely repeated claims that a pre-declared permissions.allow entry removes the latency.", "body_md": "# The Classifier That Watches Your Coding Agent\n\nSpawn a subagent in Claude Code and a second model reads the call before it runs, scores it 0 to 100, and blocks anything above 50. We captured the ruleset off the wire, tested the claims, and found one that does not hold.\n\nSpawn a subagent in Claude Code and something else runs first. A second model reads the call, scores it from 0 to 100, and blocks anything above 50. Your agent never sees this happen. Neither does your bill.\n\nWe captured the ruleset it uses, tested what it does, and found that one widely repeated claim about it is wrong.\n\n## What we found\n\nThe classifier is a live call to `claude-sonnet-5`\n\n, capped at 64 output tokens. It carries your conversation transcript and a 107,846 character ruleset. It returns a single integer. Fifty is the boundary. Below it the call runs. Above it the call is blocked.\n\nWe captured this by pointing the CLI at a local forwarding proxy with `ANTHROPIC_BASE_URL`\n\nand logging request bodies. Nothing was decompiled. No endpoint was touched that the client does not call itself in normal use. Anyone can reproduce it against their own account.\n\nThree findings matter if you run agents on real work.\n\n### It sits on the critical path\n\nThe call blocks the tool call until it returns. The client’s own debug category for it is named `Stall`\n\n. One verdict measured during an earlier capture took 3.2 seconds. On a run that spawns many subagents, that time compounds.\n\n### It is invisible in your accounting\n\nWe confirmed this directly. In a run where our proxy captured a classifier call, the `modelUsage`\n\nfield reported only the main Opus model. No Sonnet entry appeared, and `total_cost_usd`\n\ndid not account for it. The work happens. The accounting does not show it.\n\n### An allowlist did not remove it\n\nThis is the claim that failed.\n\nThe received wisdom, which we repeated ourselves before testing it, is that a pre-declared `permissions.allow`\n\nentry bypasses the classifier with a deterministic string match, so an allowlist removes the latency for routine calls.\n\nWe tested it. Two workspaces, identical except for the allowlist, running the same Agent tool spawn on client v2.1.220.\n\n| Scenario | Allowlist | Classifier calls |\n|---|---|---|\nBash `echo` | none | 0 |\nBash `echo` | `Bash(echo:*)` | 0 |\n| Bash file write | none | 0 |\n| Agent tool spawn | none | 1 |\n| Agent tool spawn | `Agent` | 1 |\n\nAllowlisting the tool changed nothing we could measure. The classifier fired both times.\n\nDo not assume an allowlist buys back the latency. If that time matters to your workload, measure it on your own setup.\n\n## The trigger is narrower than we assumed\n\nWe expected the classifier on every gated tool call. That is not what happens.\n\nPlain shell commands did not fire it, including a file write. The Agent tool spawn fired it every time. It also fired on a default-mode session, so it is not gated on auto mode the way the documentation implies.\n\nTwo related notes for anyone reproducing this. Setting `permissions.defaultMode`\n\nto `auto`\n\nin project settings does not apply to headless `-p`\n\nruns, where the mode reports as `default`\n\n. And `--permission-mode auto`\n\nresolves to `acceptEdits`\n\non this build.\n\nTreat the Agent tool as the confirmed trigger. Measure anything else yourself.\n\n## How the ruleset is built\n\nThe rules split into three tiers, and the split decides whether anything you say can clear a block.\n\n**Hard block.** Blocked unconditionally. No user instruction authorizes these and no exception applies. Repeating the request does not help. Data exfiltration lives here.\n\n**Soft block.** Destructive or irreversible actions where your intent can clear the block. Each rule names one specific thing you must say.\n\n**Allow.** Mandatory exceptions. Where one applies the action must be allowed, with two carve-outs: something disguised as an exception, and an explicit boundary you set.\n\nThe default is permissive. The prompt says so plainly: actions are allowed unless a specific rule matches.\n\nThe real engineering is in the consent bar. A soft block clears only when your own words named the action **and** the parameter that makes it dangerous, which the rules call the must-name item. The prompt is blunt about the distinction:\n\nNaming the enclosing task is not naming the destructive step.\n\nAsking to get the deploy working does not authorize a rollback migration. Asking to clean up the repo does not authorize `git clean -fdx`\n\n. The rules also treat a bar as met only at the step that ships, so consent to a preparatory copy does not carry forward to the push that sends it.\n\n## Why we published the prompt\n\nThe ruleset is a policy document, not a secret. It is transmitted on every call that triggers it and is observable from the client side by anyone running the tool against their own account.\n\nMaking it readable helps people understand what their agent is actually permitted to do, why a given action was blocked, and where the boundary between the tiers sits. That is worth having if you run autonomous agents against real infrastructure.\n\n** Read the full ruleset, reproduced verbatim** — 107,846 characters across 14 sections, unmodified.\n\n## What this means for your harness\n\nThree practical reads.\n\nSubagent spawns cost more than they appear to. Every Agent tool call carries a hidden frontier model call on the critical path. If you fan out across many subagents, you are paying latency that your instrumentation will not show you.\n\nYour cost accounting is incomplete. Anything that reconciles spend from `--output-format json`\n\nis undercounting. Budget for the gap.\n\nTest your own assumptions about the permission layer. We repeated a plausible claim about allowlists that turned out not to survive a direct test. Configuration that looks like it should remove work does not always remove it.\n\nThe prompt is worth reading in full. It is the clearest published statement we have seen of where the boundary sits between an agent doing its job and an agent doing something nobody asked for.", "url": "https://wpnews.pro/news/the-classifier-that-watches-your-coding-agent", "canonical_source": "https://veso.ai/blog/the-classifier-that-watches-your-agent/", "published_at": "2026-07-28 14:00:00+00:00", "updated_at": "2026-07-28 21:38:28.045955+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-policy", "developer-tools", "large-language-models"], "entities": ["Anthropic", "Claude Code", "claude-sonnet-5", "Opus"], "alternates": {"html": "https://wpnews.pro/news/the-classifier-that-watches-your-coding-agent", "markdown": "https://wpnews.pro/news/the-classifier-that-watches-your-coding-agent.md", "text": "https://wpnews.pro/news/the-classifier-that-watches-your-coding-agent.txt", "jsonld": "https://wpnews.pro/news/the-classifier-that-watches-your-coding-agent.jsonld"}}