> For the complete documentation index, see [llms.txt](https://docs.doma.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.doma.xyz/agentic-commerce/agentic-wallet.md).

# Agentic Wallet

The agentic wallet is the architecture behind agent mode in the Doma CLI. It lets an AI agent execute on-chain actions on the user's behalf (within a hard policy) without ever holding the wallet's private key.

This page describes the model. For the user-facing CLI flow, see [Wallet Modes](/agentic-commerce/doma-cli/wallet-modes.md).

## What it is

Doma's launchpad uses **Privy embedded wallets**. Each user has an EVM wallet whose private key is generated and held inside Privy's HSM. Neither the user nor Doma ever see it. The wallet is available across both **Doma Mainnet** (chain `97477`) and **Doma Testnet** (chain `97476`); agent mode works on either.

For agent commerce, we attach a **delegated agent signer** to the wallet, governed by a per-wallet **policy**. The agent never holds the user's key, and Privy refuses any signature request that falls outside the policy.

## Authority model

<figure><img src="/files/ssjMxcEibOD9NCfTgLuT" alt="Delegated-signer authority. The user wallet (EOA, key in Privy HSM) has the user&#x27;s Privy DID as owner and an additional signer: the agent authorization key, server-side in launchpad infra, bound to the policy doma-agentic-wallet-v1, which allows eth_sendTransaction on Doma mainnet (97477) and testnet (97476), and eth_signTypedData_v4 on Doma testnet (97476) only."><figcaption></figcaption></figure>

The policy `doma-agentic-wallet-v1` is what makes the agent signer safe. Where `<Doma chain IDs>` in the diagram resolves to `97477` (mainnet) and `97476` (testnet), and `<Doma testnet>` is `97476` alone. Typed-data signatures are scoped to testnet today (see [Known limitation](#known-limitation)).

* The **wallet's own private key** stays in Privy's HSM. It signs every transaction (so on-chain validators see `from = wallet_address`).
* The **agent authorization key** lives server-side in Doma's launchpad infra. It does not sign transactions itself; it tells Privy "this user authorized me, please sign on their behalf."
* The **policy** is enforced by Privy. Anything the agent requests outside the policy is rejected before signing.

## Policy fields

| Field               | What it controls                                        | Example                                       |
| ------------------- | ------------------------------------------------------- | --------------------------------------------- |
| `chain_allowlist`   | Which chain IDs the agent can target                    | Doma mainnet, Doma testnet, Base              |
| `method_allowlist`  | Which RPC methods the agent can call                    | `eth_sendTransaction`, `eth_signTypedData_v4` |
| `usd_spend_ceiling` | Cumulative USD spend before the agent must re-authorize | `$200`                                        |
| `allowance_window`  | Refill window for the spend ceiling                     | rolling 24h                                   |
| `revocable_by_user` | User can detach the signer at any time                  | `true`                                        |

The defaults above describe Doma's `doma-agentic-wallet-v1` policy. Future versions may tighten or relax fields.

## Session lifecycle

{% stepper %}
{% step %}

#### Login

User runs `doma auth login`. The CLI opens a localhost callback URL in the user's browser, which loads Doma's launchpad consent screen.

The launchpad calls Privy's `wallets.update()` to **attach the agent authorization key** as an additional signer with the `doma-agentic-wallet-v1` policy, then mints a short-lived **session JWT** keyed to a fresh allowance row in KV (default `$200` budget).

The CLI persists the JWT to `~/.doma/credentials.json` (mode `0600`).

Sessions are **network-scoped.** To authorize agent mode on both Doma Mainnet and Doma Testnet, run `doma auth login` once per network (toggle the network with the `--testnet` flag or `doma config set testnet <bool>` between runs).
{% endstep %}

{% step %}

#### Use

Every CLI write command POSTs the session JWT plus the intended transaction payload to the launchpad's `/api/agent/execute` endpoint. The launchpad:

1. Validates the JWT.
2. Decodes the calldata, computes the USD value of the transaction (using oracle prices).
3. Checks the policy: chain allowed? method allowed? cumulative spend within ceiling?
4. If all checks pass, instructs Privy to sign on behalf of the user.
5. Submits the signed transaction to the chain RPC.
6. Decrements the allowance row by the USD value.

If any check fails, the launchpad returns a structured error and the CLI surfaces it cleanly to the user.
{% endstep %}

{% step %}

#### Revoke

User runs `doma auth revoke`. The launchpad calls Privy's `removeSigners` to detach the agent authorization key from the user's wallet, deletes the allowance row, invalidates the session JWT, and clears `~/.doma/credentials.json`.

The user can also revoke from the launchpad's "Authorized agents" panel. Useful if the CLI machine is lost or compromised.
{% endstep %}
{% endstepper %}

## The three signing paths

A given Doma CLI action falls into one of three patterns based on what kind of signature it needs:

| Action                                                            | RPC method             | Signed by                                   | Status                            |
| ----------------------------------------------------------------- | ---------------------- | ------------------------------------------- | --------------------------------- |
| `marketplace buy`, `swap`, `bridge`, `dns set`, `subdomain claim` | `eth_sendTransaction`  | wallet's own key (via Privy)                | ✅ working                         |
| `marketplace cancel --type on-chain`                              | `eth_sendTransaction`  | wallet's own key                            | ✅ working                         |
| `marketplace offer`, `listing`, off-chain `cancel`                | `eth_signTypedData_v4` | agent authorization key, **not** the wallet | ⚠️ off-chain signature limitation |

The first two rows are "transactions": they're submitted on-chain and validators only care about `from = wallet_address`, which is true.

The third row is "off-chain typed data" used by gasless protocols like Seaport. The signing address must equal the wallet address. Today Privy uses the agent authorization key for these, so the signing address ≠ the wallet address, and Seaport rejects the signature.

## Known limitation

Gasless typed-data flows (`marketplace offer`, `listing`, off-chain `cancel`) don't work in agent mode today. **Workaround:** use `private-key` mode for those specific actions.

The path forward is a **smart-wallet migration**: instead of the user's EOA, the wallet becomes a smart contract that validates signatures via on-chain logic ([ERC-1271](https://eips.ethereum.org/EIPS/eip-1271)). The contract can be programmed to accept signatures from the agent authorization key as if they were the wallet's own. This eliminates the off-chain asymmetry entirely.

Tracked separately; not in scope for V1 of agent mode.

## Security posture

{% hint style="warning" %}
Agent mode is a **guardrail**, not a vault. The policy bounds blast radius, but a compromise of the launchpad's agent authorization key or the user's session JWT still allows actions within the policy. Use a dedicated wallet for agent mode and keep the spend ceiling tight.
{% endhint %}

* The launchpad's agent authorization key is rotated on a schedule and stored in HSM-backed cloud KMS. Compromise requires breaching both Privy and the launchpad infra.
* Session JWTs are short-lived and tied to a specific wallet + allowance row. Theft of a JWT bounds the attacker by the remaining ceiling.
* The user's wallet key remains in Privy's HSM at all times. Even an attacker with full launchpad access cannot exfiltrate it.

## What's next

* [Wallet Modes](/agentic-commerce/doma-cli/wallet-modes.md): user-facing flow for `agent` vs `private-key`.
* [Commands → coverage matrix](/agentic-commerce/doma-cli/commands.md#coverage-matrix-what-works-in-agent-mode): per-command status of agent-mode support.
* [ERC-1271 specification](https://eips.ethereum.org/EIPS/eip-1271): the migration target for gasless flows.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.doma.xyz/agentic-commerce/agentic-wallet.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
