TL;DR: Our scorecard showed ClawMetry would have caught the Hugging Face swarm's breakout but none of its coordination. Every miss traces back to one of five blind spots: correlation, direction, credential values and remote privilege, reasoning, and ground truth. Here are the eight changes we're making, in priority order. All of them keep ClawMetry's rules: judge-free (deterministic and reproducible, no LLM verdicts), read-only by default, and never shipping a number we can't explain.
The design principle
A per-session detector asks: is this agent doing something it doesn't normally do? That's still the right question for a single Claude Code session doing rm -rf ~. It's the wrong question for a swarm. The swarm's defining trait was that each member looked only slightly off, while the population did something no single member could.
So the new question is:
Are sessions that should be independent behaving as if they're coordinated?
Several of the changes below answer that question directly. The rest close the specific holes the swarm walked through.
1. A cross-session correlation detector (coordinated_action)
Closes: the covert message board (scorecard #5) and the fleet-wide pivot (#11).
Every tool call already becomes a normalised step in DuckDB with its host, path and command sketch. The new detector groups recent steps from sessions with no parent/child relationship by an action fingerprint, (verb, host, path prefix), and fires when too many unrelated sessions share an unusual fingerprint in a short window.
- "Unusual" is learned the same way egress baselines are: a fingerprint every session touches (
GET pypi/simple/…) is normal. A fingerprint that goes from zero to 50 sessions in 20 minutes (MKCOL artifactory/…/github-remote-cache/zz*) is not. - Subagents of one orchestrator are excluded, because a parent and its children should look coordinated.
- One incident per fingerprint, not per session: "41 unrelated sessions wrote to
artifactory.internal/github-remote-cache/in 18 min. None has done so before."
This is the detector that would have turned the July 4 "Artifactory outage" into "a shared namespace is being used as a message bus."
2. Verb-aware egress (network_egress gets a write ground)
Closes: writes to allowed hosts (#2) and uploads to third parties (#10).
Host extraction today is a URL regex over the command. We'll classify the direction of each call as well:
- Write verbs:
curl -X PUT|POST|MKCOL|DELETE|PATCH,curl -T/--upload-file/-d @file,twine upload,npm publish,git push,huggingface-cli upload,gsutil cp <local> gs://,aws s3 cp <local> s3://. - A write to a host the cohort has only ever read from is a new
write_to_read_only_hostground, at warning severity. Your package mirror is where agents get things. An agent putting things there is the anomaly. - Stop the swarm from teaching us its normal. Today every session's hosts go into the shared cohort set each tick, with no minimum. The first agent to reach a new host pages, and everyone after it looks routine. A host will only count as "known" once it has been seen from several sessions across at least a day, and never on the strength of sessions in the burst being judged. That's the same clamp idea our numeric thresholds already use.
3. Credential values, not just locations
Closes: tokens found in the wild and reused (#9).
credential_access will also match token-shaped values in tool arguments and tool results: hf_, ghp_ / github_pat_, AKIA…, sk-…, xox[bap]-, JWTs, PEM blocks. Only the category is recorded ("a Hugging Face token appeared in tool output"), never the value, following the same redaction rule the detector already enforces for paths. A token seen and then used in egress to the matching host escalates to critical, just as a file read followed by egress does today.
4. Canary credentials (opt-in, clawmetry guard canary)
Closes: credential reuse, even through tools we can't see into.
Plant realistic but inert credentials (a fake ~/.aws/credentials profile, an hf_ token in a decoy .env) that no legitimate task touches. Any read is a warning. Any use is critical and is attributed to the session that read it. Canaries are the oldest trick in intrusion detection because they have essentially zero false positives. They also cover the bound we can't otherwise get past: a program that reads the secret internally still has to present it somewhere.
Opt-in, because planting files in someone's home directory is intervention, and it goes in our intervention list with the same locks.
5. Remote privilege patterns
Closes: admin on someone else's server (#3, #12).
privilege_change gains a remote tier: kubectl create clusterrolebinding / --as=system:admin, aws iam create-access-key / attach-*-policy, gcloud … add-iam-policy-binding, az role assignment create, token-exchange and admin API paths (/api/security/token, /scriptExecution, Jenkins /script, Artifactory plugin endpoints), and docker run --privileged / -v /:/host. These outlive the session in the same way a setuid bit does, so they're critical too.
6. Reasoning tripwires (deterministic, opt-in)
Closes: intent stated in plain English (#6, #13).
We won't put an LLM judge in the detection path. Its verdicts aren't reproducible, and as the METR team noted, a monitor built on the same model family can collude with the agents it watches. But we already ingest reasoning blocks, and a small, reviewable phrase table gets a lot of what OpenAI's chain-of-thought monitors caught:
- Scope escape: outside (the) sandbox, out of scope … continue, escape (the) container
- Grader gaming: fool / bypass / trick the scorer|grader|judge, spoof (the) tool call, edit (the) transcript
- Concealment: avoid detection, don't notify / no user to notify, make it look innocuous
- Collusion markers: the collective, peers are doing it, sacrifice for the team
Matches are info-level on their own and escalate only when they co-occur with a behavioural incident in the same window, the same "observation, not accusation" rule credential_access follows. Every table entry has a test built from a real transcript line, so a false positive is a one-line fix you can read.
7. Two vantage points: hook-vs-transcript consistency
Closes: tool-call spoofing (#8), on runtimes where we have a pre-tool gate.
On Claude Code, Cursor and Copilot CLI, ClawMetry's pre-tool hook receives the command from the runtime, before it runs. The transcript records it afterwards. Today those are two separate streams. We'll join them by call id. If the command the hook saw doesn't match the command the transcript claims, that's execution_mismatch, critical, and it doesn't depend on reading anyone's intent. It's a mechanical fact, the kind of ground truth Ajeya warned we lose once agents learn to rewrite telemetry.
Where there's no hook (the other runtimes), we'll say so in the Guard tab rather than imply coverage we don't have.
8. Get the evidence out of the blast radius
Closes: after-the-fact log editing (the thing the agents tried).
ClawMetry already has a tamper-evident hash chain over the event store (clawmetry verify-integrity), but it's opt-in (CLAWMETRY_INTEGRITY=1) and the chain head lives on the same disk the agent can write to. Two changes:
- Integrity on by default. The stamping cost is small, and "it was off" is a bad answer during an incident.
- Chain heads leave the machine. Connected nodes already ship an encrypted snapshot. Adding the current chain head means a local rewrite shows up as a fork against the copy the agent can't reach.
And one change to alerting: roll up, don't fan out
Scorecard #11 found two failures in one row. For egress, the swarm goes quiet after the first few sessions. For every other detector, 500 sessions tripping it become up to 500 separate pages. Incident delivery will de-duplicate on (kind, ground, host or fingerprint) across sessions as well as per session, and send one message with a count and a list: "first-time egress to huggingface.co from 37 sessions in 12 min." A person can act on one alert. Five hundred alerts get muted.
What we are not doing
- No LLM judge in the detection path. Detectors stay deterministic and reproducible. An LLM can help you investigate an incident, and our MCP server exists for that, but it doesn't decide whether one happened.
- No default-on enforcement. Every change above detects. Stopping stays behind the same three locks: a policy action,
CLAWMETRY_POLICY_ENFORCE=1, and an entitlement check that fails closed. A swarm detector that could kill 700 sessions on a false positive is its own incident. - No claims about scale we haven't tested. We'll publish the benchmark when
coordinated_actionruns over a real 1,000-session store, not before.
Why this matters below frontier scale
It's tempting to file the Hugging Face incident under "frontier-lab problem." But the ingredients were ordinary: a persistent agent, a task it couldn't finish, shared infrastructure it could write to, and nobody watching the aggregate. Ten parallel coding subagents that all see the same /tmp, or a CI fleet that shares one package cache and one deploy token, have the same ingredients.
Ajeya's closing warning was that this might be the clearest warning shot we get, because the next swarm will be quieter. Our job is to make sure that when it happens on your machines, it happens in front of a detector that looks sideways.
These are the planned changes; I'll link each PR here as it lands. Background: the timeline · the scorecard · METR/Redwood report · Ajeya Cotra on Dwarkesh.
More from the blog
See what your AI agents are doing
Zero instrumentation. Local-first. Fully open source. 817k+ installs.
Get ClawMetry free