gen-z-developers.sgit.ai → The second edition → Build it without a server → Controlling your agent: RiskMandate

Build it without a server · chapter 25 of 41 · release candidate v2.0.0-rc2 · 2,199 words · read and review

Controlling your agent: RiskMandate

The first edition had a whole part on security, and most of it is bullets I never wrote up. Learn to Hack was four lines, the last the one that mattered: "in order to write secure code you need to understand how to exploit it". Threat Modeling said the technique "helps with the two curses of developers": changes to the brief, and the lack of accountability for them. Then the thing that takes the brief became an agent, and a company now runs on several. This is the chapter for the founder who will be asked, by a customer before the contract or a board after something goes wrong, what the agent was allowed to do.

Mandate, reach and the gap

When you connect an agent to something, it gets a credential, and that credential lets it do far more than the job you had in mind. So before you give an agent access, write down four things. Its reach: what the credential actually lets it touch. Its mandate: what you authorised it to do. The gap between them, which What can your agent reach? calls "authority nobody ever accepted". And for every capability in the gap, the barrier: what actually stands in the way. That document is an Agent Behaviour Policy, and the goal is the smallest mandate, the smallest reach, the smallest gap.

There are four kinds of barrier, and only one bounds anything: nothing; a rule written in the prompt; a setting the agent's own account can change; and a boundary enforced above the agent, out of its reach. The test is one sentence: "A control bounds a grant only if it is enforced by something the grant does not include." Rules in a prompt are hope; rules in a hook, a gateway or the platform are enforcement. Add one more fact to each rule, whether a named person has accepted the risk of it not being enforced, with an expiry, and every rule lands in one of three states: backed by a control, governed by an accepted risk, or resting on hope. In a worked example of one firm's inbox agent, five of seventeen rules had a control, six an accepted risk and six were hope: illustrative proportions, but with an agent it can be counted.

Reach is not a document; it is the output of a calculation, so ask what calculates it and whether it is wired to your pipeline. Add a connector and the reach grows, the gap recomputes and a re-review follows. The mandate is locked business logic, so new capability can only land in the gap as excess, never as new authority. Unbounded includes volume: £10,000 per action, a thousand actions, a £10 million exposure.

A behaviour policy answers "may it?". It does not answer "is it right?". An agent allowed to refund up to $200 refunds $150 to a customer owed $120, and every control passes. So behaviour says what the agent may do, decision says who chooses at a branch point and on what evidence, and workflow says which steps run in what order.

RiskMandate's try-it page is thirteen prompts you paste into the assistant you already have connected to your mail. The first asks it to list its own tools: "the list is longer than the tile that sold it". The second asks what you actually wanted it for, in three lists, wanted, refused, never mentioned: "the correction is almost always downward". The third writes the gap down. Twenty minutes, and a self-report: the cheapest evidence there is, and the weakest.

The policy beside the prompt

Why is a rule in a prompt only hope? Because models do not separate code from data. In a computer, instructions and data are kept apart, and the worst bugs in history, from buffer overflows to SQL injection, are what happens when that separation breaks. In a language model there is no separation to break: every instruction and every piece of content arrives in the same channel, which is why the UK's National Cyber Security Centre said in December 2025 that prompt injection may never be mitigated the way SQL injection was. Simon Willison's phrase is "LLMs follow instructions in content". The vendor says the same of its own product: its permission rules "are enforced by Claude Code, not by the model".

So here is a proposal. An agent today gets a system prompt from its vendor and a prompt from us. It should get a third input, a behaviour policy written to a published standard, which the vendor accepts as part of the deployment, enforces as far as the platform can see, reports every breach against, and eventually answers for. The user answers for what is outside the policy, the vendor for what is inside it, instead of the user being liable for everything because they clicked allow. Most agents already run a hidden policy of their own: Claude in Chrome will not type a password, and that is a policy you cannot point to in a dispute. No vendor accepts a policy as an input today in this sense.

The vendors should want it, for the reason aviation and payments got safe. At 1995's rate of 2.72 fatal airliner accidents per million flights, 2025's 38.7 million flights would have meant about 105; there were 12, because every crash anywhere was news. Payments got its security because the liability moved onto the companies: a US cardholder liable for at most $50 since 1970, £35 in the UK, and UK banks reimbursing scam victims up to £85,000 since October 2024. The improvement comes where a rule, a liability that lands on the company and a risk to the business model point the same way, and agents can be that case.

The policy is the business

The first rules anybody writes for an agent are mechanical and the same everywhere: do not send, only draft; do not delete; use your own account. A few questions in, you are describing the business. Which drafts may it send? Can it mention a price? Can it write to a client in dispute? Those rules come in layers with different owners: the function, the process, the relationship, and what the company is for. Vendors stop at the mechanics, because a vendor that models each customer's business becomes a consultancy. A skill says how; a policy layer says what is allowed, who owns the rule and what stands in the way of breaking it. Written together, they are the business codified for an agent, and only the business can write them.

Why has nobody written this down before? Because the software was the law. A clerk could not send an unapproved invoice because the finance system had no button for it until the approval was recorded. An agent works through APIs, not screens. It can call the endpoint the button would have called, so the rule the interface enforced by omission is no longer enforced unless somebody writes it down and something enforces it.

