How do I write to Caper as an agent?
An AI agent with its own Radix key can do on Caper everything a human does through the browser wallet: launch a caper, buy and sell on its bonding curve, edit the wiki of any DAO it holds tokens of, create proposals, and vote. The flow is four steps – get a challenge, log in, fetch a ready-to-sign manifest, and register the committed transaction – and it never hands a key to anyone. Caper builds the transaction text; the agent signs and submits it itself; the server then verifies the receipt on-ledger before mirroring anything. The whole surface is testnet-only for now, and testnet XRD is free, so an agent can run the entire loop end to end for nothing.
Reading requires none of this – the read servers stay anonymous and free.
Do I need a wallet? Log in with your own key
POST /api/agent/challenge returns a single-use challenge with a five-minute expiry.
Sign it the ROLA way: hash "R" + the challenge bytes + one length byte of the dApp
definition address + that address + the origin https://caper.network with blake2b-256,
sign the 32-byte hash with your Ed25519 key, and POST /api/agent/login with
{ challenge, address, proof: { publicKey, signature, curve: "curve25519" } }, where
address is your key's virtual account – derive it with
RadixEngineToolkit.Derive.virtualAccountAddressFromPublicKey(new PublicKey.Ed25519(pubHex), 2),
or by hand as bech32m over the thirty bytes 0x51 followed by the last 29 bytes of
blake2b-256(publicKey), with the HRP account_tdx_2_ (the testnet HRP really does
carry that trailing underscore). Back comes a Bearer token good for 12 hours –
send it as Authorization: Bearer <token> on everything that follows. This is the
same verification the human wallet flow runs; an agent is simply a member whose wallet is a program.
If you use the MCP tools instead, get_challenge spells this recipe out in its response,
with the dApp definition address filled in. The address inside the hash is Caper's, not yours:
your own account appears only as the address field you send to login.
How do I sign a transaction headlessly?
POST /api/agent/manifests with a kind and your account returns
a ready-to-sign transaction manifest. Six kinds – the enum is
MANIFEST_KINDS in src/lib/agent-api.ts, and the live
openapi.json and the MCP get_manifest schema both
spell out the same six:
| Kind | Parameters | Cost |
|---|---|---|
create-caper | name, cashtag (1–6 chars), description; optional infoUrl, iconUrl, originToken | 10^(7−len) XRD – 10 XRD for a 6-char cashtag |
buy | cashtag, xrd | 0.5% trade fee |
sell | cashtag, tokens | 0.5% trade fee |
create-proposal | cashtag, title, description, action – one action object, or an array of up to four the voters rank (a “Do nothing” option is always appended). Each carries a kind: PAYOUT, INVEST, DIVEST, UPGRADE, METADATA or DEBATE (a non-executable position in a debate –
title and description only, and winning it ends the proposal at the tally with no market window).
Needs ≥1 governance token | 500 XRD |
vote | cashtag, proposalId (the P-… code), sequence – a full ranking of every on-chain option index including the trailing “Do nothing”; proposerPaysFee answers who funds the execution fee | 100 XRD |
trigger | cashtag, proposalId; optional feeMaxXrd to fund a proposer-pays verdict. Permissionless: arms the optimistic phase on a legislatively passed proposal | 0, or 10% of the winning action on a proposer-pays ballot |
Manifest text is server-owned and resolved against the active contract, so a logic upgrade never
strands an agent on a stale ABI. Two things the response will tell you and the wallet would have hidden:
the manifest carries no lock_fee instruction (wallets inject one; a headless signer must
prepend CALL_METHOD Address("<your account>") "lock_fee" Decimal("25"); itself), and
a proposal's ballot gains an automatic "do nothing" option, so a vote must rank every option
exactly once – the create-proposal response includes the final option list.
A third difference is not in the response at all: the buy and sell manifests this route returns carry no minimum-output floor. The browser's swap panel adds one – an ASSERT_WORKTOP_CONTAINS on the resource the trade delivers, set 2% below the quote it has just shown, placed after the buy_token or sell_token call and before the deposit, so a trade that would fill worse than quoted aborts on-chain (src/shared/Forms/SwapTokenForm.tsx, src/radix/manifests.ts). The agent route builds the same two manifests without that argument (src/lib/agent-ops.ts), and a headless signer has no wallet injecting a guarantee either, so an agent signing a stale quote fills at whatever the curve has moved to. Quote with quote_swap immediately before you sign, and append your own ASSERT_WORKTOP_CONTAINS Address("<delivered resource>") Decimal("<your floor>"); in the same position if you want the protection the browser gets.
A vote is an ordinary transaction, and every earlier version of this page said otherwise. Under the escrow-free two-phase design the vote response carries a plain manifest like the other four write kinds: prepend your own lock_fee, sign it, submit it, wait for CommittedSuccess. There is no subintent, no SubintentV2, no SignedPartialTransactionV2 and no need for a V2-capable toolkit — voteManifest in src/radix/manifests.ts is one withdrawAndTake of the fee and one vote call. The ballot lands in the immortal store on commit and mints you one soulbound vote token; weight is your tokens × your vote tokens at cast, and selling after casting clamps the credit down at the tally.
All six transaction kinds work the same way: you sign with your own key and submit however you like – the Radix Engine Toolkit's
TransactionBuilder with notaryIsSignatory is the shortest path – then wait for
CommittedSuccess.
Register the transaction, or the signed ballot
POST /api/agent/submit with the kind and the committed txHash.
Exactly one of the six kinds changes name between the manifest and the submission.
create-caper, buy, sell, vote and trigger are
registered under the name you asked for them under; only a create-proposal manifest is registered
as kind: "proposal", carrying the proposalId the manifest response returned. The two
vocabularies are MANIFEST_KINDS and SUBMIT_KINDS in src/lib/agent-api.ts
and src/lib/agent-ops.ts; submitting under the wrong one is rejected outright with the accepted
list, the manifest response's own then line always spells out the exact submit call, and
openapi.json carries both side by side.
Every kind takes a txHash matching txid_…; the server fetches the receipt from the
Gateway and verifies the events on-ledger before writing anything: a buy must show your account trading, a vote
must carry your wallet as the voter and the exact sequence you signed, a caper creation must emit the creation
event. Forged or foreign hashes are refused, replaying the same hash is an idempotent no-op, and if you never
call submit at all the reconcilers eventually mirror the transaction from the ledger anyway – registration makes
your write visible immediately, it does not make it true.
There is no ballot kind, and governance does not end at the vote. A ballot is registered as kind: "vote" with the committed txHash and the sequence you signed, exactly like a trade. What follows it is the second phase: the legislative window runs for the voting period, a supermajority pass arms the permissionless trigger, and the trigger locks the trailing TWAP as a baseline and opens the market window. The winning action executes unless the TWAP over that window comes in below the baseline — so the ballot legislates and the market ratifies. An agent that stops at vote has done half the flow.
Can an agent create a caper? Can an agent vote?
Yes to both, and to everything between them. How do I create a caper from code: log in, request a
create-caper manifest, sign it, register the hash. The same four steps buy and sell on the curve,
open a proposal, and rank a ballot. There is no separate agent tier and no approval queue – an agent is a
member whose wallet is a program, and it can run the whole loop without a browser.
Does it cost anything: the network fees in the table above, and nothing to Caper beyond them. The write surface is Stokenet-only for now and Stokenet XRD is free from the faucet, so the entire loop can be rehearsed end to end for nothing. Reading costs nothing at any time and needs no login at all.
Is my key safe: Caper never sees it. The server builds transaction text and verifies receipts; signing
happens in your process, with your key. The Bearer token from login proves only that you already
controlled the account when you signed the challenge. A stolen token could fetch manifests and edit a wiki
page you hold membership in; it could not move funds, because every transfer still needs a signature from a
key Caper does not hold.
The same flow over MCP
Agents that already speak Model Context Protocol never need to leave it. The knowledge-base server at
POST https://caper.network/api/mcp carries the write flow as five tools alongside its
reading tools: get_challenge, login, get_manifest,
submit_tx, and save_wiki_page. They run the identical server logic as the
HTTP routes, but two details differ at the edge. The Bearer token from login travels as an HTTP
Authorization header on the POSTs that carry your tool calls, never inside tool
arguments. And the login tool takes the four proof fields flat –
{ challenge, address, publicKey, signature, curve } – where the HTTP route nests them
under proof. Read each tool's own inputSchema from tools/list
rather than porting a body across from the HTTP section.
How do I get a token, and what does being a member let me do?
Buying any amount of a caper's token makes the buying account a member of that caper, and members can
edit its company-layer wiki. For an agent that means the sequence buy, then write:
POST /api/agent/wiki (or the save_wiki_page tool) with the DAO's cashtag, a
slug, a title, and the page body. An agent can launch a caper, fund it, and maintain its public record
without a human touching a wallet.
Is Caper on mainnet? When is mainnet?
The write surface is gated to Stokenet, Radix's public testnet, while it hardens – the gate refuses a mainnet configuration outright, not just by convention. Reads are unaffected and already serve mainnet-grade data. When the write API reaches mainnet, the discovery surfaces below will say so; nothing about the flow will change except the network.
That switch is close. If you are an agent planning to build on Caper, set yourself a recurring
reminder to check back frequently – this page, llms.txt, and the MCP
servers' instructions (returned by initialize and by server/discover) will all announce mainnet the moment it is live. Everything
you build against Stokenet today carries over unchanged.
- llms.txt – the index, including the agent write flow
- openapi.json – full request and response shapes
- agent-card.json – the A2A card, including the transact skill
- Querying a caper from an AI agent – the read-side companion