The agent-native wallet. A agent native wallet where a guardian agent reads every transaction and signature before it's signed, and where third-party agents are installed, validated, and managed like apps — never trusted by default.
Agents are starting to move money. A yield bot wants to rebalance your stables, a trading agent wants a session key, a protocol wants you to sign an approval. The old wallet model — "click sign, hope for the best" — doesn't survive contact with software that acts on your behalf. mallow is built around two ideas:
Nothing gets signed blind. Whether the request comes from a dApp over
WalletConnect, from you, or from an installed agent, the Guardian reviews it
first and returns a plain-language verdict with a risk level (info → low →
medium → high → critical). High/critical verdicts require typed
confirmation before the wallet will sign.
The Guardian isn't a regex over calldata — it's a small multi-agent pipeline:
- Planner — picks the minimum set of analysis tools to run for this request.
- Analyzer — investigates by calling tools over several rounds:
decode_calldata— decode the function and argumentsget_contract_info— verification status, ABI, proxy/implementation (Etherscan)lookup_sourcify_signature— resolve unknown selectors via Sourcifysimulate_transaction— execute against an anvil fork of live state to capture balance changes, ERC-20/721 transfers, storage diffs, and reverts
- Summarizer — turns the evidence into a verdict a non-developer can act on: what happens, what it costs, and whether it's safe.
The result is a GuardianVerdict — risk level, summary, concrete asset impacts,
findings, the decoded call, and the simulation diff — streamed to the UI as it
works.
Third-party agents talk to mallow over a small agent protocol
(@mallow/agents-protocol). An agent service exposes its intent as an
AgentRequest (a list of tx and sig actions); the wallet fetches it, runs
it through the Guardian like any other request, shows you exactly what will be
sent or signed, and only then executes.
Crucially, the wallet signs or broadcasts but never interprets what a signature authorizes. An agent can ask for, say, a ZeroDev session-account approval, and mallow signs the bytes verbatim — the agent's implementation never leaks into the wallet, and the wallet never has to trust the agent's claims about what it's doing. The Guardian is what closes that gap: it independently validates the request instead of taking the agent's word for it.
Install / manage flow per agent: /request (what it wants) → Guardian review →
/install (execute + register) → /status (what it's doing) → /uninstall
(revoke and unwind positions). Installations are stored per-wallet; the Guardian
itself is an always-on builtin.
Two reference agents ship in the repo:
- Guardian (
guardian-agent-service) — the always-on transaction reviewer above. - Sprout / auto-invest (
auto-invest-agent-service) — moves idle USDC into vetted yield venues and pulls it back when rates dip. A worked example of a third-party agent driving the wallet through the protocol.
A pnpm workspace with three top-level services:
wallet/—@mallow/wallet, the Next.js wallet app (passkey-encrypted EOA, WalletConnect, approval queue, agent management UI).agents-protocol/—@mallow/agents-protocol, the shared agent-protocol wire types.agents/— runnable agent services:agents/guardian-agent-service—@mallow/guardian-agent-serviceagents/auto-invest-agent-service—@mallow/auto-invest-agent-service
The repo root holds only workspace config and delegating scripts. Run a service
via its prefixed script (pnpm wallet:<cmd>, pnpm agent:guardian:<cmd>,
pnpm agent:auto-invest:<cmd>), or target any package directly with
pnpm --filter <pkg> <cmd>.
dApp (WalletConnect) ─┐
you (send / sign) ─┼─▶ Guardian ─▶ verdict (risk + simulation + summary)
installed agent ─┘ plan→analyze→summarize │
▼
high/critical → typed confirmation required
│
▼
passkey unlock → sign / broadcast
The EOA private key is encrypted at rest with AES-GCM under a key derived (HKDF-SHA-256) from your passkey's PRF output — so unlocking to sign is a passkey prompt, not a seed phrase.
- pnpm, Node ≥ 20
- Foundry (
cast,anvil) —curl -L https://foundry.paradigm.xyz | bash && foundryup(the Guardian forks withanvilto simulate) - LM Studio (or any OpenAI-compatible endpoint) running locally with a chat-completions model loaded — the Guardian's planner/analyzer/summarizer run on it
# env is per-service; see .env.example for which keys go where
cp .env.example wallet/.env.local # edit: full wallet env
cp .env.example .env.local # edit: trim to the agent subset
pnpm install
pnpm wallet:test
pnpm wallet:dev # wallet on :3000
pnpm agent:guardian:dev # Guardian service on :3002To run the agent services together with their Postgres, use docker-compose up.
Env is per-service: the wallet reads wallet/.env.local; agent services read the
root .env.local. Shared keys (RPC, ZeroDev, Morpho vault) are duplicated across
both. See .env.example for the per-service grouping.
ETHERSCAN_API_KEY— required (etherscan.io, used via the v2 multichain endpoint for contract verification/ABI lookups)ALCHEMY_API_KEY— required for token portfolio discovery via the Alchemy Portfolio APILLM_BASE_URL— defaulthttp://localhost:1234/v1LLM_MODEL— defaultqwen/qwen2.5-coder-14b-instructLLM_API_KEY— any non-empty placeholderNEXT_PUBLIC_REOWN_PROJECT_ID— WalletConnect / Reown project id (free, cloud.reown.com)NEXT_PUBLIC_GUARDIAN_AGENT_URL— where the wallet reaches the Guardian (defaulthttp://localhost:3002)NEXT_PUBLIC_AUTO_INVEST_AGENT_URL— where the wallet reaches Sprout (defaulthttp://localhost:8787)ZERODEV_URL,DATABASE_URL— agent-service only (session accounts, auto-invest state)
pnpm wallet:test— unit + integration.- Set
ETHERSCAN_API_KEYinwallet/.env.local; boot LM Studio with a model on:1234. pnpm agent:guardian:dev(Guardian on:3002) andpnpm wallet:dev.- Walk through: create wallet → unlock → pick the "infinite approve unverified"
demo → run Guardian → confirm verdict shows
highorcriticaland requires typed confirmation. Cancel. - Pick "send 0.001 ETH" demo → run Guardian → expect
low/info. Sign and broadcast only from a wallet funded. - Install the Sprout agent → confirm its
AgentRequestis reviewed by the Guardian before any signature is produced. - Confirm the tx on Basescan.