An agent that can spend money, call tools and talk to other agents will, sooner or later, read something written by an attacker. OWASP ranks prompt injection first among risks to LLM applications, and no model-level defence has made it go away. The practical conclusion, stated plainly in Meta's Agents Rule of Two, is to assume injection will sometimes succeed and limit what a compromised agent can do.
That makes the harness, not the model, the safety boundary. This post sets out the design principles we use and how Tenzro enforces each one in consensus rather than in application code.
Principle 1: authority lives outside the agent
If an agent holds a private key, the agent is the authority, and whoever steers it holds that authority too. On Tenzro a delegated agent has no key of its own. Its authority is a Terms record on chain that its root approved, and nothing else.
Every action is checked twice: by the serving node before it signs on the agent's behalf, and again by the execution layer, whose verdict is final. Spend is counted in consensus state, so every node sees the same running totals, and there is no node-side policy store that could drift from the chain.
Principle 2: an accountable root behind every agent
Each agent has exactly one root, and its identifier is derived from it. A root is either a person, signing with a passkey, or a registered machine signing with its own TPM or Secure Enclave key. Every approval, whether creating Terms, changing them, revoking the agent or approving a single held action, is a challenge the root signs on its own hardware. A revoked machine identity approves nothing, and approvals are bound to the network's chain id, so an approval for one network is refused on any other.
Which roots an application accepts is the application's policy. A service that must keep a person accountable, as the EU AI Act's human-oversight provisions require for high-risk systems, can accept only agents with a human root.
Terms also expire by default. An agent acts only within a governed window (90 days at genesis) of its root last approving its Terms in full. Past that, every action is refused until the root approves again, so an agent does not outlive the person or machine that answers for it.
Principle 3: scope is an allow-list, limits are numbers
The scope an agent's root approves is concrete:
| Field | What it bounds |
|---|---|
max_transaction_value | The most one action moves |
max_daily_spend, max_hourly_spend | Rolling 24-hour and 60-minute spend |
max_actions_per_hour, max_actions_per_day | Action counts, value-moving or not |
allowed_hours_utc | The hours the agent may act in |
allowed_operations | Operations; anything unlisted is refused |
allowed_models, allowed_counterparties, allowed_chains | Allow-lists |
step_up_above, step_up_new_counterparty | Actions held for the root's approval |
Anything an agent asks a node to do is a typed proposal (an operation and the model or tool it names) validated against these fields before it runs. A tool call is checked again once the node knows what it executes: a URL fetch counts as fetch, a code executor as execute, a file manager as files.
An operator can read any agent's Terms, status and spend so far:
tenzro agent terms --agent-did did:tenzro:machine:<root>:<agent>Principle 4: hold the risky action, not the whole agent
Requiring approval for everything trains people to click approve. Tenzro holds only the actions that warrant it. An action above step_up_above, or the first payment to a counterparty the agent has never paid, is refused with a challenge. The agent resubmits the same action with the root's signature over that exact action digest. One approval covers one action, and it never lifts a hard limit.
Principle 5: no session gets the whole trifecta
Simon Willison named the lethal trifecta: private data, exposure to untrusted content, and the ability to communicate externally. Any agent holding all three can be steered into leaking data. Meta's rule of two expresses the same constraint as a design rule.
Tenzro enforces it in the Terms. Each operation counts toward three exposures:
- Private data:
files,database,memory,private_data, and any machine-access grant to the agent. - Untrusted input:
fetch,web_search,browse,inbound_messages. - External egress:
fetch,web_search,browse,message,webhook.
The execution layer refuses Terms that hold all three, and a node refuses a machine-access grant that would complete them, unless the root's signed Terms carry an explicit exception.
Untrusted input also leaves a mark. When an agent fetches outside content, or receives a message from anyone other than its root or an allowed counterparty, its actions through that node are marked tainted for an hour. The mark is part of the digest the serving node signs, and the agent can set it but never clear it. A tainted action that moves more than a configured limit, or pays a new counterparty, needs the root's step-up.
Principle 6: revocation has to reach everywhere, with a bound
A kill switch that works only on one server is a suggestion. Tenzro gives the root graded controls, each a transaction:
tenzro agent pause --controller <address> --controller-did <root did> \
--agent-did <agent did> --until <unix ms>Pause freezes payments; quarantine also freezes rewards and stake withdrawals; revocation ends the agent. Payment-channel vouchers stop being honoured from the moment of revocation, and a payee checking vouchers off-ledger runs the same check, so a revoked channel stops paying everywhere at once.
Authority on other chains is bounded in time and size by construction. An agent acts elsewhere only under a short-lived grant: by default at most one twenty-fourth of an asset's daily limit and ten minutes of life. Revoking the agent voids every live grant, and a remote account stops the agent at the latest when the grant expires. Short lifetimes and small budgets bound what a compromised serving node could spend in the meantime.
What this means for agent builders and policy makers
Put the boundary where an attacker cannot talk their way past it: in records the agent cannot edit, checked by parties the agent does not control. State limits as numbers. Hold individual risky actions rather than whole agents. Refuse the trifecta by default. And make revocation a transaction with a known worst-case delay, not a hope that every service hears about it.
Where Tenzro fits
Built: consensus Terms for delegated agents with passkey or machine roots, chain-bound root approvals, typed proposals checked by the serving node and the execution layer, rolling spend and action limits, allowed hours, step-up approval, taint marking, trifecta refusal, renewal expiry, pause, quarantine and revocation, and short-lived bounded grants on other chains. The network is live in preview; governance decides the steps to testnet and mainnet, including the governed defaults quoted here.



