Terminal 3 Agent Developer Kit

An agent that can spend your money — without being trusted with it.

Gatekeeper proves an investor is eligible without seeing their identity, then enforces their spending mandate inside a TEE. The agent never holds the credentials, and it cannot widen its own limits.

Agent DID · did:t3n:3d7dd668ccf58ff2ac0fa8662572e12d35aad05f
Contract · z:3d7dd668…:gate — live on T3N testnet

Demo — 2½ minutes

Captions are burned in. Subtitle file: gatekeeper-demo.srt. Built with Remotion — the scenes are React, the narration is neural TTS, and every scene's length is derived from its measured audio rather than hand-timed.

The problem

Private-credit funds can only sell to accredited investors — and proving it costs everyone.

A fund like Meridian Private Credit is legally barred from selling to a non-accredited buyer. Today that means collecting passports, bank statements and net-worth attestations from every investor, then storing them: a compliance cost for the fund and a breach liability that grows with every new client. And when an investor delegates buying to an AI agent, the agent is handed the account credentials and trusted to stay within its limits.

Who this is for: tokenised RWA and private-credit distribution platforms, and the treasury or wealth agents that transact with them.

Investor delegates a mandate Agent proves eligibility (BBS+) Enclave enforces the mandate Order leaves the TEE, signed

The fund learns exactly one fact — this buyer is accredited — and never the net worth behind it. The mandate lives in the enclave's key-value store, so the agent cannot raise its own ceiling: the decision and the outbound order are the same enclave call, and a rejected action never reaches the network.

What shipped

0.7.0Rust → WASM contract, live on testnet
107automated tests — 28 Rust, 40 Node, 39 integration
19bugs & doc gaps reported with repro steps
8mandate dimensions enforced in hardware

The agent signs every outbound order with Web Bot Auth (RFC 9421), and its public key is published here — /.well-known/http-message-signatures-directory — so any destination can verify a request came from this agent with nothing shared in advance. That round trip is itself a test in the suite.

Evidence

Quickstart authentication output
QuickstartOne authenticated call. handshake → authenticate → getUsage against live testnet.
Contract get showing gate 0.6.0 live
WalkthroughThe Rust contract is live on the network. Anyone can verify it without a key — command at the bottom of this page.
Full agent run
Use caseThe whole chain, one run. Identity → BBS+ credential gate → revocation check → TEE mandate → audit row → signed dispatch. Six scenarios: one approved and dispatched for real (HTTP 200 from inside the enclave), five rejected, each with the enclave's own reason.
agent-auth-update grant accepted
Agent AuthThe caller authorises what the enclave may reach. An agent-auth grant scoped to contract, functions and destination hosts. Without it the same call returns egress_denied.
Agent registry record
Agent IDRegistered on-network. The DID resolves to an ERC-8004 / A2A agent card. (The owner_eth_address rendering here is bug #10.)
QA console approving an in-mandate action
QAHappy path. An in-mandate purchase approved. Every verdict comes from the contract's real Rust decide() — the rules are never reimplemented in JavaScript.
QA console rejecting an unknown counterparty
QAWrong path. An unlisted payee refused by name. Playwright drives six scenarios plus four API-abuse cases, including a negative amount that must not wrap past the cap.
QA console rejecting a self-issued credential
QAThe attack that matters. A BBS+ signature proves the issuer signed the claim — never that the issuer is anyone the fund trusts. An agent that mints its own "accredited investor" credential is refused against the mandate's issuer trust list.
Node test suite output
Testsnode verify.mjs — 85 checks in one command: Rust unit tests, a wasm component build, the Node suite, and Playwright over the real Rust decide(). No API key, no network, no credits.
token balance RPC error
Bug #9 — fixedtoken balance works now. We reported this in August, when every call failed on a params-sealing mismatch. Terminal 3 fixed it server-side; the command returns a real row. (The same server change is what broke SDK 3.5.2 — see bug #19.)
host-card NotScopeWriter error
Bug #11 — likely fixedNo more NotScopeWriter. The documented agent host-card step used to fail on a scope prerequisite the guide never mentioned. It now gets past that and stops only on credits, so the original defect appears resolved.
tee:organisation/contracts version 0.4.1
Bug #12 — fixedOrg-owned agents work. The CLI needed tee:organisation/contracts ≥ 0.6.0 while testnet ran 0.4.1, making that whole walkthrough page unusable. The node is on 0.17.0 now and agent create --org succeeds end to end.
trustAnchor CONFIG_ERROR next to the working form
Bug #20trustAnchor is required from SDK 5.x. The change is right — it pins the node's attestation — and the error is clear about the field. It just never names fetchTrustedManifest(), the one-line fix exported from the same module, and no changelog says which version introduced it.
card-publish refused for insufficient credit
Bug #21Metering is inconsistent and unpublished. At a balance of exactly zero, agent create --org minted a DID, issued an API key and hosted a card — free. Publishing that same card demands 10000000000, about 6.7× the entire initial grant. No price list, no pre-flight estimate, and an empty usage ledger to audit against.

Verify it yourself

No API key needed — the contract and the agent ID are public:

npx @terminal3/t3n-sdk contract get z:3d7dd668ccf58ff2ac0fa8662572e12d35aad05f:gate --env testnet
npx @terminal3/t3n-sdk agent registry did:t3n:3d7dd668ccf58ff2ac0fa8662572e12d35aad05f --env testnet

Or run the whole suite offline, no credits:

git clone https://github.com/PugarHuda/t3-gatekeeper-agent
cd t3-gatekeeper-agent/agent && npm ci && cd ..
node verify.mjs                                           # 85 checks, one command