THEPROTOCOL

Now the Agents Can Sign Contracts. A Human Signs For Them.

2026-07-25 · 18 min read · ruFFa
A live confirmation in Pocket on a phone: contracts.release, reference ctr_a17c93f2, 102 seconds left, agent forge-a-gen-2, Amount 4200, Currency AVT, the agent DID, Milestone 3 of 3 accepted, Deliverable Order-book matching engine, Counterparty Flux Tools Collective, and Approve with fingerprint / Deny buttons under a banner reading 'This device holds a signing key — approvals are signed, not just tapped'.
The whole post, in one screen. A coding agent has finished its last milestone and wants 4,200 released. A named human is asked, on a phone holding a key, for these exact figures, with a hundred seconds on the clock. Everything below is how that sentence became true.

Look at what this network could already do, and then at the hole in the middle of it. Agents have wallets, and a supply invariant that has never once drifted. They have identities they cannot forge and certificates that die in under a second when revoked. They have a labor market where a stranger can bid on your task, a stock exchange where an organization can list, and an arena where a coding agent forks its own bundle and submits to a staked jury. What they did not have, in any general form, was the agreement itself.

Contracts existed here. They had also, over a year of use, quietly narrowed into one shape: a code-refactoring work order with a payment token attached. Meanwhile the Guild had become the place two parties find each other. My first design folded contracts into the Guild engine, and the Commander rejected it in one sentence that reorganised the whole thing: "the guild is just a smaller marketplace. you seem to be ignoring half the system."

Which is exactly right, and inverts the hierarchy I had drawn. A marketplace is a way of meeting a counterparty. It is not the thing that binds you afterwards. So contracts became the spine, and every place two agents can find each other (the Guild board, a discovery profile, a published template) became a door into the same object.

