Aegis is a wallet execution layer for AI agents on Solana devnet.
It lets agents act on-chain, but only inside strict safety rules.
- Creates wallets for agents
- Lets agents send structured intents
- Checks policy before any signature is allowed
- Signs through Privy-managed wallets
- Logs every approve/reject decision
Agents can decide what to do.
Agents cannot sign directly.
Aegis is the gate between agent decisions and wallet signatures.
- Programmatic wallet creation per agent
- Privy-based signing path
- Policy checks: assigned DSL rules + baseline limits + simulation
- Explicit policy precedence via assignment priority
- Agent-owned policy library with archive-only lifecycle
- DSL v1 + v2 compatibility for policy definitions
- Durable daily spend accounting (DB-backed)
- Idempotent intent execution by
agentId + idempotencyKey - Per-tx cap and daily cap controls
- Recipient, protocol, swap-pair, and action-scoped policy controls
- Structured audit logs for every intent
- TypeScript + Bun
@solana/web3.js@solana/spl-token- Orca Whirlpools
- Raydium Trade API
- Jupiter API
- Privy Node SDK
- SQLite
- Bun test
External demo clients (not part of Aegis core):
- Solana Agent Kit (SAK)
- OpenClaw
- OpenAI Agents SDK CLI (
scripts/agent-cli.tsx) - Any agent framework that can make HTTP requests
Watch the recorded demo on YouTube:
git clone https://github.com/fido1hn/agentic-autonomous-wallets.git
cd agentic-autonomous-walletsbun installcp .env.example .envRequired runtime vars:
SOLANA_RPC=https://api.devnet.solana.com
AEGIS_DB_PATH=./data/aegis.db
PRIVY_APP_ID=<privy-app-id>
PRIVY_APP_SECRET=<privy-app-secret>
LOG_LEVEL=info
OPENAI_API_KEY=<only needed for the demo agent CLI>
JUPITER_QUOTE_URL=https://lite-api.jup.ag/swap/v1/quote
JUPITER_SWAP_URL=https://lite-api.jup.ag/swap/v1/swapApp startup fails fast when PRIVY_APP_ID or PRIVY_APP_SECRET is missing.
The interactive agent CLI additionally requires OPENAI_API_KEY.
bun run startThis starts the Hono API server on http://localhost:3000 by default.
Pending DB migrations are applied automatically on startup.
OpenAPI docs are available at:
GET /openapi.json(raw OpenAPI spec)GET /docs(Swagger UI)
bun testRun one process per terminal and give each a unique name:
bun run demo:agent
# or explicit names
bun run scripts/agent-cli.tsx --name agent-alpha
bun run scripts/agent-cli.tsx --name agent-beta
bun run scripts/agent-cli.tsx --name agent-gammaThen chat naturally in each terminal, e.g.:
register yourself in aegiscreate your walletshow your session
bun run test:privy-liveGET /healthGET /openapi.jsonGET /docsPOST /agentsPOST /agents/:agentId/walletGET /agents/:agentId/walletGET /agents/:agentId/balancesPOST /policiesGET /policiesGET /policies/:policyIdPATCH /policies/:policyIdDELETE /policies/:policyIdPOST /agents/:agentId/policies/:policyIdDELETE /agents/:agentId/policies/:policyIdGET /agents/:agentId/policiesPOST /intents/executeGET /agents/:agentId/executions?limit=50
Agent-scoped endpoints require:
x-agent-id: <agentId>x-agent-api-key: <apiKey>
Use migrations as the source of truth for schema changes.
bun run startYou do not need to run bun run db:generate before bun run start unless you changed the schema locally and need to create a new migration file.
start applies pending migrations automatically before runtime work begins.
If you want to apply migrations without starting the API, use bun run aegis:init.
bun run db:generate
bun run startbun run db:pushNotes:
- Migrations are written to
/src/db/drizzle_migrations. - DB path comes from
AEGIS_DB_PATH(default:./data/aegis.db). - Commit migration files to git.
- Agent signs up and gets
agentId+apiKey - Agent requests a wallet and gets a wallet binding for that
agentId - Agent sends
execute_intentrequests withExecutionIntent - Aegis claims the
idempotencyKeyand starts a durable execution record - Aegis runs wallet resolution, policy checks, tx build, and simulation in memory
- If approved, Aegis asks Privy to sign
- Privy signs and the provider path broadcasts the transaction
- Aegis durably finalizes spend/accounting after broadcast
- Aegis returns an approved or rejected result
- Private key material never touches agent logic or app code
- Resolve agent wallet binding
- Evaluate assigned Aegis DSL policies for that wallet
- Evaluate baseline Aegis safety checks (global defaults)
- Build transaction payload (adapter)
- Run simulation gate
- Request provider signature + broadcast
- Persist decision logs and policy checks
- Persist/replay idempotent results for repeated requests
idempotencyKey is required for intent execution.
If the same execution is already in progress, Aegis waits internally and returns the same terminal result for duplicate requests with the same idempotency key.
If any step fails, execution is rejected with a reason code.
Rejected responses include stable reason codes. Detailed request and response examples are in docs/architecture.md.
Policies are owned by the creating agent and can be created, assigned, updated, unassigned, disabled, or archived.
Aegis now supports both:
aegis.policy.v1aegis.policy.v2
v1 policies continue to work unchanged.
v2 keeps the same flat rules[] model and adds stronger wallet controls:
allowed_recipientsblocked_recipientsallowed_swap_pairsallowed_swap_protocolsmax_lamports_per_day_by_actionmax_lamports_per_tx_by_actionmax_lamports_per_tx_by_mint
Important policy-authoring rule:
- a cap on transfers or swaps does not imply exclusivity for that action
- use
allowed_actionsonly when the user explicitly wantsonly transfersoronly swaps
In practice, the current policy system can express:
- "allow only swaps, no transfers"
- "send at most 1 SOL per day"
- "send at most 0.5 SOL per transaction"
- "only send to these addresses"
- "never send to these addresses"
- "only swap SOL to USDC"
- "only use Orca for swaps"
- "only allow these token mints"
- "cap this mint to X per transaction"
- "never swap above X bps slippage"
Detailed policy examples are in docs/architecture.md.
The current runtime supports:
- Create a policy
- Assign it to the wallet
- Trigger a rejection
- Inspect
policyMatchto see the exact blocking rule - Update the policy
- Retry the same action successfully
autoprefersorcaon devnetraydiumis available explicitlyjupiteris mainnet-only in this build- detailed backend behavior and payload examples are in
docs/architecture.md
- Create 3 agents
- Create 3 wallets
- Fund one or more wallet addresses on devnet
- Ask one agent for its balance
- Ask one agent to transfer SOL to another
- Ask one agent to transfer an SPL token
- Ask one agent to swap SOL to USDC through Orca on devnet
- Inspect execution logs for approved/rejected runs
- an agent can register itself and receive API credentials
- an agent can provision its own wallet
- an agent can read native SOL and SPL balances
- an agent can transfer SOL and SPL tokens
- an agent can swap on Solana devnet
- an agent can create, assign, update, and archive wallet policies
- Aegis can reject actions before signing and explain the exact blocking policy rule
Key management stays with Privy.
Policy and intent control stays with Aegis.
That means:
- agents keep autonomy to propose actions
- Aegis keeps authority to approve/reject actions
- provider only signs when Aegis already approved
This is the product edge: deterministic intent policy enforcement before signing.
Canonical reason codes are centralized in:
src/core/reasonCodes.ts
Use these constants for API/UI handling instead of ad-hoc string literals.
ExecutionIntent: the structured request an agent sends to Aegisapprove: Aegis allows signing and returns a tx signaturereject: Aegis blocks signing and returns a reason code
This is a prototype, not production custody software.
Current protections:
- Agent never gets raw private key
- Signing is behind policy gates
- Privy handles primary key custody
- Simulation gate before broadcast
- Full approve/reject audit trail
- This submission is explicitly devnet-first.
- Privy is the only active custody/signing backend in v1.
- Token symbol resolution is intentionally narrow for the demo:
SOLis resolved automaticallyUSDCis resolved automatically- other tokens should be provided by mint address
- Swap availability still depends on devnet liquidity and protocol support.
- Policy DSL v2 is intentionally flat; nested boolean logic is not part of this submission.
aegis-agent-wallet/
src/
docs/
scripts/
tests/
README.md
SKILLS.md
.env.example
- Skills:
SKILLS.md - Deep dive:
docs/architecture.md
MIT