Most crypto-and-AI projects are assembled from other people's parts. You rent an RPC endpoint, sign up for a hosted model and paste in an API key, call a third-party price feed with another key, and bolt a token on top. Each integration is its own account, its own bill, its own dashboard. Circuit is built the other way around: it owns its whole stack, from the validator plugin that reads the chain, to the model that does the reasoning, to the payment rail that ties the economics together. The Circuit SDK is how you build on that stack, and it inherits the same shape — one wallet instead of a drawer full of API keys, and a single composable surface over every part of the network.

This is a tour of that surface: what the SDK is, the layers it's made of, how each one reaches into a live piece of the ecosystem, and — the part that's grown the most since this toolkit first shipped — how the agents you write run wherever you put them: some that only think and sense, some that trade; on your own laptop, your own server, or Circuit's mesh, without changing a line of your code. All of it, including the circuit terminal app, now lives in one repository, MIT-licensed and versioned for release.


One wallet, no API keys

Start with the thing that makes the rest possible. Every paid call in Circuit settles the same way: the server answers your first, unpaid request with 402 Payment Required, names a price in CIRC and a treasury to send it to; you transfer the CIRC on Solana; you retry the request with the transaction signature attached; the server verifies the payment on-chain and returns the result. This is x402 — HTTP's long-dormant 402 status code revived as a real micropayment protocol.

The consequence for a developer is the headline feature of the whole SDK: there are no API keys. A wallet is the account and the meter at once. You don't register, you don't provision a key, you don't get a monthly invoice. You hold a Solana keypair with some CIRC in it, and every call pays for itself.

import { makeWallet, Inference, Data } from '@circuit-llm/sdk';

const wallet = makeWallet();              // from CIRCUIT_WALLET, or pass a keypair
const ai   = new Inference({ wallet });   // pays CIRC per call (x402), automatically
const data = new Data({ wallet });

for await (const tok of ai.chatStream({ messages: [{ role: 'user', content: 'explain x402 in one line' }] }))
  process.stdout.write(tok);              // stream the decentralized 72B

const px = await data.tokenPrice('8fQgfsRnRkKSeNUhevT7wp8mhNvMSJdLn1fJi4oVpump');

That's the entire setup. The Inference and Data clients each carry the wallet, and the moment a server asks to be paid, the SDK runs the 402 loop for you — transfers the CIRC, retries — without you writing a line of payment code. You can cap the spend per call with maxSpendRaw, approve payments with a hook, or, on a trusted host, bypass payment entirely with an internal key. Read-only data and the network's topology need no wallet at all.


A spine, the layers it carries, and the app on top

The SDK is a TypeScript monorepo of twelve small, scoped packages, a standalone Python client, and the circuit command-line app itself. The organizing rule is simple: x402 is the spine, everything paid depends on it, and everything depends on a tiny core.

packages/
  x402/      the payment spine: 402 → pay CIRC → retry · verify        ← zero deps
  core/      http · config (DI) · ed25519 identity · owner-auth · types  ← zero deps
  inference/ │ data/ │ wallet/        the consume layer
  agent/     CircuitAgent + four custody modes + verified-intents + scaffold
  attest/    Verified Intents: authenticated inputs + the decision gate ← zero deps
  node/      │ onchain/               the contributor layer
  bundle/    content-addressed, signed agent bundles                    ← zero deps
  vault/     the non-custodial on-chain vault client        (opt-in: Anchor)
  sdk/       meta-package — re-exports the consume + agent + contributor packages
apps/
  cli/       the `circuit` terminal console, built on the packages above
circuit-py/  a stdlib-only Python consume client

Three packages sit at the bottom with zero runtime dependencies. @circuit-llm/x402 is the payment spine itself — generic enough to wrap any x402 endpoint in the world, not just Circuit's — and it ships the server-side verifier too, so you can meter your own API with the same code. @circuit-llm/core is the plumbing: an HTTP client, an injectable config so nothing is hard-wired, an ed25519 identity, the owner-auth request signing that proves a control-plane request came from your wallet, and the shared types. @circuit-llm/bundle is the codec for packaging an agent into a content-addressed, signed artifact. Everything else builds on those, and only two packages pull anything heavy: @circuit-llm/wallet brings Solana, and the opt-in @circuit-llm/vault brings Anchor. A consumer who just wants inference and data installs neither.

