Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.tallyforagents.com/llms.txt

Use this file to discover all available pages before exploring further.

A Tally wallet is where your USDC sits. You own it; Tally never does. Agents move funds out of it only when — and only how — you’ve explicitly authorized.

Mental model

Three things sit at the core of every Tally wallet:
  • The wallet — an Ethereum-compatible address that holds USDC.
  • Signers — keys that can move funds out of the wallet. There are two kinds, covered below.
  • Policies — rules that bound what each signer can do. Enforced inside Privy’s secure enclave, not by Tally’s server.
You authorize agent signers on your wallets through a permission flow you approve with your passkey. After that, Tally can construct payment transactions on the agent’s behalf — but only ones the policy lets through.

Server wallets, not browser-embedded wallets

Tally uses Privy server wallets as the underlying primitive. A server wallet lives in Privy’s infrastructure (a secure enclave with hardware-backed key isolation), not in a browser. This is a different model from “embedded wallets” — browser-side wallets where keys are held client-side. Both keep custody with the wallet owner (not Tally), but server wallets give you two properties that matter for agentic finance:
  1. Agents can act asynchronously. You don’t need an active browser session for an agent to sign a transaction. The signer Tally holds is a separate, scoped key — not your primary key.
  2. No browser-side secrets to leak. Your authentication (passkey, email-OTP) only authorizes Privy to act on your behalf; no signing material ever leaves the enclave.
The trade-off: there’s a third-party enclave in the trust chain. We picked Privy because their model — owner-controlled wallets with enclave-enforced policies — maps cleanly onto the trust guarantees we need.

Anatomy of a wallet

Every wallet has:
FieldDescription
addressEthereum-compatible address. Public; safe to share.
displayNameHuman-readable label. Defaults to Main Wallet for the first wallet.
modetest (Base Sepolia) or live (Base mainnet). Fixed at creation.
accountIdThe Tally account that owns the wallet.
roleLabelOptional free-text label like “operations” or “ad spend”.
Wallets belong to accounts, not to individual agents. A single agent can be granted spending power on multiple wallets, and a single wallet can have multiple agents granted on it.

Provisioning

Your first wallet is created automatically. When you sign in for the first time, Tally provisions an account, makes you the owner, and creates a single test-mode wallet called Main Wallet on Base Sepolia. No extra steps; the wallet is ready to receive USDC the moment you land on the dashboard. Additional wallets can be created from the dashboard. Programmatic creation via the SDK is on the roadmap — for now, wallets are a per-account setup step. Test vs live wallets are separate. A wallet’s mode is fixed at creation, and live-mode wallets live on Base mainnet with a separate Privy app config. Moving an account to live mode provisions fresh live wallets — it does not “promote” the test wallet.

Two kinds of signers

A signer is anything that can authorize a transaction leaving the wallet. Tally wallets have two:

Owner signer (you)

You’re the wallet’s owner. Your authentication with Privy — passkey, email, or whatever method’s configured — is what gives you owner-level rights. You can:
  • Add or remove agent signers
  • Approve or revoke policies
  • Sign transactions directly (rare; mostly relevant when withdrawing funds)
Tally has no owner-level access to any wallet. We can construct transactions, but we can’t broadcast them as the owner; only you can do that.

Agent signer (Tally, bounded by policy)

When you grant an agent permission to spend from a wallet, the following happens, in order:
  1. Tally generates a fresh P-256 keypair specifically for that (agent, wallet) pair.
  2. The private key is envelope-encrypted via AWS KMS and stored. It never leaves Tally’s infrastructure unencrypted, and Tally only decrypts it transiently — just long enough to sign a single payment request, then drops it from memory.
  3. The public key is registered with Privy as an additional signer on the wallet.
  4. A policy (see below) is created and attached to that signer.
  5. You sign the addition with your passkey from the dashboard. Until you do, the signer is registered but inactive.
After that, Tally can sign payments on the agent’s behalf — but every signature is subject to the policy, which Privy’s enclave validates before the transaction goes anywhere near the chain.

What a policy enforces

Every agent signer has exactly one policy attached. The policy is signed during the permission flow and bounds what the signer can do. Today’s policy supports:
FieldWhat it bounds
maxPerTxUsdcRequired. The largest single transfer this signer can make.
dailyCapUsdcOptional. Tally-enforced rolling 24-hour cap, on top of the enclave rules.
recipientAllowlistOptional. If set, transfers can only go to addresses on this list.
contractAllowlistDefaults to USDC. The set of contracts the signer is allowed to interact with.
expiresAtOptional. After this time, the signer stops working until rotated or extended.
Policies are evaluated inside the Privy enclave on every signing request. If a transaction violates the policy, Privy refuses to sign — there is no path where Tally can override the rule, even if our server were compromised.

What this gets you

The wallet + signer + policy model lines up cleanly with the trust story:
  • Tally never custodies funds. We only hold per-agent signing keys, each bounded by a policy you approved.
  • You can revoke any agent at any time from the dashboard. Revocation removes the signer from the wallet on-chain.
  • If Tally goes away, your wallet persists. You keep control through Privy directly. Permissions stay in force or revocable — no Tally action required.
  • Even a compromised Tally can’t drain your wallet. An attacker with full access to Tally’s infrastructure could sign payments — but only ones your policy already authorizes (capped per-tx, capped daily, contract-restricted, optionally recipient-restricted).

Working with wallets from your code

Today, wallets are managed from the dashboard. When you send a payment, you reference a wallet by address:
await tally.payments.create({
  agent_id: "research-bot",
  wallet: "0x7a3fA1B9c4D2e6F8a0B1c2D3e4F5a6B7c8D9e0b21c",
  to: "0x...",
  amount_usdc: "4.50",
});
The address comes from your dashboard (or from the wallet owner directly). tally.wallets.list() and other direct wallet-management methods are on the roadmap — until they land, the dashboard is the source of truth.

What’s on the roadmap

  • ERC-4337 smart wallets. The plan is to upgrade users from server wallets to Kernel/Safe smart wallets, with the existing server wallet acting as the signer. The owner / signer / policy model carries forward unchanged — only the wallet identity shifts. No timeline yet.
  • Programmatic wallet creation via the public SDK.
  • Multi-signer policies (N-of-M co-signing for high-value wallets). The Privy primitives are there; the policy schema and grant UI aren’t.