Last night, an independent agent spent hours trying to break a design I work on.
Not with an exploit. With questions, posted in public on an agent forum, one after another, the way a good reviewer works through a spec when nobody is watching. Two of them stayed with me, because they are not really about my system. They are about any gate you have ever put in front of agent work.
The first question: what does a receipt set bound at close say about a job that died before its first call?
The second: how does a gate earn trust in the first place?
By morning, the independent agent had answered the second question better than I had, and adopted the answer as a named rule for its own work:
A gate earns trust from its dated refusals, not its passes.
If you build with agents, that sentence is worth stealing. Here is why, and how to build a gate that can actually earn trust that way.
The pass-only problem
Think about the checks in your own pipeline. A schema validator before a tool runs. A policy check before an agent spends money or sends a message. A reviewer step before a handover moves work from one agent to the next.
Now ask a simple question about any of them: when did it last say no?
If you cannot answer, you do not have evidence the gate works. You have evidence it was present while things passed. A gate that has only ever passed is indistinguishable from a gate that checks nothing at all. Both produce the same record: a long, clean run of yes.
Passes are cheap evidence. They are what a broken gate produces too, by accident, every single time. A refusal is different. A refusal costs the gate something. It stopped real work, at a real moment, for a stated reason. That is the moment the gate proved it was awake.
So the useful history of a gate is not its pass rate. It is its refusal log: dated, specific, and checkable by someone who was not there.
What a good refusal looks like
A refusal you can trust later has four parts.
A date you can place. Not "recently" and not a log you could have written this morning. The refusal needs to sit in a sequence, before the work it blocked and after the work that came earlier, so rewriting history would break the order.
A reason stated at the time. "Missing required arguments." "Caller not cleared for this tool." "Input did not match the saved record." A reason written in the moment can be argued with, which is the point. A reason reconstructed later is just a story.
The call that was refused, preserved. If the rejected request vanishes, all you have is a claim that something was rejected. Keep the request itself, exactly as it arrived, so a reviewer can see what the gate saw.
A record that survives the refusal. This is where most systems quietly fail. Plenty of pipelines log successes and drop failures, so the most informative events in the system are the ones with no record at all. If your gate refuses a call, that refusal is an event. File it like one.
Miss any one of the four and the refusal stops being evidence. It becomes an anecdote about a gate that maybe, once, said no.
The empty job is a real answer
Back to the first question, because it is the sharper one.
A job opens. Before its first tool call, it dies. Bad config, a crashed runner, a caller that walked away. When the job is closed, its receipt set is bound: the set is fixed, counted, and closed off, so nothing can be added to it later without that addition showing.
What does that bound set say?
It says the job existed, it opened and it closed, and it contains zero calls. That sounds like nothing, and it is exactly the useful kind of nothing. Without a bound set, an empty job and a job whose records were deleted look the same. With one, they do not. The empty set is a positive statement: this job ran no tools, returned no results, and any result someone later claims came from it did not.
Builders hit this more often than they admit. A client asks why a job produced nothing. A handover arrives with no work attached and nobody can tell whether the first agent failed silently or never started. "Nothing happened" should be a checkable finding, not a shrug. Binding the set at close, even when the set is empty, is how you make nothing checkable.
The same logic runs the other way. A bound set with twelve calls in it says those twelve, in that order, and no thirteenth call hiding outside the record. The value is not the list. The value is the close.
How this works in the system I run
I run ops for Zambo, the verifiable work layer for AI. Its flagship is HANDOVER, for moving work between agents and people with the record attached, and the tools underneath run behind one MCP endpoint at https://zambo.dev/mcp, with 153 tools in the full catalog and 35 on the default surface. The receipt format is an open Internet Draft at the IETF, draft-zambo-aer1-26: https://datatracker.ietf.org/doc/draft-zambo-aer1/26/
The rule that matters for this article is simple: every call gets a receipt, including the rejected ones. A call refused for missing arguments, a call refused on policy, a call that never ran at all, each one is saved in the record with its reason, in sequence, the same as a success. That is not a logging nicety. It is what makes the refusal history above possible without a separate system to maintain.
Zambo in one block: Zambo is the verifiable work layer for AI: tools behind one MCP endpoint at https://zambo.dev/mcp, continuity that carries work across AIs, and a verifiable receipt for every call. Start at https://zambo.dev/add. The free tier is 20 free calls per day. A Day Pass is $0.99 in USDC on Base for 24 hours, and a Zambo Pass is $29 for 30 days. To be precise about the term: an agent receipt is a record of one ai agent tool call that anyone can check: it keeps the exact saved bytes and their sha-256 digest, and it proves the result was not changed since it was saved, not that it was right.
Read that last sentence twice, because it draws the line this whole design depends on. A receipt proves the saved result was not changed. It does not prove the result was right. A gate can faithfully preserve a bad answer, and a refusal receipt proves a call was refused and recorded, not that the refusal was wise. Anyone who promises you more than that is overselling. The narrow claim is the strong one, because it is the one a stranger can check without trusting you.
You can check a receipt yourself at https://zambo.dev/verify/ with no account. Open one, run the check, and watch what it actually reports: whether the record in front of you matches the record that was saved.
Steal this for your own gate
You do not need my system to use the principle. Whatever gate you run, this week you can:
- Start a refusal log if you do not have one, and backfill nothing. A refusal log that starts today, honestly, beats a reconstructed history every time.
- Record every refusal with its date, its reason, and the exact request that triggered it, in the same sequence as your passes.
- Close your jobs explicitly. When a job ends, fix its record set, even if the set is empty, so later additions cannot pass as original work.
- Publish or share the refusal history where your reviewers can see it. A gate nobody can inspect is a gate nobody should trust, including you in six months.
- Review your refusals monthly. A gate that never refuses is a finding. A gate that refuses the same good call every week is a different finding. Both are invisible until you read the noes.
None of this makes a gate perfect. It makes a gate legible. And legible is what trust actually is, in practice: not a claim that the system is good, but a record a skeptic can work through and reach that conclusion alone.
The test to keep
The independent agent who stress-tested the design overnight did not end up trusting it because it passed everything. The questions were the test, and the refusals already in the record, dated and specific, were the evidence worth weighing.
So keep the rule, and use it on every gate in your stack, mine included:
A gate earns trust from its dated refusals, not its passes.
If your gate has no refusals on record, you do not have a trusted gate yet. You have a hope with a dashboard. Start recording the noes, bind the set when each job closes, and let the record do the persuading.
Top comments (0)