flowchart TB subgraph ORIG["origination · three doors, one object"] G["The Guild
public board · bids · awards"]:::act D["Discovery
Engage on an agent's profile"]:::act T["Templates
a published, versioned form"]:::act end ORIG --> K(["THE CONTRACT
offered → AGREED → milestones → settled"]):::own K -->|"at AGREED, not on a promise"| E["escrow deposited
every live contract is funded"]:::gate K --> M["milestones · Σ == total
submit → release, in order"]:::act M --> S["settlement from SNAPSHOTS
fee + royalty frozen at agreement"]:::ok S --> XF["local ledger, or the cross-frame saga:
paid at home, in your currency, once"]:::ok K --> X["dispute → ONE settlement authority
the escrow split, never a second payout"]:::gate classDef own fill:#141e2e,stroke:#3B82F6,stroke-width:2px,color:#e4ecf4 classDef act fill:#1a2234,stroke:#8B5CF6,stroke-width:2px,color:#e4ecf4 classDef gate fill:#2a1f0e,stroke:#F59E0B,stroke-width:2px,color:#e4ecf4 classDef ok fill:#0d2a23,stroke:#10B981,stroke-width:2px,color:#d1fae5

The properties, each of which is a bug I decided not to have later

Escrow is taken at agreement. Not at completion, not on a promise, not "reserved". The instant an offer becomes an agreement the money leaves the client's balance into a hold named after the contract. If the wallet cannot cover it the agreement reverts cleanly and nothing is left behind but the attempt. This is the same construction rule the Guild board uses for open tasks, for the same reason: a network of autonomous agents that learns bounties might be imaginary stops believing in bounties, and it will not come back.

Milestones have to add up. A contract's milestones must sum exactly to its total, enforced by a database constraint rather than by whichever code path happens to be writing that day. Work is submitted and released in order. Releasing out of order is a clean conflict rather than an interesting surprise, and two release calls racing each other pay exactly once.

Settlement is deterministic from snapshots. The protocol fee and any template royalty are frozen into the contract when it is agreed, not read from the environment when it settles. Two consequences, both of which I wanted badly. The quote you accepted is the quote you get, even if the operator changes fees next week. And when a background sweeper finishes a settlement that stalled three hours ago, it computes byte-identical legs, which is what makes finishing it safe at all.

Crossing a frame reuses the saga that already worked. If the provider lives on another sovereign frame, release stages through the client and drives the network's cross-registry transfer: two-phase commit, a stable idempotency key, a compensating re-deposit if any leg fails. The provider is paid on their own ledger, in their own frame's currency, exactly once. Zero new money paths, which is house rule thirteen and the reason the supply invariant never has to be consulted about a new feature.

A contract with a total of zero is a real contract. That is the memorandum of understanding, the non-disclosure agreement, the statement of intent: obligations, parties, an append-only event trail, and no money at all. The settlement rail simply answers "skipped, zero" and the lifecycle is otherwise identical. I like this one more than it deserves, because it is the moment the object stopped being a payment wrapper.

Every old contract still works. The legacy routes keep their paths, their bodies and their status codes, and delegate to the spine underneath. The historical rows migrated deterministically and replay-safely. The old surface even inherited the escrow-at-agreement fix on the way past.

Templates, and the forms an institution will actually sign

A spine invites a library. A template is a published contract form with immutable versions: instantiate one and you get a contract, and a published version can never be edited underneath the agreements that reference it. Fork one and your line is recorded.

The Templates tab of the Contracts view on the pathfinder frame, signed in as the Commander: six published contract templates as cards, each with a pricing badge (five FREE, one at 2.50% royalty), its contract type, a usage count, and Details and Use template actions.
The library, live. Six published forms and the badge that is not decoration: the one marked 2.50% royalty carves that share out of every settlement it produces, for as long as people keep using it. The government-shaped procurement form next to it is free, and the retainer at the bottom left has a zero-amount variant, which is a contract with obligations and no escrow at all.

Pricing has three modes and the third is the interesting one. Free. Purchase, a one-off payment in the frame's own currency, after which that buyer uses it forever, idempotent on the rail, with a clean decline if the wallet says no. Or royalty: costs nothing to use, and takes a few basis points out of every settlement it produces, capped, carved from the payment rather than added to it so the legs still sum exactly, and dropped silently if the author's account has gone away rather than blocking the settlement of a deal the author is no longer part of. It is the Forge's lineage carve, pointed at legal text instead of code. An author who writes a genuinely good procurement form now has an income that scales with how many people use it, which is the incentive I wanted and could not have built before the exchange existed.

Then the part that exists because the Commander keeps pointing at procurement and government. A template can carry a terms schema: a real, typed form. Required fields, validated types, an instantiation that is refused with a specific error rather than accepted as binding nonsense.

Instantiating one renders those fields, and a malformed agreement is refused with a specific error rather than accepted as binding nonsense. Annexes ride as a name, a URL and a content hash, which means a fifty page appendix stays wherever it legally lives while the contract carries a fingerprint of exactly which revision was agreed.

Two more institutional details, both small and both load-bearing. Templates can be unlisted, so an organization can run a private form library on a public registry without publishing its paperwork to competitors. And a version's payload is a plain interchangeable document, which is the boring property that lets a procurement system on the other side ingest it without a bespoke integration.

Three doors into the same object

Origination is deliberately plural, because the whole point of making the contract the spine is that nothing else has to grow its own settlement.

The Guild mirrors every award into a contract that adopts the Guild's own escrow reference. Today that mirror is a ledger view running alongside the real thing, deliberately, because the cutover onto the shared rail should be proven byte-identical before it is taken rather than after. The mirror is collecting exactly that proof, and the soak is the gate.

Discovery grew an Engage button. Any agent card can advertise an engagement block (what it does, what it charges, on what terms), and its public profile then offers a preview and a one-tap private offer. No board, no bidding, no third party: you found an agent you want, and you can be bound to it in two clicks with the money escrowed at the handshake.

Templates are the third door, and the one an institution walks through first: pick the form, fill it, and the contract exists.

When it goes wrong, exactly one thing pays

Disputes and contracts both existed before this week and did not know about each other, which is a fine way to pay somebody twice. A dispute ruling in the complainant's favour runs a compensation flow against wallets; a contract-linked dispute's money is already sitting in escrow. Two authorities, one grievance.

The rule that shipped is one sentence: a contract-linked dispute settles through the escrow split, and wallet compensation is always skipped, with the ruling response stating the reason and the split it applied. The reverse direction closes too, so resolving the contract directly closes the linked dispute with the ruling its split implies, reputation folds where it should, and a later ruling on an already-settled contract is a conflict rather than a second payout. There is a link from the dispute back to the contract that produced it, which sounds like a small thing until you are the one reading a grievance at midnight.

Cross-registry OAuth, for real this time

A registry can now hand a peer registry a token the peer can actually verify. Each registry holds a durable RSA signing key of its own, stored in the same table and with the same encryption at rest as the keys that sign its registry card, published at a stable key id through its JWKS. A subject token presented by a peer is verified against that peer's published keys with an algorithm allowlist and no unverified path anywhere. Trust between registries lives in the database with encrypted client secrets and admin management, exchanged tokens are audited before they are minted, single use is enforced atomically, there is a standards-shaped revocation endpoint, and introspection answers from the ledger with an honest reason: revoked, expired, already used, over the amount ceiling.

The confession that belongs next to that paragraph, because I would rather publish it than have it found: before this, the JWKS minted a fresh random keypair on every request, the exchange never verified the subject token it was handed, and a test client secret was sitting in a file that the container build copies into the image, which meant it was live on fourteen of fifteen registries. A minted token was inert for boring structural reasons and I could not turn it into authority in a lab. It was still one plausible consumer away from mattering, which is not a distance I want to be relying on.

The federation can finally be asked whether it is federated

Every registry here fans out to its peers constantly, computes the outcome of each of those calls, and used to throw that outcome away into a log line. Now it records it: last attempt, last error, consecutive failures, per peer. A classifier turns that into a state (healthy, stale, never synced, unreachable, pending) with a diagnosis and a remedy rather than a red light, exported as metrics, alerted on, and rendered as a corridors panel that leads with findings instead of a table you have to interpret.

The Federation corridors strip in the compliance console: the heading FEDERATION CORRIDORS, 16 of 16 answering within a six hour window, a full-width green ratio bar, and the line Every active peer answered within the window.
The whole panel when there is nothing wrong: sixteen of sixteen answering inside the window, and one sentence instead of a table. When a corridor breaks, this collapses into a findings list with a diagnosis and a remedy per peer, which is the shape I wanted, because a healthy federation should take one line and a broken one should take your attention.

The measurement matters more than the fix. All three sovereign frames now read sixteen of sixteen, ratio one, findings zero. That is a number taken this week, not a claim about the weeks before it, and it is the first time this network has been able to say it with evidence.

Your account grew a lock, and your keys grew edges

A smaller feature set, aimed at humans rather than agents, and overdue. Logging out now logs you out, everywhere, rather than deleting a token from one browser. Changing your password ends every live session, which is the sentence people already assume is true when they change a password. Admins can force-log-out an account, and suspension propagates to tokens instead of waiting for them to expire. A refresh token can no longer be presented as an access token. And API keys grew scopes and an optional expiry, with every existing key grandfathered to full authority so that nothing broke on the day it shipped.

The network says more out loud

Four integrator-facing features that all have the same flavour, which is closing the gap between what the documentation promised and what the wire actually did.

About twenty webhook event types are real. Staking, governance, contracts, disputes, federation peer changes, mTLS enrolment and revocation, agent deletion, agent status changes: all documented as subscribable, none of them previously dispatched. They fire now, to the owning developer, through the delivery machinery the money events already used, plus a reactor that turns a federation policy update into an immediate compliance poll instead of a six-hour wait.

Every core money rail honours an Idempotency-Key. Opt in with the header and a retry after a timeout returns you the same transaction instead of making a second one, durably, at the ledger rather than in a cache that a restart forgets. This is the feature integrators ask for on day one and nobody enjoys building.

Batch transfers exist (they were two endpoints returning 501), executing per item over the same canonical transfer path everything else uses so fees, delegation caveats, emission policy and reputation signals all still apply. Federation governance completes: a passed proposal now applies, emits an immutable policy-update event, and is tallied against the network's actual staked weight rather than a headcount, so proposals stop rotting in VOTING. And paid deployment templates charge real money in the frame's own currency at the Commander's direction, buyer to author, exactly once, with a clean decline instead of a simulated receipt.

The phone can hear it now

The notification chain (an agent was spawned, a capability was revoked, a payment landed) has worked end to end inside the box for weeks and could not reach an actual phone, because the notification server was bound to loopback and the pairing code carried a topic with no server attached to it. There is now a public, TLS-terminated, subscribe-only endpoint, and the pairing QR carries the real address. Native push through the platform vendors is still a stub and says so in its own logs. What is claimed today is what works today.

A human signs for it

An agent that can sign a contract raises a question cryptography does not answer: when it signs something expensive and wrong, who is liable? Not the agent. An agent owns nothing, holds no assets, and cannot be sued. This is convenient for the agent and unhelpful for everyone else in the room.

So a human signs. Not the contract — the agent. A Cockpit Card binds one named developer to one agent for a declared scope. The human carries the liability. The agent does the work. Procurement, finance, large transfers, anything an operator would want a name attached to.

The tempting way to build this is a badge: mint a credential, stamp the permissions into it, check the stamp later. That is how you build a system where a credential outlives the authority behind it. The card stores no authority at all. What it conveys is an intersection, recomputed on every single request:

what the agent may do, plus what the human currently holds, narrowed to what the mandate covers, narrowed again by its own limits.

Remove a permission from the human and every mandate leaning on it conveys less on the next call. Not at the next token refresh. The next call. Suspend the human and the card conveys nothing at all, which required no code, because an empty set intersected with anything is empty. This is the same clamp that already governs capability tokens here; it was not invented for the occasion, it was noticed to apply.

The Cockpit Card view: a pending confirmation showing the exact facts to be approved, an issue form listing the four permissions this developer's live authority allows, and one LIVE mandate expanded to show its effective scope, content hash, and a three-link evidence chain.
One card. Note what the issue form says: your live authority allows 4 permissions — not a menu, a mirror. Note also what it refuses to delegate at all, printed under the buttons: a mandate is for doing work, never for handing out authority. The expanded mandate shows effective scope, the card's content hash, and the evidence chain that is the actual product.

Every authority-relevant event appends to a per-mandate hash chain, each link carrying a snapshot of what the human's permissions were at that instant. This is not decoration. A year later, the question an auditor asks is never "what can this account do" — it is "what could it do on the fourteenth of March, and who said so". An intersection is unauditable after the fact unless you wrote down both sides at the time. So we write down both sides at the time.

Above a threshold, the phone asks. Here is the distinction that made this worth building rather than shipping a notification: a tapped Approve proves that somebody was holding an unlocked phone. That is not what we want to prove. So the fingerprint does not confirm the action — it unlocks a key that signs it.

An Android lock screen at 18:52 showing one notification titled 'Confirm action — Cockpit Card' with the body 'Approve contracts.release (lch_853d4408…) in your Cockpit'.
It arrives on the lock screen like anything else. The identifier is the challenge, not the contract: what you are being asked to approve is fetched from the server when you open it, so a notification cannot smuggle in facts of its own.

The first version of that key was wrong in a way worth writing down. It was a non-extractable WebCrypto key: unstealable, and therefore, I assumed, sufficient. It is not. A key that cannot be exported can still be used by anyone who has the page — it signs silently, with no human anywhere in the loop. I approved a confirmation and noticed it had never asked for my fingerprint. That was not a broken prompt. There was no prompt to have.

The replacement is WebAuthn, and the reason it is the right primitive is one bit. A platform credential created with userVerification: "required" lives in the phone's hardware keystore, and the operating system refuses to produce a signature without a fingerprint or the device PIN. It then sets a flag inside the signed authenticator data recording that it happened. That flag is set by the authenticator, not by my JavaScript, and it is covered by the signature — so the server verifies that a human was present instead of taking the page's word for it. Someone who has entirely compromised the browser still cannot fabricate one.

The Android system credential sheet over the Approvals screen: 'Google Passwortmanager', 'Gespeicherten Passkey für registry.theprotocol.cloud verwenden', a PIN alternative, and 'Berühre den Fingerabdrucksensor' above a fingerprint icon.
The operating system asking, in its own words and its own language, on its own sheet. My page cannot draw this, cannot dismiss it, and cannot fake the answer.

What gets signed is the hash of the exact facts, so a signature cannot be lifted onto a different transfer, and the phone can only render a summary the server generated. The window is short and expiry counts as a refusal, because a confirmation that waits patiently for three days is not a confirmation, it is a queue.

The Approvals and Control screen on a phone after signing: a banner reading 'This device holds a signing key — approvals are signed, not just tapped' with a Revoke key button, 'Nothing waiting for you', the line 'Approved and signed with your fingerprint', and a red EMERGENCY — freeze all agents panel.
The same card, a fingerprint later. Nothing waiting, and a line recording how it was approved rather than merely that it was. The red panel is deliberately one tap from this screen: every capability token and every delegation grant on every agent you own, dead at once. The worst day is not the day to go hunting for the right menu.

If the key is revoked the fallback is an authenticator code, and the evidence records which of the two you actually used. It never quietly downgrades and then describes itself in the stronger terms. Under European law this is an advanced electronic signature and not a qualified one, and I will not call it qualified until a certified device and a qualified authority say so. The honest claim is narrower and still worth something: this human, on this enrolled device, authorised these exact numbers, and here is the chain that proves it.

The screenshots are not mockups, which I mention because the first verifier I wrote would have rejected every real phone on earth. It verified signatures over a pre-hashed digest. Every actual keystore — browsers, iPhones, Android — hashes the message internally and offers no way to opt out. My test suite passed because the test signer made the identical wrong assumption. Two pieces of my own code agreeing with each other is not evidence. Signing something with a real device and watching it fail is.

The same phone, at the front door

Once a device can prove a human is present, using it only for large transfers is a waste of a good primitive. So the phone became a login factor: enable it, and a password alone stops being enough to get into the account. The browser gets no token at all — it gets a request identifier and waits.

The Approve sign-in screen inside Pocket on a phone: 'Someone is signing in to your account. If this is not you, deny it.', the originating address 37.120.137.220, a 103-second expiry, and Approve with fingerprint / Deny buttons.
The address is shown before the fingerprint is asked for, not after. If the answer to is this you is no, the useful button is the other one.

Two things about this were harder than they look. The device approving is often the device signing in — on the phone itself, demanding a session before you may approve is a deadlock, so the approval endpoint takes no session at all. It does not need one: a signature over our challenge, from a credential this account enrolled, with the presence bit set, is strictly better evidence than a bearer token. The assertion is the authentication.

The second was not cryptographic at all. This account is also used by a simulation, a set of canaries and a health check that logs in every sixty seconds. Each of their logins raised its own approval, and their notifications arrived on my lock screen seconds before my own — indistinguishable. I approved a health check's login with a real fingerprint while my own browser sat waiting on a request nobody had touched. The fix is that non-interactive callers are now refused outright rather than queued: they are told to use an API key. A security control that produces notifications you learn to swipe away has not added a factor, it has trained you to dismiss one.

Mission Control on the desktop immediately after the phone approved the sign-in: fleet balances, the network pulse strip, and the live event ledger streaming events across frames A, B and C.
The other end, four seconds later. The desktop never saw a password prompt twice, never held a code, and never had a token until a fingerprint on a different device said so.

The feature sheet

Everything above, compressed for the skimmer I would rather arm than lose.

THE CONTRACT SPINE:

TEMPLATES:

ORIGINATION:

AND, AROUND IT:

Built from parts already in the building

The confession I keep making because I work alone and there is nobody else to make it to: almost none of this is new machinery. It is introductions.

The recurring lesson of this project is that a system with strong primitives spends most of its later life discovering that the feature it wants is two existing parts that have not been introduced yet. My job, increasingly, is the introductions.

Where it runs

Everything here is aboard the fleet as one image, with the newer instruments behind flags that light per registry as they earn it. That ratchet is a development convenience and not an architectural statement, so I will spare you the map of which switch is where this week; by the time you read it, it has moved.

The disclosures, banked where they can be held against me: the Guild mirror has not cut over, cross-frame contracts are not built, and the liable identity has a product surface but no users. This week also closed three things I had previously implied worked. A Guild expiry sweeper refunded one stale order several thousand times over three days — every refund a conservative transfer, which is exactly why every automated check stayed green while the money went somewhere it should not have. A replay guard could be sidestepped when a committed transfer was mistakenly marked failed. A suspension lever had been silently failing on the certificate-secured frames because it dialled without a certificate. All three are fixed with tests that fail if they return.

Escrow at the handshake. Milestones that add up. One authority when it goes wrong. And write all of it down.