tally.agents resource manages agent identities — the things you run that spend money. See Agents (concept) for the model.
Types
Agent
AgentUpsertInput
Methods
agents.upsert(input)
Creates an agent if it doesn’t exist; returns the existing record if it does. Idempotent — safe to run on every deploy.
| Field | Type | Description |
|---|---|---|
input.id | string | Stable identifier. Must be unique within the API key’s (account, mode). |
Promise<Agent>. For a freshly registered agent, status will be "no_permissions" and both signer counts will be 0 until a user authorizes a grant. See Permissions for the grant flow.
Throws
| Error | When |
|---|---|
ValidationError | The id is missing, empty, or fails server-side format checks. |
AuthenticationError | The API key is missing, revoked, or out of its rotation grace window. |
agents.list()
Returns every agent in the API key’s (account, mode).
Promise<Agent[]>. No pagination today — accounts with hundreds of agents will get the full list. Cursor-paginated variant is on the roadmap; until it lands, this is a single round-trip.
Throws: AuthenticationError if the API key is invalid.
agents.get(id)
Fetches a single agent by id.
| Field | Type | Description |
|---|---|---|
id | string | The agent’s stable identifier. URL-encoded automatically. |
Promise<Agent>.
Throws
| Error | When |
|---|---|
NotFoundError | No agent with that id exists in this (account, mode). |
AuthenticationError | The API key is invalid. |
agents.delete(id)
Soft-deletes an agent. The DB row stays in place so historical transactions keep their attribution; future list() / get() responses hide it.
has_active_grants enforcement makes consent ordering explicit: an agent with active spending power isn’t quietly removed from view while still attached to a Privy wallet. Revoke its permissions first, then retry.
Resurrection is supported: re-running tally.agents.upsert({ id }) with the same id clears deletedAt and brings the agent back with no transaction history loss.
Throws
| Error | When |
|---|---|
NotFoundError | No agent with that id exists (or already soft-deleted). |
ConflictError | err.code === "has_active_grants" — agent still has non-revoked permissions. Revoke them first. |
AuthenticationError | The API key is invalid. |
Patterns
Idempotent registration on deploy
Becauseupsert is idempotent, the cleanest pattern is to register every agent your service needs at startup:
REQUIRED_AGENTS in a later deploy, the new entries get registered automatically and existing ones are unchanged.
Checking grant status before sending a payment
Agent.status reflects whether any wallet has authorized this agent to spend. Use it as a gate before invoking spend-related flows:
status: "active" only confirms the agent has some grant; it doesn’t tell you which wallets or what allowance remains. For that, today you have to either attempt the payment and branch on the error, or check the dashboard.
Not yet in the SDK
agents.delete(id)— soft-delete an agent. Tracked in BUILD_LOG.md.agents.list({ limit, starting_after })— cursor pagination.tally.permissions.list({ agent_id })— per-grant inspection (allowance, policy summary, wallet). Currently dashboard-only.
mintlify-docs/permissions.mdx get removed.