One setup, two effects, one Privy app: execution (Privy signs your users’
trades) and auth (users sign in with a Privy access token). Both turn on
when you save Privy as the wallet provider. Privy sign-in is not available on
its own, because AGG finds a user’s Privy wallets by the Privy identity that
sign-in records.
What You Need From Privy
Three values, all from your Privy dashboard:
The key is accepted in any of the shapes Privy hands out: the
wallet-auth:MIGH... form, a bare base64 PKCS#8 body, or a full
-----BEGIN PRIVATE KEY----- PEM block.
Ownership Model
Wallets must be app-owned: AGG holds the authorization key and signs every wallet call with aprivy-authorization-signature header, with no user present.
This is not a preference — it is required by how execution works. AGG signs
inside detached execution graphs that run minutes or hours after the originating
request, and several flows have no user request behind them at all: limit-order
fills, settlement webhooks, and managed balance refills.
- Server-owned wallets (owner is your authorization key or a key quorum containing it) — works.
- User-owned wallets with your server key as an additional signer
(
owner: { user_id }+additional_signers: [{ signer_id: <key quorum id> }]) — works, as long as the key quorum contains the authorization key you saved in AGG. - User-owned wallets with no additional signer — does not work. Only the
user’s own session can sign, and there is no user session at signing time.
AGG refuses these at provisioning with
PRIVY_WALLET_NOT_SIGNABLE.
- User-owned wallets — from the user’s linked accounts. No
entityneeded. - Server-owned wallets — by
entity: { id: "<your Privy user id>", type: "user" }. Entity is immutable once set, so a server-owned wallet created without one can never be attributed to a user.
PRIVY_WALLET_NOT_READY and
succeeds on a later attempt once the wallet exists.
If your onboarding also creates wallets, possibly after your user has signed in
to AGG, leave wallet creation off. Otherwise both sides could create a wallet
for the same chain.
Setup — Execution
- Go to Settings → Wallet Provider in the AGG dashboard.
- Change the provider dropdown from Portal (default) to Privy.
- Enter the app ID, app secret, and authorization private key.
- Save. Secrets are encrypted before storage and are never returned to the dashboard — the form shows only whether they are set.
- Validate. This round-trips your credentials against Privy from the service that actually signs, so a typo fails here rather than hours later inside an execution run.
The Provider Lock
User migrations are not supported. If you have wallets created you cannot change wallet provider. Please create a new instance to change providers.Once any wallet exists for one of your app’s users, the provider is fixed. There is no migration path — the two custodians hold key material in different systems and neither exports it, so switching would strand every existing wallet and the funds in it. The rule is enforced on the API, not just in the dashboard. Credential rotation is never blocked. If your Privy app secret or authorization key leaks, replace it in the same form at any time, lock or no lock. Rotation requires all three fields together — a partial update is rejected, because the three values are one credential and mixing generations produces silent signing failures.
Privy Auth — enabled with the wallet provider
There is no separate Privy setting on the Auth tab. Once Privy is saved as the wallet provider (above), AGG accepts Privy access tokens for the app and verifies them against the Privy app ID in those credentials, using Privy’s published public keys athttps://auth.privy.io/api/v1/apps/{appId}/jwks.json.
There is no callback URL to register. Unlike the OAuth providers, Privy never
redirects — your app holds the token already and posts it to AGG directly.
Exchanging a token
Your frontend obtains a Privy access token through Privy’s own client SDK, then posts it to AGG:/auth/verify endpoint used for wallet sign-in — the body is a
union on kind, and everything after identity is proven is shared.
A success returns the same access + refresh token pair as every other AGG
sign-in method. The Privy DID (sub) becomes the user’s provider account ID, so
the same person signing into two of your apps gets one identity across both.
Errors
Every failure is a401 with a message:
Troubleshooting
Validate fails after saving credentials. The message is Privy’s own. A 401 usually means the app secret or the authorization private key does not belong to the app ID you entered — all three must come from the same Privy app. Re-copy them together rather than one at a time. Every Privy sign-in fails withWeb3 authentication failed. The tokens
your frontend is minting come from a different Privy app than the one saved
under Settings → Wallet Provider. This is almost always a staging token being
sent to a production app, or vice versa.
The provider dropdown is greyed out. Wallets already exist for this app’s
users. See The Provider Lock — the fix is a new app, and
credential rotation is still available below the dropdown.
Validation passes but execution fails later. Validation proves the
credentials are accepted by Privy; it does not prove your wallets can meet a
signing policy you have configured in Privy. Check that no Privy policy or
additional quorum member blocks the authorization key AGG holds.