BotanaryBotanary
Agents

Agents

An agent acts under a mandate - a bounded, revocable grant - and every proposal it makes is previewed and enforced before anything can be signed.

"Agent" covers two related things in Botanary: the authority an agent acts under, and the seam an agent runtime calls to turn its own proposals into something signable.

A mandate is the authority

The authority side is a mandate - a kind: 'mandate' delegation, the same object described in Delegations, just built with venues and per-venue caps instead of a flat budget. Granting an agent a mandate is exactly the delegation grant flow in Granting a delegation; revoking it is exactly Revoking a delegation. An agent has no authority beyond what its mandate encodes, and nothing an agent proposes can move funds outside those venues, recipients, and caps.

An owner can hold more than one active mandate at a time - one per hired agent - and each is revoked independently of the others.

The agent-build seam

The second half is a dedicated build endpoint the agent runtime itself calls to turn its own approved proposal into an owner-lane unsigned operation. It's deliberately kept outside the versioned public API - it isn't part of the frozen contract between the backend and the Botanary app - but it still requires an authenticated session; the account it builds against is always resolved from that session, never taken as an unauthenticated parameter.

Only three actions can be built through this path today: sending funds, depositing into a vault (as a batched approval and deposit together), and approving a spend. A swap isn't supported here yet and is declined outright rather than attempted. Whichever of the three it is, signing works identically to an ordinary send - there's no separate signing path just because the proposer was an agent.

Every proposal is previewed before it can be signed

Exactly like every other action in Botanary, an agent's proposal gets a simulation preview before the unsigned operation is ever returned:

  • If a named policy reason declines it, the build fails outright - no unsigned operation comes back at all.
  • If the simulator itself is unreachable (not a named decline, just an unknown outcome), the build still returns an operation, but marked as blocked - something the client is expected to refuse to sign, not something it should present as ready.
Preview statusMeaning
okexpected to succeed cleanly
warnexpected to succeed, with something worth surfacing
blockednot safe to sign

A named policy decline never reaches you as a signable operation - it's refused at build time. An unknown outcome does come back, but blocked, so the decision to refuse to sign it is explicit rather than accidental.

What you see before you confirm

An agent's proposed action is never auto-approved. Before you confirm anything:

  • A decline reason on the proposal always removes the confirm control - even if a technically signable operation happened to come back alongside it.
  • A blocked preview does the same - even though a key could technically sign it, the interface doesn't offer that path.
  • If a proposal lists multiple possible venues, that list is informational only. Exactly one built operation ever backs the confirm action, so browsing the other listed options can't change what actually gets signed - and any venue that isn't allowed is shown, visibly disabled, rather than hidden.
  • The confirm control is labeled with the specific mandate authorizing the action, so it's always visible which grant is being exercised, not just that "an agent" is asking.

Agent identity

There's no separate agent profile or registry behind any of this - an agent's identity, as far as the account is concerned, is just the delegate address and name recorded on the mandate that authorizes it. Revoke the mandate, and that identity's authority is gone; there's nothing else to clean up.

TODO: verify whether a future release adds a standalone agent identity/registry before launch - today, a mandate's delegate address and name are the only record of "who" an agent is.

On this page