# Session keys and spending caps

> How to delegate scoped spending power to an agent without giving up the SCW's owner key.

In the canonical `aa-native` flow the SCW's owner key signs every UserOp. For an agent that needs to spend autonomously, this means either keeping the owner key online indefinitely (full delegation) or using a different account contract that supports scoped delegation.

ERC-4337 supports session keys at the account-contract layer. The `aa-native` wire format is unaffected by which account contract you use; only the on-chain validation logic changes.

## What a session key buys you

A session key is a separate keypair the SCW's owner authorizes for a constrained subset of operations. Constraints are enforced by the account contract during `validateUserOp`. Typical constraints:

- **Time-bounded.** "Valid until `expiry` timestamp."
- **Method-bounded.** "May only call `SettlementContract.settle(...)`."
- **Amount-bounded.** "May spend at most 10 USDT/day."
- **Counterparty-bounded.** "May only target merchants in this allowlist."

When the constraints are exceeded, the account contract rejects validation and the bundler refuses to submit the UserOp. The owner can revoke a session key at any time by sending a single transaction.

## Why this is not in the canonical SDK

The canonical `SimpleAccount` contract (the factory the reference SDK targets at `0x9406Cc6185a346906296840746125a0E44976454`) does not implement session-key validation. Adding it requires deploying a different account contract.

Several account contracts in the ERC-4337 ecosystem do support session keys:

- **Kernel** (ZeroDev) — validator plugins, including session-key validators with policies.
- **Safe with `Safe4337Module`** — Safe accounts as ERC-4337 wallets, with module-based delegation.
- **Biconomy Smart Account** — pluggable validation modules, session-key module included.

Each comes with its own factory and account-contract address. The wire-format implications for `aa-native` are zero: the verifier ABI-decodes `userOp.callData` to a `SettlementContract.settle(...)` call regardless of which account contract is the `userOp.sender`.

## Plugging an alternative account contract into the SDK

`@nerochain/x402-aa`'s `aaNativeSigner` accepts `entryPoint` and `accountFactory` options. Override them to use a different account contract:

```ts
const signer = aaNativeSigner({
  signer: ownerOrSessionKeyWallet,
  rpcUrl, bundlerUrl, paymasterUrl, paymasterApiKey,
  settlementContract,
  entryPoint:     "0x...",   // EntryPoint v0.6 for the chain
  accountFactory: "0x...",   // Kernel / Safe / Biconomy factory
});
```

The SDK builds the UserOp via the `userop` SDK, which respects whatever factory you point it at. For account contracts that need additional middleware (signature shape changes, validator selection, etc.), you'll likely want to drop down from `aaNativeSigner` to a custom `PaymentSigner` implementation that knows about your account contract's specifics.

## A future @nerochain/x402-aa-session

A planned package, `@nerochain/x402-aa-session`, will package up the session-key flow for one or more popular account contracts as a configuration option. Expected surface:

```ts
const signer = aaNativeSessionSigner({
  ownerSigner,                   // the SCW's owner — used to sign session-key authorizations
  sessionKey: { ... },           // generated or imported session key
  scopes: {
    spendCap: parseUnits("10", 6),    // 10 USDT/day
    targets: [SETTLEMENT_CONTRACT],
    expiry: Date.now() + 24 * 3600 * 1000,
  },
  rpcUrl, bundlerUrl, paymasterUrl, paymasterApiKey,
  settlementContract,
});
```

This is a future deliverable, not something shipped today. The ephemeral SCW pattern (see [Delegated agent](/docs/guides/delegated-agent)) covers most demo and trusted-environment use cases without it.

## When you actually need session keys

- Multi-user platforms where the operator runs LLM agents on behalf of users and cannot hold each user's owner key online.
- Long-running autonomous agents that should keep operating across user-session boundaries.
- Cost-capped agent budgets where a runaway prompt cannot drain the wallet.

For one-off scripts or single-user demos, the ephemeral-SCW pattern is enough.