On top sit the packages that reach into the live network. They map onto what an autonomous program does — think, sense, act, and live somewhere — with acting (trading) needed only by the agents that actually move funds.


Think, sense, act, live

Think — @circuit-llm/inference. An OpenAI-compatible client for the decentralized 72B. You call chat or chatStream exactly as you would any hosted model, except the model isn't hosted anywhere in particular: it's split layer-by-layer across a mesh of independent commodity GPUs, and your call is paid per request in CIRC. The interface is deliberately familiar, so existing code ports with almost no change while, underneath, the request is served by contributor hardware and settled on-chain.

Sense — @circuit-llm/data. A typed client for the Circuit Data API: token price and info, wallet analytics, token security, holders, DeFi yields, trending lists, a real-time price feed, market overviews — more than forty endpoints in all, some free, most paid per call, with a generic get() escape hatch for anything new the API adds. The data isn't proxied from a third party; it comes out of Circuit's own pipeline — a validator geyser plugin and an indexer that turn raw on-chain activity into prices, candles, and discovery feeds in real time. The SDK gives you that pipeline as typed methods and, when you want it, signed, so an agent can prove what it acted on (more on that below).

Act — @circuit-llm/wallet. SOL and CIRC balances, transfers, and SOL↔CIRC swaps through Jupiter. CIRC is a Token-2022 mint with its own handling quirks; the wallet package hides them. It reads and sends across a primary RPC and public fallbacks, so a rate-limited or stalled endpoint doesn't stop a balance check or a transfer — and a transaction is signed once before that failover, so a retry on another RPC re-broadcasts the same bytes and can never spend twice. It implements the PaymentWallet interface @circuit-llm/x402 needs (which is what lets the consume clients pay for themselves), and its walletTradeExecutor is what powers self-custody agent trading — the second of the four custody modes below.

Live — @circuit-llm/agent. The runtime that turns those clients into something that runs on its own — an agent, deployed wherever you want it. This is where the SDK stops being a set of clients and becomes a place to ship something that lives, and it's the piece that has changed the most.


Agents: build one, run it anywhere

@circuit-llm/agent is the runtime for autonomous agents. You extend a base class, implement a single tick(), and the runtime owns the rest — environment wiring, config, the heartbeat, logs, and the graceful-shutdown lifecycle. What the agent does in that tick() is entirely yours.

import { CircuitAgent } from '@circuit-llm/agent';

class DipBot extends CircuitAgent {
  async tick() {
    const trending = await this.data().tokenTrending();   // sense
    const pick = decide(trending);                        // your strategy
    if (pick) {
      const r = await this.buy(pick.mint, 0.01);          // act, through custody
      if (r.ok) this.log(`bought ${pick.mint} (${r.code})`);
    }
  }
}

new DipBot().run();

Plenty of agents never trade at all. One that watches a wallet and pings you when it moves, summarizes the market every hour, or feeds a data pipeline just thinks (inference) and senses (data) — it holds no key and needs no custody. Trading is one thing an agent can do, not what an agent is: this.buy and this.sell only enter the picture when it moves funds.

And you run it wherever it makes sense. In dev it's a process on your laptop; in production it's the same file on your own always-on server, or handed to Circuit's CPU mesh to run on borrowed hardware when you'd rather not run a server yourself — or anywhere else you can run Node. The mesh is an option, not the definition. It does raise the one question that only bites once an agent trades on hardware you don't fully control: how do the funds stay safe? That is the job of custody.


Custody: match it to where the agent runs

this.buy/this.sell never sign anything locally by default — they hand an intent to custody, one interface with four backends. Your strategy is byte-for-byte identical across all four; what changes is how the funds are held. You pick the backend that fits where the agent runs and how much you trust that place:

That single Custody interface is the quiet design win. The same strategy file runs unchanged whether you paper-test it on your laptop, trade it self-custodied on a box you own, hand it to the mesh under the off-box signer, or route it through the on-chain vault — you swap custody to match where it runs, never the code. One strategy, deployed wherever you want, with the money safe by construction.


