Agent Patterns
How the WaaP CLI works under the hood.
How It Works
- Login. Email + password → JWT (no cookies, no browser)
- Keyshare. Fetched from the keyshare-manager and AES-GCM decrypted with
userKey - Signing. 2-party ECDSA (WASM + policy-engine over HTTP)
2FA: Newly created accounts start with Authorization Method set to
Disabled. To manage 2FA:waap-cli 2fa status/enable/disable. To bypass 2FA programmatically, pass--permission-token.
Risk Levels
The policy engine assigns a risk level to every signing request. When the highest risk level meets or exceeds the wallet’s Min Risk for 2FA threshold (default: HighWarn), 2FA authorization is required before the signature is released.
| Level | What it means |
|---|---|
Ok | No known risk. Transaction proceeds without friction |
LowWarn | Minor risk detected. Warning shown but no 2FA |
HighWarn | Significant risk. Triggers 2FA if Min Risk for 2FA is set to HighWarn (default) |
HighWarnButGracefully | Routine high-risk (e.g., daily spend limit exceeded). Triggers 2FA |
Block | Extreme risk. Transaction blocked by policy engine |
2FA Flow
When the policy engine determines that 2FA is required (i.e., highest_risk >= min_risk_for_2fa):
- Policy engine returns
WaitForAuthzduring signing. - CLI opens a WebSocket connection to
/listen-authz/{method}/{payloadId}/{jwt}. - For email: a verification link is sent. CLI waits for the user to click it.
- For phone: an OTP is sent via SMS. CLI prompts for the code via stdin.
- For wallet: a message is signed on the external hardware wallet.
- Timeout: 5 minutes. CLI exits with an error if no authorization is received.
Session Storage
- Session is saved at
~/.waap-cli/session.jsonwith0600permissions (owner read/write only). - Contains:
token,jwt,userKey, and optionallyuserId. waap-cli logoutdeletes this file.- Set
WAAP_CLI_SESSION_DIRto relocate it. Give every agent or CI job its own directory. Two processes sharing one will contend over the same session file.
Chains
Every signing command requires an explicit --chain. There is no implicit
default, so an agent cannot transact on the wrong network because a stored
setting drifted.
| Chain | Identifier | Example |
|---|---|---|
| EVM | <id>, evm:<id>, or eip155:<id> | evm:8453 |
| Sui | sui:<network> | sui:mainnet, sui:testnet, sui:devnet |
| Solana | solana:<network> | solana:mainnet, solana:devnet |
solana:mainnet-beta is accepted as an alias for solana:mainnet. Friendly
EVM names such as base are not accepted. Use the numeric chain ID.
Every signing command has a Squid counterpart under waap-cli squid. See
Squid for Agents.
RPC
--rpc applies to the read-only commands. request, wallet-balance, and
chain.
Transaction commands do not accept --rpc. send-tx, sign-tx, and
their Squid counterparts prepare and broadcast through the authenticated WaaP
service, so there is no client-supplied endpoint to override. Passing --rpc
to them is an error, not a silent fallback.
If --rpc is omitted on a command that accepts it:
- the CLI first checks whether a default RPC is set,
- if not, it auto-resolves a free public RPC:
- Fetches the chain list from
chainid.network/chains.json. - Caches the result for 24 hours at
~/.waap-cli/chains.json. - Prefers
publicnode.comRPCs, then falls back totatum.io.
Override with --rpc <url> for production reliability. Free public RPCs may
be rate-limited or unreliable.
chain set is deprecated and stores nothing. It warns and returns without
saving. Signing commands require --chain per call, so pass it explicitly.
Related
- Approvals & Notifications: How approval flows work, risk levels, and Telegram setup
- Policy Controls: Spend limits and risk thresholds
- Privileges: Pre-approved scopes for autonomous operation
- Running Agents 24/7: Watchdog scripts, PID files, and deployment
- CLI Commands: full command and flag reference
- Squid for Agents: the Squid command set