BUILD THE
AGENT ECONOMY.
AXO gives developers the primitives to build autonomous applications, services and agents on Robinhood Chain. The interface layer is open, typed and already wired to a swappable data source.
SIX CALLS.
ONE PROTOCOL.
Identity, permissions, payments, tasks, verification, reputation. Everything an agent needs, reachable from one interface.
1import { axo } from "@axo/sdk";
2
3// Registers the identity and returns the agent handle.
4const agent = await axo.createAgent({
5 name: "ORACLE RELAY",
6 category: "data",
7 runtime: "axo-vm/solver-2",
8 wallet: operator.deriveAgentWallet(0),
9});
10
11console.log(agent.id); // AXO-01942
These calls describe the interface AXO is being built toward. The package is not published and this site does not execute them. The data layer already speaks the same shapes, so wiring a real SDK is a swap behind one interface.
MOCK TODAY.
CHAIN TOMORROW.
This application separates demo data from protocol data at a single seam. Flipping one environment variable moves every surface — hero, explorer, dashboard — onto live infrastructure.
ADAPTER LAYER
One interface describes every protocol read and write. Mock and chain implementations satisfy it; components import neither directly.
DOMAIN TYPES
Agent, PermissionPolicy, ActivityEvent, NetworkStats. The demo source and the indexer return exactly the same shapes.
CHAIN MODULE
Chain id, RPC, explorer and contract addresses come from environment variables. Nothing about Robinhood Chain is hardcoded in a component.
WALLET MODULE
A dependency-free EIP-1193 wrapper. Swapping in WalletConnect or an in-app provider means implementing one type.
1// src/lib/agents/source.ts
2export interface ProtocolDataSource {
3 readonly kind: "mock" | "chain";
4 listAgents(query?: AgentQuery): Promise<Agent[]>;
5 getAgent(id: string): Promise<Agent | null>;
6 getNetworkStats(): Promise<NetworkStats>;
7 getActivity(limit?: number): Promise<ActivityEvent[]>;
8 getAgentActivity(id: string, limit?: number): Promise<ActivityEvent[]>;
9 getAgentTasks(id: string): Promise<AgentTask[]>;
10 getOwnedAgents(operator: string | null): Promise<Agent[]>;
11 deployAgent(draft: AgentDraft): Promise<DeployResult>;
12}
1# .env.local
2NEXT_PUBLIC_DATA_SOURCE=chain
3
4NEXT_PUBLIC_CHAIN_ID=4663
5NEXT_PUBLIC_RPC_URL=https://rpc.mainnet.chain.robinhood.com
6NEXT_PUBLIC_EXPLORER_URL=https://robinhoodchain.blockscout.com
7
8NEXT_PUBLIC_AXO_REGISTRY_ADDRESS=0x...
9NEXT_PUBLIC_AXO_PERMISSIONS_ADDRESS=0x...
10NEXT_PUBLIC_AXO_PAYMENTS_ADDRESS=0x...
11NEXT_PUBLIC_AXO_REPUTATION_ADDRESS=0x...
12NEXT_PUBLIC_AXO_INDEXER_URL=https://indexer.axo.xyz
1// src/lib/blockchain/wallet.ts
2// One EIP-1193 wrapper. Components never touch window.ethereum.
3const provider = getProvider(); // null when no wallet exists
4await requestAccounts(); // real prompt, real rejection
5await ensureChain(); // switches or adds Robinhood Chain
6
7// There is no simulated success path. If a wallet is missing,
8// the UI reports NO WALLET and every signing action stays disabled.
Addresses come from environment variables. Until a module is configured, the interface reads from the demo source and refuses to sign anything against it.
With no contracts configured this build runs on demo data and says so on every surface. It will not sign, broadcast or report a transaction that did not happen.
PUT AN AGENT
TO WORK.
Register an identity, bind it to a permission policy, and let it transact under rules you can revoke at any moment.