@aomi-labs/client
v0.1.16
Published
Platform-agnostic TypeScript client for the Aomi backend API
Readme
@aomi-labs/client
TypeScript client for the Aomi on-chain agent backend. Works in Node.js and browsers.
Install
npm install @aomi-labs/client
# or
pnpm add @aomi-labs/clientQuick Start
Low-level client
Direct HTTP/SSE access to all backend endpoints.
import { AomiClient } from "@aomi-labs/client";
const client = new AomiClient({ baseUrl: "https://api.aomi.dev" });
const threadId = crypto.randomUUID();
await client.createThread(threadId);
const response = await client.sendMessage(threadId, "What's the price of ETH?");
console.log(response.messages);Session (high-level)
Handles polling, event dispatch, and wallet request management automatically.
import { Session } from "@aomi-labs/client";
const session = new Session(
{ baseUrl: "https://api.aomi.dev" },
{ namespace: "default" },
);
// Blocking send — polls until the agent finishes responding
const result = await session.send("Swap 1 ETH for USDC on Uniswap");
console.log(result.messages);
// Listen for wallet signing requests
session.on("wallet_tx_request", async (req) => {
const signed = await mySigner.signTransaction(req.payload);
await session.resolve(req.id, { txHash: signed.hash });
});
session.close();Session API
Constructor
new Session(clientOptions: AomiClientOptions, sessionOptions?: SessionOptions)
// or pass an existing AomiClient instance:
new Session(client: AomiClient, sessionOptions?: SessionOptions)| Option | Default | Description |
| ---------------- | --------------------- | --------------------------------------- |
| sessionId | crypto.randomUUID() | Thread/session ID |
| namespace | "default" | Backend namespace |
| publicKey | — | Wallet address |
| apiKey | — | API key for private namespaces |
| userState | — | Arbitrary user state sent with requests |
| pollIntervalMs | 500 | Polling interval in ms |
| logger | — | Pass console for debug output |
Methods
| Method | Description |
| ---------------------- | ----------------------------------------------------------------- |
| send(message) | Send a message, wait for completion, return { messages, title } |
| sendAsync(message) | Send without waiting — poll in background, listen via events |
| resolve(id, result) | Resolve a pending wallet request |
| reject(id, reason?) | Reject a pending wallet request |
| interrupt() | Cancel current processing |
| close() | Stop polling, unsubscribe SSE, clean up |
| getMessages() | Current messages |
| getTitle() | Current session title |
| getPendingRequests() | Pending wallet requests |
| getIsProcessing() | Whether the agent is processing |
Events
session.on("wallet_tx_request", (req) => { ... });
session.on("wallet_eip712_request", (req) => { ... });
session.on("messages", (msgs) => { ... });
session.on("processing_start", () => { ... });
session.on("processing_end", () => { ... });
session.on("title_changed", ({ title }) => { ... });
session.on("tool_update", (event) => { ... });
session.on("tool_complete", (event) => { ... });
session.on("system_notice", ({ message }) => { ... });
session.on("system_error", ({ message }) => { ... });
session.on("error", ({ error }) => { ... });
session.on("*", ({ type, payload }) => { ... }); // wildcard.on() returns an unsubscribe function:
const unsub = session.on("messages", handler);
unsub(); // stop listeningCLI
The package includes an aomi CLI for scripting and Claude Code skills.
When installed globally or in a project, the executable name is aomi.
For one-off usage, run commands via npx @aomi-labs/client ....
npx @aomi-labs/client --version # print installed CLI version
npx @aomi-labs/client chat "swap 1 ETH for USDC" # talk to the agent
npx @aomi-labs/client chat "swap 1 ETH for USDC" --model claude-sonnet-4
npx @aomi-labs/client chat "swap 1 ETH" --verbose # stream tool calls + responses live
npx @aomi-labs/client app list # list available apps
npx @aomi-labs/client model list # list available models
npx @aomi-labs/client model set claude-sonnet-4 # switch the current session model
npx @aomi-labs/client secret list # list configured secret handles
npx @aomi-labs/client --secret ALCHEMY_API_KEY=... # ingest a secret for the active session
npx @aomi-labs/client log # show full conversation history
npx @aomi-labs/client tx # list pending + signed txs
npx @aomi-labs/client sign tx-1 # sign a specific pending tx
npx @aomi-labs/client status # session info
npx @aomi-labs/client events # system events
npx @aomi-labs/client close # clear sessionWallet connection
Pass --public-key so the agent knows your wallet address. This lets it build
transactions and check your balances:
npx @aomi-labs/client chat "send 0 ETH to myself" \
--public-key 0x5D907BEa404e6F821d467314a9cA07663CF64c9BThe address is persisted in the state file, so subsequent commands in the same session don't need it again.
Model selection
The CLI can discover and switch backend models for the active session:
$ npx @aomi-labs/client model list
claude-sonnet-4
gpt-5
$ npx @aomi-labs/client model set gpt-5
Model set to gpt-5
$ npx @aomi-labs/client chat "hello" --model claude-sonnet-4aomi model set persists the selected model in the local session state after a
successful backend update. aomi chat --model ... applies the requested model
before sending the message and updates that persisted state as well.
Secret management
The CLI supports per-session secret ingestion. This lets the backend use opaque handles instead of raw secret values:
$ npx @aomi-labs/client --secret ALCHEMY_API_KEY=sk_live_123
Configured 1 secret for session 7f8a...
ALCHEMY_API_KEY $SECRET:ALCHEMY_API_KEY
$ npx @aomi-labs/client --secret ALCHEMY_API_KEY=sk_live_123 chat "simulate a swap on Base"You can inspect or clear the current session's secret handles:
$ npx @aomi-labs/client secret list
ALCHEMY_API_KEY $SECRET:ALCHEMY_API_KEY
$ npx @aomi-labs/client secret clear
Cleared all secrets for the active session.Transaction flow
The backend builds transactions; the CLI persists and signs them:
$ npx @aomi-labs/client chat "swap 1 ETH for USDC on Uniswap" --public-key 0xYourAddr --chain 1
⚡ Wallet request queued: tx-1
to: 0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD
value: 1000000000000000000
chain: 1
Run `aomi tx` to see pending transactions, `aomi sign <id>` to sign.
$ npx @aomi-labs/client tx
Pending (1):
⏳ tx-1 to: 0x3fC9...7FAD value: 1000000000000000000 chain: 1
$ npx @aomi-labs/client sign tx-1 --private-key 0xac0974...
Signer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
IDs: tx-1
Kind: transaction
Tx: tx-1 -> 0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD
Value: 1000000000000000000
Chain: 1
Exec: aa (alchemy, 7702; fallback: eoa)
✅ Sent! Hash: 0xabc123...
Backend notified.
$ npx @aomi-labs/client tx
Signed (1):
✅ tx-1 hash: 0xabc123... to: 0x3fC9...7FAD value: 1000000000000000000EIP-712 signing is also supported. When the backend requests a typed data
signature (e.g. for CoW Protocol orders or permit approvals), it shows up as a
pending tx with kind: eip712_sign. aomi sign handles both kinds
automatically:
$ npx @aomi-labs/client tx
Pending (1):
⏳ tx-2 eip712 Sign CoW swap order (2:15:30 PM)
$ npx @aomi-labs/client sign tx-2 --private-key 0xac0974...
Signer: 0xf39Fd...92266
IDs: tx-2
Kind: eip712_sign
Desc: Sign CoW swap order
Type: Order
✅ Signed! Signature: 0x1a2b3c4d5e6f...
Backend notified.By default, aomi sign tries account abstraction first. In default mode the CLI
retries unsponsored Alchemy AA when sponsorship is unavailable, then falls back
to direct EOA signing automatically if AA still fails. Use --aa to require AA
only, or --eoa to force EOA only.
Verbose mode & conversation log
Use --verbose (or -v) to see tool calls and agent responses in real-time:
$ npx @aomi-labs/client chat "what's the price of ETH?" --verbose
⏳ Processing…
🔧 [tool] get_token_price: running
✔ [tool] get_token_price → {"price": 2045.67, "symbol": "ETH"}
🤖 ETH is currently trading at $2,045.67.
✅ DoneWithout --verbose, only the final agent message is printed.
Use aomi log to replay the full conversation with all messages and tool results:
$ npx @aomi-labs/client log
10:30:15 AM 👤 You: what's the price of ETH?
10:30:16 AM 🤖 Agent: Let me check the current on-chain context for you.
10:30:16 AM 🔧 [Current ETH price] {"price": 2045.67, "symbol": "ETH"}
10:30:17 AM 🤖 Agent: ETH is currently trading at $2,045.67.
— 4 messages —Options
All config can be passed as flags (which take priority over env vars):
| Flag | Env Variable | Default | Description |
| ----------------------- | ----------------- | ---------------------- | -------------------------------------------- |
| --backend-url | AOMI_BASE_URL | https://api.aomi.dev | Backend URL |
| --api-key | AOMI_API_KEY | — | API key for non-default apps |
| --app | AOMI_APP | default | App |
| --model | AOMI_MODEL | — | Model rig to apply before chat |
| --secret <NAME=value> | — | — | Ingest secret values for the active session |
| --public-key | AOMI_PUBLIC_KEY | — | Wallet address (tells agent your wallet) |
| --private-key | PRIVATE_KEY | — | Hex private key for aomi sign |
| --rpc-url | CHAIN_RPC_URL | — | RPC URL for transaction submission |
| --chain | AOMI_CHAIN_ID | 1 | Chain ID (1, 137, 42161, 8453, 10, 11155111) |
| --verbose, -v | — | — | Stream tool calls and agent responses live |
| --version, -V | — | — | Print the installed CLI version |
# Use a custom backend
npx @aomi-labs/client chat "hello" --backend-url https://my-backend.example.com
# Full signing flow with all flags
npx @aomi-labs/client chat "send 0.1 ETH to vitalik.eth" \
--public-key 0xYourAddress \
--api-key sk-abc123 \
--app my-agent \
--model claude-sonnet-4
npx @aomi-labs/client sign tx-1 \
--private-key 0xYourPrivateKey \
--rpc-url https://eth.llamarpc.comSigning modes
aomi sign supports three practical modes:
- Default: AA first, then automatic EOA fallback if AA is unavailable or fails
--aa: require AA and do not fall back to EOA--eoa: force direct EOA execution
How state works
The CLI is not a long-running process — each command starts, runs, and
exits. Conversation history lives on the backend. Between invocations, the CLI
persists local state under AOMI_STATE_DIR or ~/.aomi by default:
| Field | Purpose |
| --------------- | ------------------------------------------------------ |
| sessionId | Which conversation to continue |
| clientId | Stable client identity used for session secret handles |
| model | Last successfully applied model for the session |
| publicKey | Wallet address (from --public-key) |
| chainId | Active chain ID (from --chain) |
| secretHandles | Opaque handles returned for ingested secrets |
| pendingTxs | Unsigned transactions waiting for aomi sign <id> |
| signedTxs | Completed transactions with hashes/signatures |
$ npx @aomi-labs/client chat "hello" # creates session, saves sessionId
$ npx @aomi-labs/client chat "swap 1 ETH" # reuses session, queues tx-1 if wallet request arrives
$ npx @aomi-labs/client sign tx-1 # signs tx-1, moves to signedTxs, notifies backend
$ npx @aomi-labs/client tx # shows all txs
$ npx @aomi-labs/client close # clears the active local session pointerSession files live under ~/.aomi/sessions/ by default, with an active session
pointer stored in the state root.
