6-agent AI swarm that researches, risk-scores & executes Uniswap swaps via 0G Compute + ENS routing.
UniswapSwarm is a fully autonomous, multi-agent DeFi trading swarm that identifies and executes profitable, low-risk token swaps across Uniswap V2, V3, V4, and UniswapX on Ethereum mainnet. The system is built on three core infrastructure pillars: the 0G Compute Network for decentralised, verifiable LLM inference; 0G Storage for immutable on-chain audit trails; and ENS as a live agent-discovery and routing registry.
The swarm runs a strict sequential pipeline of six specialised agents — Researcher, Planner, Risk, Strategy, Critic, and Executor — that collaborate through a shared BlackboardMemory (a session-scoped in-process key-value store). Every write to that store simultaneously uploads a JSON blob to the 0G Storage network via @0gfoundation/0g-ts-sdk, returning a root hash (CID) stored per entry. This means every reasoning step — every research report, trade plan, risk assessment, strategy proposal, critic verdict, and execution receipt — is permanently recorded on-chain with a verifiable content address. The UI surfaces each root hash as a live audit chip next to the agent's response card.
Every LLM call across all six agents is routed through the 0G Serving Broker (@0glabs/0g-serving-broker). The @swarm/compute package wraps the broker, auto-managing ledger deposits, provider sub-account initialisation, and acknowledgement flows. This makes every inference request verifiable and decentralised — no single hosted LLM provider controls the pipeline.
Agent pipeline in detail:
Researcher — Detects the current market narrative (AI, DeFi, L2, safe-haven, staking, neutral) from the Fear & Greed index and Reddit/news headlines. Fetches CoinGecko 24h market data for wallet tokens and narrative-focused candidates. Pulls live pool snapshots across V2, V3, V4, and UniswapX for each candidate. Applies goal-first prompt rules (the user's stated goal is injected at call time to pre-focus the candidate feed). Writes researcher/report and researcher/wallet_holdings to shared memory.
Planner — Reads the research report and produces a structured TradePlan: strategy type (momentum, safe-haven, narrative, etc.), conservative constraints (max slippage, max position size, min liquidity), and a per-agent task list. Writes planner/plan.
Risk Agent — Scores every candidate token through honeypot detection, ownership concentration checks, MEV exposure scoring, low-liquidity flags, and contract verification checks. Emits typed RiskFlag[] with severity levels (low / medium / high / critical). Any critical flag is a hard Critic veto. Writes risk/assessments.
Strategy Agent — Reads all prior memory, selects the highest-scoring safe candidate, and crafts an exact swap calldata spec: token-in, token-out, pool fee tier, route (direct or multi-hop), position size, slippage ceiling, and gas parameters. Stablecoin candidates are stripped before the LLM sees them; if the LLM still emits a stablecoin output, the agent forces a synthetic USDC→WETH fallback. Writes strategy/proposal.
Critic Agent — Performs a holistic review of the entire assembled plan. Hard-vetoes any stablecoin→stablecoin proposal with confidence=100. Otherwise produces an approved flag, confidence score (0–100), and a structured issues list. Writes critic/critique. The Executor will not proceed without an approved critique.
Executor — If the Critic approved, calls the Uniswap Trading API (check_approval → quote → swap) to get an optimised route and submit the transaction via the Universal Router (0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45). Runtime safety defaults to simulation because DRY_RUN=true; an additional SIMULATION_ONLY guard can force simulation even when DRY_RUN=false. Writes executor/result with the tx hash or simulation receipt.
ENS as a live service registry — Each agent has its own ENS subname on Sepolia (researcher.uniswapswarm.eth, planner.uniswapswarm.eth, etc.) with addr, text[name], and text[url] records. The orchestrator self-registers its live A2A endpoint URL into every agent's text[url] record at startup via publishAgentUrlsToEns(). On every CopilotKit request, the web app calls resolveSwarmAgentUrls() which fetches /api/ens/agents, reads the on-chain text[url] per agent, and uses those as the A2A routing targets with a 5-minute in-process cache. ENS is not decorative — removing it breaks the entire multi-agent routing layer. A separate delegate key is approved via approve-ens-delegate.ts so CI/CD can update records without exposing the domain owner key.
Front-end cockpit — Built with Next.js 16, CopilotKit, and the AG-UI / A2A protocol. Every send_message_to_a2a_agent call renders as an animated green "orchestrator → agent" card with a flowing arrow and pulsing badge, followed by a blue "agent → orchestrator" response card with 0G Storage audit chips showing root hashes and byte sizes. Structured JSON from each agent is parsed into first-class sidebar cards: candidate list, plan tasks, per-token risk scores with severity flags, strategy proposal, critic verdict, and execution receipt. Two HITL flows mirror the a2a-travel pattern: a pre-trade intent form (token-in, token-out, size, risk level) and a post-critic trade approval card — the Executor will not sign without an explicit user click.
Capital preservation is enforced at three independent layers: the Researcher's system prompt forbids stablecoin candidates and post-filters them programmatically; the Strategy Agent strips stablecoins before the LLM sees the candidate pool; the Critic hard-vetoes any proposal where both tokenIn and tokenOut are stablecoins. The canonical stablecoin set (USDC, USDT, DAI, FRAX, BUSD, FDUSD, PYUSD, USDe, USDS, and their contract addresses) is centralised in constants.ts.
Monorepo — Turborepo + pnpm workspaces. Six agent packages, an Express orchestrator server with REST + SSE + A2A JSON-RPC endpoints, a Next.js cockpit, and shared compute, memory, and shared packages. Deployable to Railway (config included).
Stack & Architecture
UniswapSwarm is a Turborepo + pnpm monorepo with six TypeScript agent packages, an Express orchestrator server, and a Next.js 16 cockpit. Every agent is a standalone A2A JSON-RPC server running on the same Express port via route-based dispatch (/a2a/agents/researcher, /a2a/agents/planner, etc.), so the entire swarm deploys as a single Railway service.
0G Compute — verifiable decentralised inference
Every LLM call across all six agents is routed through the 0G Serving Broker (@0glabs/0g-serving-broker). We built a thin @swarm/compute wrapper that: (1) checks the on-chain ledger balance before every call and auto-tops-up if low, (2) initialises the provider sub-account with a transfer-fund call on first use (this tripped us up — the chain wallet can show funded while the provider sub-account is still dry, requiring ~2 OG for the transfer fee, so we enforce a 5 OG minimum deposit), (3) selects an available inference provider from the indexer, and (4) issues the verifiable inference request. Model is qwen/qwen-2.5-7b-instruct configurable via ZG_INFERENCE_MODEL.
0G Storage — on-chain audit trail as a side effect
We implemented a BlackboardMemory class (memory) backed by a plain in-process Map<string, MemoryEntry>. Every memory.write(key, value) call: (1) writes synchronously to the Map so the next agent sees it at O(1) with zero latency, (2) concurrently fires storage.store() via @0gfoundation/0g-ts-sdk which uploads the JSON blob to 0G Storage and returns a root hash (CID), (3) stores that root hash in the MemoryEntry. If 0G Storage is unreachable, it falls back to a local SHA-256 so a storage outage never stalls the agent pipeline. This means the entire 6-step reasoning chain — research report, trade plan, risk assessments, strategy proposal, critic verdict, execution receipt — is permanently on-chain with verifiable content addresses. The web UI surfaces each root hash as a live audit chip (risk/assessments → 0x8ad6…ba6d3 · 943 B) next to every agent response card.
ENS as a live service registry (the creative angle)
Each agent has its own ENS subname on Sepolia (researcher.uniswapswarm.eth through executor.uniswapswarm.eth) with addr, text[name], and text[url] records set via ethers v6 and the ENS Name Wrapper contract. The orchestrator calls publishAgentUrlsToEns() at startup, which writes the live A2A base URL into every agent's text[url] record on-chain — idempotent, skips unchanged records. On every CopilotKit request, the web app calls resolveSwarmAgentUrls() → GET /api/ens/agents → reads on-chain text[url] per agent with a 5-minute in-process cache, and uses those as the A2A routing targets. This means updating a deployment URL on-chain propagates to live traffic within 5 minutes with zero redeploy. ENS is in the hot path of every single pipeline run — remove it and routing breaks entirely. We also implemented delegate approval (approve-ens-delegate.ts) so CI/CD can rotate text[url] records using a separate key without ever touching the domain owner key.
Uniswap integration
The Researcher fetches live pool snapshots across V2, V3, V4, and UniswapX for every candidate token. The Executor calls the Uniswap Trading API (check_approval → quote → swap) and routes execution through the Universal Router (0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45). We use DRY_RUN=true by default so the swarm runs in full simulation mode out of the box. A second SIMULATION_ONLY guard acts as an additional fuse. Capital preservation is enforced at three independent layers so even a hallucinating LLM cannot produce a stablecoin→stablecoin swap: the Researcher prompt + post-filter, the Strategy Agent pre-LLM strip + forced USDC→WETH fallback, and a Critic hard-veto at confidence=100.
CopilotKit + AG-UI / A2A front-end
The cockpit uses @copilotkit/react-core, @copilotkit/runtime, and @ag-ui/a2a-middleware. The middleware injects a send_message_to_a2a_agent tool into a Gemini-backed SwarmOrchestrationAgent, which calls each agent in sequence. Every tool call renders as an animated green "orchestrator → agent" card with a flowing arrow and pulsing badge; every response renders as a blue card sliding in from the right with 0G Storage audit chips. We built a SwarmAuditContext React context that fan-ins 0G Storage write events from every streamed message into a single dedicated Storage Audit Trail sidebar card. Two HITL flows are implemented: a pre-trade intent form and a post-critic trade approval gate — the Executor will not sign without an explicit user click, matching the a2a-travel approval pattern.
Notable hacks
The A2A middleware occasionally causes the orchestrator LLM to paste a previous agent's full JSON envelope as the task string to the next agent. We detect the JSON shape client-side and render a compact "📎 Forwarded payload" pill instead of dumping raw braces into the chat. impit (a TLS-fingerprint spoofer) is used to bypass bot detection on the Fear & Greed index and Reddit endpoints for market narrative detection — standard fetch gets blocked. Managed wallets are stored AES-256-GCM encrypted in DynamoDB, with the encryption key kept only in the server environment. The /managed-wallet/:address/ledger endpoint decrypts on the fly to check the 0G Compute ledger balance without ever sending the private key to the client.

