Skip to main content
There are three ways to give an agent Tally tools. Pick by what your agent can do:
Your agent…UseWhat it feels like
Chats + makes web requests (Hermes, OpenClaw, most LLM agents)Device flow (this page)Agent shows you a link → you approve in the browser → done. No localhost.
Controls its own browser (Claude Desktop, ChatGPT, Cursor via a bridge)Native MCP OAuthA browser popup opens automatically; you approve.
Runs a local subprocessStdio + API keyPaste a key into config. See Connect via stdio.
All three connect to the same hosted endpoint and expose the same four tools — pay_x402_service, pay_direct, list_recent_payments, get_wallet_info — bounded by the per-tx and daily caps you set in Tally. If you’re not sure, use the device flow — it works for any agent that can make HTTP requests, including chat-only ones.

Fastest path: paste this into your agent

This drives the device flow, which works regardless of host (it doesn’t need your agent to open a browser or run a local listener).
Connect yourself to Tally using its OAuth Device Flow so you can hold and spend
USDC on my behalf. Tally base URL: https://app.tallyforagents.com

1. Register a client (once):
   POST /oauth/register
   JSON: {"client_name":"My Agent","redirect_uris":["http://127.0.0.1/cb"],"scope":"wallet:read wallet:transfer x402:pay"}
   Save the returned client_id.

2. Start the device flow:
   POST /oauth/device_authorization
   form body: client_id=<client_id>&scope=wallet:read wallet:transfer x402:pay
   It returns verification_uri_complete, device_code, and interval.

3. Show me ONE line, then wait — do not show the raw code:
   "Click here to connect Tally and approve: <verification_uri_complete>"

4. After I tell you I've approved, poll for the token:
   POST /oauth/token
   form body: grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=<device_code>&client_id=<client_id>
   - {"error":"authorization_pending"} → wait <interval> seconds, then retry.
   - {"error":"slow_down"} → wait a few extra seconds, then retry.
   - When you receive an access_token, stop polling and save it.

5. Confirm: GET /v1/me with header Authorization: Bearer <access_token>, and tell
   me the workspace, mode, and agent it returns.

Use this access_token as the Bearer credential for Tally from then on.

What you’ll experience

The agent shows you a single link like https://app.tallyforagents.com/device?code=WDJB-MJHT. You:
  1. Click it (it’s your own Tally domain).
  2. Sign in if needed, pick the workspace, mode (test/live), and agent.
  3. Click Authorize → you see “Connected — return to your agent.”
The agent’s polling finishes on its own a few seconds later. You never type the code — it’s embedded in the link; the visible code is just a fallback for typing it manually at https://app.tallyforagents.com/device.
This is the same pattern as gh auth login, the AWS CLI, and signing into apps on a smart TV. For a chat-based agent it’s the simplest flow possible — the “popup opens by itself” experience requires an agent that controls its own browser (see below).

Native browser popup (browser-driving hosts)

If your host drives its own browser and can catch an OAuth redirect (Claude Desktop, ChatGPT, or Cursor via the mcp-remote bridge), point it at the hosted endpoint and you get the automatic popup instead of a code:
https://app.tallyforagents.com/mcp
It’s a standard OAuth 2.1 protected resource: an unauthenticated request gets a 401 + WWW-Authenticate pointing at /.well-known/oauth-protected-resource/mcp, which the host follows to open the consent screen. On Hermes builds that support remote-MCP OAuth:
hermes mcp add tally --url https://app.tallyforagents.com/mcp
hermes mcp login tally     # opens the browser → pick workspace → authorize
hermes mcp test tally
hermes gateway restart
If your host only prints a link instead of opening the browser and catching the response, it can’t complete this flow — use the device flow above instead. That’s the common case for chat-based agents.
The endpoint also accepts a static API key (tly_test_… / tly_live_…) as a bearer token, the same credential the stdio server takes.

The OAuth endpoints

Everything is advertised at the discovery document, so a host can wire itself up:
GET https://app.tallyforagents.com/.well-known/oauth-authorization-server
EndpointPurpose
/oauth/registerDynamic client registration (RFC 7591) → client_id.
/oauth/device_authorizationStart the device flow (RFC 8628) → device_code + user_code.
/oauth/authorizeBrowser consent for the redirect/popup flow.
/oauth/tokenExchange a code / device_code, or refresh.
/oauth/revokeDisconnect (revokes the whole session).
Scopes: wallet:read, wallet:transfer, x402:pay. Moving money requires wallet:transfer. See OAuth 2.1 for the full protocol.

Grant a wallet permission

On first connect the agent has the tools but no spending power — Tally is non-custodial, so you authorize a wallet explicitly. Ask the agent “what’s my wallet?” (it calls get_wallet_info); it returns a dashboard URL. Open it, Grant permission, pick a funded wallet, set the per-tx + daily caps, and approve via passkey. Grants are mode-scoped — a test-mode grant won’t show in live mode.

Switching workspaces

The token is bound to the workspace you picked, so switching is a re-auth: run the connect flow again and choose a different workspace, or revoke first via /oauth/revoke (on Hermes, hermes mcp logout tally).

Skill install (Hermes / OpenClaw)

For hosts that use a skill manifest instead of (or alongside) MCP, Tally publishes one:
hermes skills install https://www.tallyforagents.com/skill.md
The skill is API-key based: it collects a TALLY_API_KEY and teaches the agent to call Tally’s REST API directly. Use the device flow above when you want OAuth (no key); use the skill when you want “install + paste a key.”

What’s happening under the hood

  • Every entry point runs the same enforcement: the Tally policy check (caps, allowlists, expiry) then Privy’s secure-enclave signature. The MCP/OAuth layer can’t widen those caps.
  • The access token only ever sees the workspace + mode you chose on the consent screen, and it expires (the agent silently refreshes).
  • Payments show up in the dashboard’s Transactions tab with the same metadata as SDK or stdio calls.

See also