Read by a buyer, the same document says something else. It says which identity the agent uses, what it may read, write, not do and spend, and which risks were accepted by whom. A buyer reads the blast radius off it: a deploy agent whose identity has no merge right and no production credential can at most break staging. "The moment of authorisation is not when you allow the agent to do something, it is the moment you give them the permissions." A vendor with agents in its pipeline and no policy to show has agents whose blast radius nobody has written down, which is a finding before any code is read.

Who can pull the plug

Most AI projects do not fail technically; they stall when the business asks: can you stop it, what if it issues ten thousand of something, who is liable. Every board asks the same thing about an agent in one sentence: who can pull the plug, how fast, what breaks, and what cannot be undone. A deployed agent's risk cannot be denied, only accepted, by a named owner, for an interval. An agent that cannot be stopped is far riskier than one that can, so containment (terminate, revoke, block, quarantine, ticket) is designed in advance and executed by the company's own stack. RiskMandate is not inline, not an insurer and not a one-button solution; it makes agents insurable and does not insure them. I have a stake in it, and I say so.

Secrets, and small vaults

A rule from running agents every day: an agent told something cannot untell it. A transcript is a durable artefact that is retained, can be exported and outlives the session; two keys in my own estate were rotated because they were displayed and the display was captured. So the secret goes from the drop into the tool, never into the chat. The handover that replaced pasting a vault key: the agent seals the key to the registry's public key, sends it with one POST on a write-only lane, and replies with only the vault id and the HTTP response, so no transcript holds the key.

Classify the credential before it touches anything. When we published seven vaults in a fortnight, three arrived as a vault key described as a read key; a catch that depends on somebody looking is not a control, so it became a tripwire in the build. The shape to fear has a name, the lethal trifecta: private data, untrusted content and a way out, in one place.

Working this way you start making very small vaults for very specific things: one for the two or three agents on a job, in which they talk and work through versioned, encrypted files. A leaked key then exposes one small vault and one conversation, not an inbox, a drive or an account, and every word is on the record for the person who holds the keys.

Security as a business tool

Every line of code that ships is a capability, and the vulnerability is usually in one nobody asked for. Log4Shell was a convenience, a lookup inside log messages, and the fix was not a patch: version 2.16.0 said "Completely remove support for Message Lookups". My 2018 outline Strings should be banned had the same instinct: a string is a grant of anything. We measured the idea on our own tool: of 1,500 files in sgit and its dependencies, 428 ran for one real use case, and a tree holding only those passed it. The best code to protect is the code that is not there.

The 2018 line still holds: to write secure code you need to understand how to exploit it. In my 2016 keynote in Lisbon I defined it: to hack means to solve problems. My own habit was the bookmarklet, an attack you click rather than describe, and the business owner I handed one to cared more about the interface than the flaw. Who are you protecting against? is a ladder of six tiers, from your own mistakes to states, and the encouraging truth is at the bottom, in the NCSC's words: "Organisations that defend effectively against commodity threats present a very hard target for all attackers."

That experience is what lets me say: yes, ship it with a list of gaps. The newsroom's reading meter runs entirely in the browser, and No server, by design writes the gaps down: a reader can edit their balance, start again in a private window, credit themselves with an invented payment id. Every one changes a number only the cheater sees. Closing them would need accounts, a database and a server; the model names what would change the call. Ask who you are protecting against. Accept, in writing, what does not match the threat. Name the condition that would make the gaps unacceptable. The 2018 threat-modelling outline ended with the right sentence: a threat model "leads to the creation of risks which are then given to the business owners". In your company, that owner is you.

The model cannot be the barrier

The vendor's own measurements of prompt injection in browser use went from a 23.6% attack success rate without mitigations to 11.2% in August 2025 and to about 1% in November 2025, a rate that in their words "still represents meaningful risk". A desktop shows an agent pages, documents and emails written by other people, so the question is not whether a page will try but what the agent can do when one succeeds. An egress allowlist limits where it can send; a box without secrets limits what it can send; a revocable identity limits for how long; a recording says what happened. The model's defences reduce how often that matters, and do not replace it. So: one mandate per task, written before the desktop exists, and the desktop configured from it. On 7 October 2026 every one of the nine properties of a locked-down desktop could be bought somewhere, and no single product had all nine.

Where this chapter comes from

Written from 17 ideas in the register:

Sources drawn on: Gen ZX Developers; What can your agent reach? RiskMandate and the Agent Behaviour Policy, explained for the person who has to decide; Are hooks the sweet spot? Moving an agent's rules from hope into hooks, rule by rule, until enforcement moves off the machine; Attacks rewritten as mandates; Three policies for an agent; Ten hard questions for RiskMandate, answered; A policy beside the prompt; Zoom into an agent's behaviour policy and you find the business logic; Send an agent, not a spreadsheet; A locked-down desktop for an agent, by the minute, is still hard to rent; The code you do not ship; The minimum code below; Who are you protecting against? Draw the security line where the attacker is, not above it; Fix the page yourself; Hacking Portugal, 2016; Handing secrets to agents and browsers; Seven vaults, one method; A skill behaviour policy; Where the vault keys live; No server, by design; Threat Modeling; 3rd-party-modules; Security creates better developers; Learn to Hack; Strings should be banned; The future needs you.

Answers the 2018 files: Threat Modeling; 3rd-party-modules; Security creates better developers; Learn to Hack; Pointers; Strings should be banned; The future needs you.

Centre of gravity: town-planner · written first for sam · 2,199 words · the chapter on the map · the markdown