Two more protections that ride on custody

Off-box (or on-chain) custody stops a host from stealing. Two further pieces stop a host from cheating and let an owner always recover.

Verified Intents — @circuit-llm/attest. Custody alone doesn't stop a hostile host from making your agent place a trade it chose, within policy. Verified Intents closes that. You commit a decision rule (requireVerifiedIntent), and custody signs a trade only if that trade is the genuine output of the rule re-evaluated on authenticated inputs — signed first-party data, a signed inference receipt, or a zkTLS proof for third-party data. A tampered agent, a faked price, or a host-chosen trade is rejected before anything is signed (decision-unjustified / evidence-invalid). @circuit-llm/attest carries the evidence types, the rule evaluator, and the decision gate; the Data API and the inference gateway can sign their responses on request; and the same check is enforced both in the off-box signer and on-chain in the vault. It's pure software, works on any CPU, and is live across the stack. It covers any rule the signer can re-check — a deterministic strategy, or a rule over a signed-AI verdict, which is most agents. A genuine black box the signer can't re-run is the one case that needs a hardware enclave: the separate Sealed Agents path.

Owner recovery. Your funds are always yours to pull home. With the vault, the owner is the chain's sole withdraw authority, enforced on-chain — and the SDK's @circuit-llm/vault drives it directly. With the off-box signer, the same recovery runs through the agent-cloud control plane — withdraw returns funds to the committed owner address, and setOwner/export hand you full control — driven from the circuit CLI. What the SDK contributes there is the authentication: every control-plane request is signed with @circuit-llm/core's owner-auth, the wallet itself proving the request, so a multi-tenant control plane can tell owners apart without holding any secret of yours. The autonomous path can trade; only you can take the money out.

The honest residuals are narrow and worth naming: a host can still withhold or time a genuinely-valid trade, and it can observe your strategy. It can never invent a trade or move your funds. Hiding the strategy itself is the one thing that needs the hardware path. The full failover-and-trust story is its own article.


The terminal that runs on the same packages

For a long time Circuit had two front doors that did the same work twice. The circuit CLI — the interactive terminal console — was the project's first tool, and it grew the scars of real use: a wallet that fails over across RPCs, a bundle packer that refuses to ship a secret file, the owner-auth signing that authenticates a request. The SDK was the clean library extraction that came later. Each had its own copy of the wallet, the bundle codec, the request signing — and copies drift.

