SLK (Short Lived Keys)
Short Lived Keys are the sole authorization path for AI agents. Every MCP request from an agent must carry a valid SLK token; the daemon validates it on every call and rejects anything outside the SLK’s stated scope. Operator-direct ops in the TUI / Web UI never need an SLK and never go through the agent path.
An SLK is not a wallet key. It is a typed, scoped, time-bounded, auditable policy contract between you and one agent.
Requesting an SLK
An agent calls request_slk with a full SlkDraft — typed
capabilities, per-capability scopes, a lifetime, and (optionally) rate
limits. The draft is queued as a proposal for operator review in
the Proposals tab (TUI / Web UI / CLI). The operator can narrow the
draft — never widen it — and then approve or deny. On approval the
daemon mints the SLK and returns the token to the agent; the agent then
operates autonomously until expiry, budget exhaustion, or revocation.
If a scoped wallet is password-protected, the operator unlocks it once, at approval time. The wallet’s secrets are encrypted at rest under a per-SLK 32-byte wrap key, so the agent keeps signing across a daemon restart without re-prompting.
Wallet scope
Each SLK’s wallet scope is explicit:
- Specific wallets — the SLK can only touch wallets the operator selected.
- All wallets — an explicit
allow_all_walletsgrant that includes every wallet now and any wallet added later under the same daemon.
An SLK with neither set authorizes nothing (an empty scope is not treated as “all wallets”) and is rejected at draft validation.
Capabilities
Capabilities are typed boolean flags. Each flag is necessary but not sufficient: the matching scope (see below) constrains how the flag may actually be exercised.
| Capability | Allows |
|---|---|
can_balance | Read native and token balances |
can_transactions | Read transaction history |
can_send_native | Send the chain’s native asset (SOL, ETH, MATIC, BNB) |
can_send_token | Send tokens (SPL on Solana, ERC-20 on EVM) |
can_swap | Swap tokens via DEX (Jupiter / Raydium on Solana) |
can_close_token | Close empty SPL token accounts and reclaim rent |
can_sign_message | Sign arbitrary messages (EVM personal_sign / Solana ed25519) |
can_sign_typed_data | Sign EIP-712 typed data (e.g. Polymarket CLOB orders) |
can_sign_hash | Sign a raw 32-byte digest (ERC-1271 / ERC-7739 SCW flows) |
can_wc_connect | Approve a WalletConnect session proposal autonomously |
Scopes
Per-capability scope structs narrow what each granted capability may do:
send_native— per-tx cap, total budget, recipient whitelist.send_token— per-mint per-tx cap, per-mint total budget, per-mint recipient whitelist, and global allowed / denied mint lists.swap— allowed input/output pair list, max slippage in bps, total USDC-denominated budget, allowed venues.sign_message— domain / dApp allowlist.sign_typed_data— EIP-712 domain match rules.sign_hash— context hashes the agent must declare (blind-signing guard).wc— allowed dApp origins for autonomous session approval.
Scopes always narrow a capability — the daemon refuses any operator edit that would widen scope after the SLK is minted.
Rate limits
Optional SlkRateLimit constrains ops/minute, ops/hour, ops/day. The
validator computes rolling windows from the activity log at dispatch
time. Hitting any limit returns a typed SlkViolation; the SLK itself
stays Active.
Lifetime
SlkLifetime carries an optional not_before (the SLK is dormant
until that timestamp) and a mandatory expires_at (hard cutoff). No
“forever” SLKs.
Inspection and revocation
slk_status— returns the typed status snapshot for a proposal id (before approval) or for an SLK token (after approval): lifecycle status, cumulative usage, expiry, capabilities, scopes.slk_revoke— proof-of-possession revoke; the agent holding the token can revoke it without operator approval (permission-reducing). Operators can also revoke from the SLKs tab.
A revoked or expired SLK is rejected at dispatch with a typed violation; no operator interaction needed.
Surviving a daemon restart
Per-SLK wallet secrets are AES-256-GCM encrypted at rest under the SLK’s own wrap key and rehydrated on daemon startup, so an agent’s autonomous signing continues uninterrupted for the SLK’s lifetime.
Locking a wallet (the operator’s panic button) clears the cached
secrets for every SLK on that wallet; the next agent op against that
wallet surfaces PasswordRequired, the operator unlocks once, and the
SLK resumes signing. Revocation and expiry sweep the persisted secrets
too.
When to use SLKs
You need an SLK for every agent operation. Typical patterns:
- periodic balance / transaction polling (read-only scope)
- capped recurring payouts to a fixed whitelist
- swap execution with a strict slippage ceiling
- dApp order signing (EIP-712) within a time and budget window
- autonomous WalletConnect session approval for a known dApp origin