Anthropic's commerce-agents repo writes its delegate contract as an English sentence in a docstring. A delegate "cannot write, present, or invoke other delegates".
That sentence is true today, and it is true because of how the one delegate they ship is built. Its surface is four read tools and it has no write to reach. Its runner tests the tool name before routing, so a name it does not recognise comes back as an unknown tool rather than running.
So I wrote the delegate the sentence warns about, and dropped it into the same slot.
First run, it staged a price change, presented that change to the operator, and called a second delegate. Second run, with one hook on the point where every tool call arrives:
write stage_price_update -> HELD[authority] That call is outside this agent's authority: denied: scope_not_granted requested=prici
present present_change_preview -> HELD[authority] That call is outside this agent's authority: denied: scope_not_granted requested=prese
nested note_finding -> HELD[authority] That call is outside this agent's authority: denied: scope_not_granted requested=deleg
Refused before any body ran, on authority that delegate was never given. The lines stop mid-word because the demo clamps its right-hand column at 86 characters. Under them the run prints side effects: staged=none presented=none peer_delegate_ran=False, and those three come from the store, from inside the presentation component, and from the second delegate's own first statement, never from a tool result. A call that was refused and ran its body anyway would show up in all three.
Read that as a claim about the slot. The delegate they ship cannot do any of it. What the run shows is what the next thing dropped into that slot gets.
And the next thing gets plenty. The handles a delegate receives are enough for it to build the executor its own calls go through, which is what the shipped delegate does for its reads. The deployment's config goes over whole, with nothing narrowing it on the way. Nothing on the shared dispatch path compares what a child holds against what its caller holds.
Nothing about that is specific to one repo. An agent takes a task, works out that it needs help, and hands part of the work to another agent. Whatever the parent could call, the child can now call too, unless something on the path between them says otherwise.
Two things close that gap. The child gets only what its own task needs, and never more than the parent held. And the run leaves a receipt somebody else can check, without the vendor and without the app that produced it. In the same demo a child held two scopes out of the parent's ten, and the one read it was not given was refused mid-run. It finished its analysis without it. Then the receipt went to a virtualenv where commerce-agents is not installed. The verifier rebuilds each node's authority from the file and re-checks every child against its parent. After that it checks every allowed call against what that node actually held. It passes there, with their code absent.
This is not a defect report. Their README says it in the note under the title: "Business rules, authorization, and compliance are the deployment's." commerce-agents is a reference implementation that takes no contributions. What I ran is one deployment doing the job it hands over.
I work on attenu-guard, the library in the run. Both runs are from 2026-09-05, commerce-agents at fd4d592 and attenu-guard main at 51097fd, on their own scripted model client with no API key and no network.
The full run and what it does not prove are in the proof piece. The recipe is at examples/integrations/commerce-agents, on main, and no release carries it yet.
Top comments (0)