Action lifecycle
Every action initiated by an agent is atomic: one MCP tool call covers the whole flow from proposal to on-chain settlement. The agent never has to choreograph multiple round-trips — it calls a single tool, hands the user a sign URL, and listens for status updates.
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Agent calls │ │ User opens │ │ Server executes │
│ transfer / swap │───▶│ sign_url, signs │───▶│ on bundler / GP, │
│ /card_* │ │ via passkey │ │ mines, settles │
└──────────────────┘ └──────────────────┘ └──────────────────┘
proposed signed submitted → broadcast → executedStep 1 — Call the action tool
The agent calls one of the action tools (transfer, swap, card_freeze, card_unfreeze, card_limit). Picnic validates the parameters, builds the underlying ERC-4337 UserOperation (or Gnosis Pay payload for card actions), and persists it as a pending action.
The tool returns:
action_id— opaque UUID identifying the pending action.sign_url— URL the user opens to authorize with their passkey (e.g.https://agents.usepicnic.com/sign/<action_id>).resource_uri—picnic://action/<action_id>. Subscribe to receivenotifications/resources/updatedas the action progresses.simulation_url— Tenderly preview URL (only for 4337 actions). The user can independently verify the call before signing.expires_at— pending actions are valid for 10 minutes; after that the user has to start over.
Nothing settles on-chain on its own. If the user never signs, the action expires and is dropped.
Step 2 — User signs at sign_url
The user opens sign_url, reviews the transaction summary and (when applicable) the Tenderly preview, then approves with their existing Picnic passkey via WebAuthn.
The signing page is hosted at https://agents.usepicnic.com/sign/<action_id>. It is the only place the user sees the actual transaction details and is the primary defense against prompt-injection — the agent cannot make Picnic sign on the user's behalf. After signing, the same page transitions into a live status view that polls until the action reaches a terminal state: tx hash + block explorer link on success, error detail on failure.
Step 3 — Server-side execution (no extra tool call)
As soon as the signature is attached, the server kicks off execution from the sign endpoint:
- Transfer / swap — submits the signed UserOperation to the 4337 bundler. The bundler accepts (
broadcast), the UserOp mines (executed), or it reverts (failed). - Card freeze / unfreeze — verifies the EIP-1271 signature against Gnosis Pay and calls the freeze / unfreeze endpoint.
- Card limit — enqueues the new allowance via Picnic's delay module; the on-chain
setAllowancedispatch lands a few minutes later.
The agent does not need to call a separate execute tool.
Step 4 — Receive updates
Status flips trigger two parallel channels:
- MCP push. Every status transition emits a
notifications/resources/updatedforpicnic://action/<action_id>to every session subscribed to that URI. MCP clients that render resource notifications surface progress automatically. - Polling fallback. Agents whose clients don't render resource notifications can call
get_action_statuswith theaction_idto read the latest state.
Action status enum
proposed → signed → submitted → broadcast → executed (success path).
Other terminal states: failed (on-chain revert or downstream API failure), expired (TTL elapsed before signing), rejected (user denied at the sign page).