So the two were merged. The CLI now lives in the same monorepo, at apps/cli, and runs on the very @circuit-llm/* packages this article describes. The duplication is gone: one wallet, one bundle codec, one owner-auth. The cross-repo contracts that have to match byte-for-byte — the bundle signature and the owner-auth message — are pinned by tests that verify what the CLI produces against the real servers that consume it. Where the CLI's version was the more battle-tested one, the fix was to level the SDK up to it rather than weaken the CLI, so the shared logic is now both the single source and the stronger one.

The practical result is that the same toolkit you import from also runs as a program you can just open:

npm run cli        # or, linked globally, simply: circuit

Its nine modules are the whole network from a terminal: chat with the decentralized 72B (with a live cost meter), check and move CIRC, pull market data with braille candle charts, watch a swarm of trading agents, inspect network health, create/run/host an agent, lend your CPU to the cloud, or print the one-line command that attaches a GPU to the mesh. "One toolkit for the whole network" stopped being a slogan about a set of libraries and became one repository that holds the libraries, the Python client, and the human-facing app — all on the same spine.


The other direction: joining the network from code

The same SDK that consumes the network can also join it. @circuit-llm/node speaks the two protocols a contributor needs: the inference-mesh control plane (register a GPU, signal ready, heartbeat) and the public node registry (announce a node, ping it). The heavy lifting of actually serving model layers stays in the node image; the membership and coordination are a few typed calls.

import { MeshControl, generateMeshIdentity, verifyStake } from '@circuit-llm/sdk';

const id   = generateMeshIdentity();
const mesh = new MeshControl({ controlUrl: 'http://control:18932', identity: id });
const { assignment } = await mesh.register({ endpoint: ['1.2.3.4', 5000], capacityLayers: 40, modelFp: 'qwen2.5-72b-awq' });
await mesh.ready();

const stake = await verifyStake(wallet, pool, 100_000, { rpcUrl });   // ≥ 100k CIRC staked?

Alongside it, @circuit-llm/onchain reads what matters on-chain — a wallet's CIRC balance, its StakePoint stake, and the mesh_registry control-plane records that hold node trust and the model topology — using pure JSON-RPC with no @solana/web3.js at all. Staking is how a node earns access and payouts, so being able to check it from a few hundred lines of dependency-free code matters for anyone running infrastructure.


How the pieces line up

The SDK isn't a wrapper bolted on after the fact. Each package is extracted from a system that already runs in production — the same x402 flow the network settles on, the same custody contract the agents already use, the same mesh protocol the GPUs already speak — and each reaches into a specific part of the ecosystem.

SDK package Reaches into
@circuit-llm/x402 The CIRC treasury and Token-2022 settlement — the payment layer every service shares
@circuit-llm/core Identity + owner-auth request signing shared by every control-plane call
@circuit-llm/inference The decentralized DLLM — a 72B split across commodity GPUs
@circuit-llm/data The Data API, fed by the validator geyser plugin, the indexer, and the price feed
@circuit-llm/wallet Solana, CIRC, and Jupiter for swaps — plus self-custody trade execution
@circuit-llm/agent The agent runtime — run it on your own box or the CPU mesh — and all four custody modes
@circuit-llm/attest Verified Intents — authenticated inputs and the signer-and-vault decision gate
@circuit-llm/bundle The content-addressed, signed bundle format an agent ships and a node verifies
@circuit-llm/vault The non-custodial Agent Vault program, driven from off-chain
@circuit-llm/node The inference-mesh control plane and the public node registry
@circuit-llm/onchain StakePoint staking, on-chain CIRC balances, and the control-plane registry

Read top to bottom, that table is the whole network. And the reason it's worth assembling into one toolkit is composition. A trading agent can use every layer at once: it thinks with @circuit-llm/inference, senses with @circuit-llm/data, acts through @circuit-llm/agent's custody, proves its decisions with @circuit-llm/attest, pays for all of it in CIRC over @circuit-llm/x402, and lives wherever you run it — your own box or the mesh. The packages are separable — take only the inference client and nothing else, or build an agent that never trades and only touches two — but they're designed to stack, because the most interesting things to build on Circuit are the ones that reach across the stack.


What you can build today

The twelve TypeScript packages, the Python client, and the circuit CLI are built in one npm workspace, covered by 191 tests (179 TypeScript + 12 Python) that run straight off the source — Node 22's native type-stripping means there's no transpile step in development — and faithful to the live ecosystem they were extracted from. It's MIT-licensed and versioned 0.2.1, packaged for public release.

Working today: paid inference and data, CIRC wallet operations with RPC failover, and the CircuitAgent runtime — an agent that only thinks and senses or one that trades, run on your own box or handed to the mesh, with custody to match (paper for dev, self-custody with your own key, the off-box signer live on the mesh, and the on-chain vault client). Verified Intents end to end, owner recovery, the bundle codec, and the mesh and registry clients. The non-custodial vault is complete and hardened on-chain and live on devnet, its off-chain client ships in the SDK, and the mainnet deploy and retiring the signer are the steps that remain. The Python side covers the consume layer — inference, data, and x402 — with the standard library and nothing else, for the data-and-ML developers who live in that world. And the CLI is the same capability with a face on it: the whole network from a terminal, on the same packages.

The shape of it is the point. Building on a decentralized network usually means more moving parts than building on a centralized one — more keys, more endpoints, more accounts. The Circuit SDK inverts that. One wallet, no keys, a few typed clients, a custody contract that runs from a paper bot on your laptop to a non-custodial program on-chain without changing your code, a terminal app that runs on the same packages, and the entire network behind a surface small enough to learn in an afternoon. The hard, integrated system underneath is exactly what makes the thing on top so simple.