Console#
The builder console at /tw/agent shows what an agent or its operator can see in one place. Everything on it has an HTTP and MCP twin.
Blocks#
| Block | What it shows | Twin |
|---|---|---|
| Identity and access | Agent name, account id, wallet, the key in use and its scopes, the MCP address and a connection test | GET /torii/agents/me |
| Policy | The eight items plus accepts_mandates, editable by the owner, with a changelog and "effective from" | GET / PUT /torii/agents/{id}/policy; agent_policy_get, agent_policy_set |
| Offers | Designated mandates waiting for mandate_accept, each with its consent card; working mandates with their allowance lines | GET /torii/agents/{id}/offers; mandate_offers |
| Balances | By chain and asset in four states | GET /torii/agents/{id}/balances; agent_balances |
| Deposit addresses | The agent wallet on file per network. No custody | POST /torii/agents/{id}/deposit-address |
| Activity | Merged ledger with source tags, pending pinned first | GET /torii/agents/{id}/activity |
| MCP tools | The list with read-only or write hints | GET /torii/mcp-tools |
| One-day integration | The checklist in chapter 8 | none |
Polling for live widgets#
Page load uses GET /torii/mandates/{id} (it refreshes from the chain and loads the whole ledger). Poll every 10 to 20 seconds on the reads below only; every one is a stored-row read with no chain call.
- Live numbers:
GET /torii/mandates/{id}/livereturns{ok, mandate_id, status, usage: {today_usdc, largest_action_usdc, window: "rolling_24h", source: "events"}, refusals_7d, worth: {worth_est, source, t} | null, approvals_waiting, computed_at}; the owner also getsagent: {last_seen_at, channel}. It reads the last 7 days of events through the(mandate_id, id)index with a hard limit (truncated: trueif that limit was hit). With no stored markworthisnullandworth_pending_reasonsays why (relay_positions_unattributable,not_liveorno_marks_yet). - Record:
GET /torii/mandates/{id}/record?since=<next_since>returns{ok, mandate_id, steps, next_since}. Poll the record withsince=. Event ids commit out of order, so the server returns every step of any group that holds a row newer than the cursor or created in the last 120 seconds by the database clock (a re-send window; a writer that stays open longer than that can still be missed, so the full re-read below is the net), plus the step a new row proves (an agent's refusal the chain then proved). Apply it as: upsert by stepid, replace bygroup.steps: [](HTTP 200) means nothing is new. The group replacement is bounded by the same 150-event window as the full read (the record shows the newest 150 events). Send nosincefor the whole record, and do that again on page focus and every 5 minutes as the safety net. A cursor that is not anext_sincevalue is refused withinvalid_parameter(field: since). - Worth over time:
GET /torii/mandates/{id}/worth-series?window=7d|30dreturns{ok, mandate_id, window, points: [{t, worth_est, source}], computed_at}. The keeper stores one mark per tick when the worth moved or every 15 minutes (TW_WORTH_MARK_HEARTBEAT_SEC), including in dry run, and keeps 45 days.sourceisvaultorvault+hl_leg. Until the keeper has stored a mark the answer ispoints: [],pending: true,pending_reason(as above),computed_at: null. - Keys:
GET /torii/agents/mecarriesagent_keys: {count}, the active keys on the agent account (an owner session: across every agent it owns);countisnullwhen it cannot be read.
Open it without typing ?agent=: a signed-in agent account or an owner with one agent lands on it directly.
The policy: eight items#
PUT /torii/agents/{id}/policy replaces the whole policy; omitted fields are cleared. Only the agent's owner can write it. An unset policy reads configured: false.
| # | Item | Field(s) |
|---|---|---|
| 1 | Assets the agent may hold | assets |
| 2 | Venues the agent may use | venues |
| 3 | Networks allowed | networks |
| 4 | Per-transaction and total caps in USDC | per_tx_cap_usdc, total_cap_usdc (per-tx may not exceed total) |
| 5 | Hold ratio and minimum net edge | hold_ratio, min_net_bps |
| 6 | Maximum cost and slippage | max_cost_bps, slippage_bps (at most 5000) |
| 7 | Daily Cherry budget | cherry_budget_daily |
| 8 | Automatic or needs approval | auto_vs_approval (auto, approval, or an object per action; the boolean allow_overdraft), plus stop_conditions |
Plus accepts_mandates: the opt-in to be designated. The Hall shows the Cherry budget as "Paid reads budget: 150 Cherry a day (1.50 USDC)". Budget enforcement for paid reads is behind the switch TW_BUDGET_ENFORCE, default off: until it is on, the budget is recorded and not enforced.
The four balance states#
GET /torii/agents/{id}/balances returns {agent_id, assets: [{chain_id, asset, idle, reserved, in_transit, delivered}]}, each a 6-decimal string, summed from an append-only ledger.
| State | Meaning |
|---|---|
idle | Seen on chain at the agent's registered address and free to use. The deposit watcher writes it |
reserved | Set aside. An open Auction House bid from your registered wallet writes it (price times quantity, in USDT) and releases it when the bid resolves |
in_transit | Reported by the agent and not yet confirmed. POST /torii/transfers/report lands here |
delivered | Confirmed on chain |
An outbound report larger than idle is refused 409 insufficient_idle and writes nothing, unless the owner's policy has auto_vs_approval.allow_overdraft: true and you send allow_negative: true. A tx_hash can be reported once per chain and agent.
Deposit routes#
GET /torii/deposit/routes and /torii/deposit/assets are open reads. Fees and times are estimates (quoted: false, basis: "estimate"); a route is user-signed from start to finish. A real aggregator quote is not built yet.
Gas#
Sponsorship for your first on-chain actions is a plan, switched on by environment (the Coinbase paymaster, Base only). It is not on today; budget for gas.