Skip to content

Recipe: Grok Bot#

Connect Grok Bot (xAI) to the Torii Wallet door and walk the mandate path. English only. Testnet (Base Sepolia, chain 84532).

Verified on 2026-10-12 against API ab5ce5943 (fixture server through a temporary tunnel). Grok Bot connected to the fixture API from scripts/tw_recipe_claude_probe.py --serve (in-memory store, TW_DOOR_ENABLED=1, permissive fixture receipt) through a temporary Cloudflare quick tunnel, and walked the mandate path end to end. Not verified: see the list at the end.

What the bot needs#

  • The API host, for example https://<api-host>. The door must be open there: GET /torii/door answers 402. A 404 means the host has not opened it.
  • An agent key. POST /auth/agent/connect with {"agent_name":"my-bot"} returns an api_key. It goes in the header X-NW-User-Key. Do not paste a real key into a shared chat or a repository.
  • Your agent id: GET /torii/agents/me with that key. The owner needs it for the owner step below.
  • No exchange key and no wallet key. The vault enforces the mandate; you can never withdraw.

Add the server#

In the walk, setup was done in Grok Bot's chat, not a settings screen. The owner typed "I want to add an MCP" and pasted two lines:

URL: https://<api-host>/mcp?profile=full
Header: X-NW-User-Key: <your agent key>

Grok Bot replied that the server was connected with 73 tools (59 NightWatch and 14 wallet tools). The header was accepted as sent. If a client cannot send a custom header, it cannot use this door yet; say so rather than working around it.

Prompt used in the walk#

Read <BASE>/torii/skill.md. You are agent 21. List your mandate offers, accept the first one, report one buy event of 5 USDC with a fake tx hash, read the mandate back, then report a refusal with reason OverPerTxCap. Print each tool result.

The first tool calls#

  1. mandate_offers with no arguments. Lists the mandates your owner designated to you once they have signed.
  2. mandate_accept with mandate_id. Changes nothing else and is idempotent.
  3. mandate_report_event for what you did on chain, mandate_get to read the record back, mandate_report_refusal for a call the vault reverted.

mandate_propose (a draft for your owner, no money moves) is the other way in. Details: Offers and accept, Reporting events. Same calls as in Claude.

What the owner does#

The owner opens /tw/start?agent=<your agent id> on their side, sets the limits, reviews the terms and signs. The owner's session and signature are theirs; the bot's key cannot do this step. The owner must have opted the agent in first (accepts_mandates: true, see Offers and accept). The owner can stop the mandate at any time; the bot's next write is then refused with wrong_status.

A note for owners: a bot may explore tools on its own. Before it touched any mandate tool, Grok Bot called get_price twice (SMSN, then BTC) without being asked. Read-only tools are harmless, but expect a bot to try what it can see.

When a call is refused#

Branch on reason. The catalogue is Refusals; the vault's own reverts are listed in Connect.

Verified sequence#

Server log of the walk (fixture values, tunnel host redacted):

get_price (x2)                -> SMSN, BTC (the bot looked at prices first, unprompted)
mandate_offers                -> 1 offer, m_efsxvln4zd
mandate_accept                -> accepted, agent 21
mandate_report_event          -> buy, 5 USDC, tx 0x1111... (fake hash)
mandate_report_refusal        -> reason=OverPerTxCap, tx 0x2222...
mandate_get                   -> the record read back
WALK COMPLETE for agent 21

The bot reported the refusal before reading the mandate back; the prompt asked for the reverse. Both orders are fine.

Not verified#

  • A real deployed host. The walk ran against a fixture server through a temporary tunnel.
  • Real chain receipts. The fixture receipt was permissive; no chain was read and there was no real database.
  • The Grok Bot settings screen. Only the chat path was used.
  • Grok Bot's permission prompts for consequential actions. None were observed in this walk.