OrreryDocsBack to the networkInstall
Docs · Overview

Orrery docs. Run a router, or run a node.

Orrery is a peer-to-peer AI inference network. A router on your computer sends each request straight to a provider's machine and pays it through a Solana payment channel. Nothing sits in between, and the program takes no fee.

no server in the middledepositredeemYour computerRouter127.0.0.1:7171Kestrel GPU Co-opeu-north · from $0.08/MIronbridge Computeus-east · from $0.20/MVault Nineeu-west · from $0.15/MSolana program · channels · 0% fee
Requests and answers go straight between your router and the provider's machine. The program only holds each channel's deposit: a provider redeems what you signed, the rest comes back to you.

01Quickstart

  1. Install the router from npm: npm install -g orrery-node (Node 22 or newer).
  2. Fund a Solana wallet with a few USDC and a little SOL.
  3. Run orrery router --wallet <keypair.json> --rpc <your RPC>.
  4. Point any OpenAI-compatible tool at http://127.0.0.1:7171/v1 with any API key, and add :cheap, :fast, :trusted or :private to the model name when you care.

That is the whole setup. There is no account, no sign-up and no API key to buy: your wallet is the account, and each answer is paid to the machine that served it.

02Install

The router and the provider node are one npm package, orrery-node, which installs a single command, orrery. It needs Node.js 22 or newer and runs on macOS, Linux and Windows (WSL).

bash
node --version          # v22 or newer
npm install -g orrery-node
orrery help

Or run it once without installing:

bash
npx -y orrery-node router --wallet ~/.config/solana/id.json

Everything the router keeps lives in ~/.orrery (set ORRERY_HOME to move it): the session key that signs your running totals and the list of your open channels. Updating is npm install -g orrery-node@latest; uninstalling is npm uninstall -g orrery-node after you close your channels.

03Fund a wallet

The router pays from an ordinary Solana wallet file (the JSON keypair the Solana CLI writes). Use a dedicated wallet with only what you plan to spend.

bash
solana-keygen new -o ~/.config/solana/orrery.json   # or use a wallet file you already have
solana address -k ~/.config/solana/orrery.json      # send USDC and a little SOL here
NeedsHow muchWhy
USDC$2 per provider you useeach new channel locks a deposit (--deposit, default 2). What you do not spend comes back when the channel closes.
SOLabout 0.05transaction fees, and the rent for each channel's accounts, which is returned when the channel closes
RPCone URLthe router reads the provider list with a filtered getProgramAccounts call; most paid RPCs allow it, the public endpoint is rate limited

Settlement is in mainnet USDC (EPjF…m3CY). Only this wallet signs to open, top up or close a channel; every answer in between is signed by a session key on your computer.

04Run the router

bash
orrery router \
  --wallet ~/.config/solana/orrery.json \
  --rpc https://your-rpc.example.com \
  --daily-cap 5
output
Orrery router on http://127.0.0.1:7171/v1  ·  3 providers  ·  route auto  ·  wallet 7xKXtg…
session key 9WzDXw…AWWM signs vouchers; console at http://127.0.0.1:7171/

The router listens on 127.0.0.1 only, so nothing outside your computer can reach it. Its console at http://127.0.0.1:7171/ shows every request, the provider that answered, the tokens and what it cost, plus your providers and channels.

FlagDefaultWhat it does
--walletnonewallet file that opens and tops up channels. Without it the router is read-only. Env ORRERY_WALLET.
--rpcpublic mainnetSolana RPC URL. Env ORRERY_RPC_URL.
--routeautodefault route: auto, price, speed, reputation, privacy
--deposit2USDC locked when a channel opens
--top-up-below0.25add to a channel when what is left falls under this
--daily-cap5stop spending for the day after this many USDC
--min-reputation0.2the auto route ignores providers below this score (0 to 1)
--port7171local port
--refresh60seconds between re-reading the provider list from the chain
--enclave-imagesnonecomma-separated enclave measurements you trust for :private

05Connect your tools

The router speaks the OpenAI Chat Completions API (/v1/chat/completions, streaming or not, and /v1/models). Anything that lets you set a base URL works unchanged. The API key can be any string.

ToolWhere to set it
CursorSettings → Models → OpenAI API key: any string, Override OpenAI Base URL: http://127.0.0.1:7171/v1, then add a model such as llama-3.3-70b:cheap
Continuea model with provider: openai, apiBase: http://127.0.0.1:7171/v1, model: deepseek-v3
AiderOPENAI_API_BASE=http://127.0.0.1:7171/v1 aider --model openai/llama-3.3-70b:cheap
Open WebUIAdmin → Connections → OpenAI API: URL http://127.0.0.1:7171/v1, any key
LangChainChatOpenAI(base_url="http://127.0.0.1:7171/v1", api_key="unused", model="qwen3-235b")
python
from openai import OpenAI

client = OpenAI(base_url="http://127.0.0.1:7171/v1", api_key="unused")
reply = client.chat.completions.create(
    model="llama-3.3-70b:cheap",
    messages=[{"role": "user", "content": "Hello from the network"}],
)
print(reply.choices[0].message.content)
typescript
import OpenAI from 'openai';

const client = new OpenAI({ baseURL: 'http://127.0.0.1:7171/v1', apiKey: 'unused' });
const stream = await client.chat.completions.create({
  model: 'deepseek-v3:fast',
  stream: true,
  messages: [{ role: 'user', content: 'Explain payment channels in two lines' }],
});
for await (const chunk of stream) process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
curl
curl http://127.0.0.1:7171/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{"model":"gpt-oss-120b:cheap","messages":[{"role":"user","content":"hi"}]}' -i

Every answer carries three headers so you can see who served it and what you paid:

response headers
x-orrery-provider: 5Tq7…   (the provider's on-chain listing)
x-orrery-route: price
x-orrery-cost: 0.000009     (USDC, signed into your channel)

The Anthropic Messages API (/v1/messages) is not served yet. Tools that only speak it cannot use the router today.

06Models and routes

Model names are the ones providers list. orrery models prints every model on the network with its cheapest price and how many providers serve it; orrery providers prints every listing with what the chain says about it.

bash
$ orrery models
llama-3.3-70b                              2 providers  from $0.12/M in · $0.30/M out
deepseek-v3                                1 providers  from $0.27/M in · $1.10/M out
gpt-oss-120b                               1 providers  from $0.030/M in · $0.11/M out

Add one word after the model name, or send the header x-orrery-route:

SuffixRoutePicks
(none)autoa blend of expected cost, first-token time and reputation, among providers above your reputation floor
:cheappricelowest expected cost for this request
:fastspeedfastest first token this router has measured
:trustedreputationhighest reputation: USDC settled on chain, number of redemptions, age, bonded $OREY, and this router's own success rate
:privateprivacyonly providers whose enclave this router verified; the request is sealed

The router tries the top three providers in order, so a slow or failing one is skipped without your tool noticing. Pin one provider with the header x-orrery-provider: <first characters of its address>.

07How you pay

The first request to a provider opens a payment channel: your wallet moves a deposit into an account only the channel controls. From then on the session key on your computer signs a running total after every answer, an 88-byte voucher: orrery/voucher/1, the channel, the total, and a hash chain over every answer's usage.

  • The router prices every answer itself from the provider's published price list and pays the smaller of its number and the provider's.
  • A provider serves the next request only once the previous one is paid, so it is never owed more than one answer, and you never pay for an answer you did not get.
  • The provider redeems the highest total whenever it likes. The program pays the difference to the provider's own token account and nowhere else.
  • When what is left in a channel falls under --top-up-below, the router asks your wallet to add another deposit. --daily-cap stops all spending for the day.

08Your channels

Closing takes two steps so a provider cannot be cheated out of its last answer: you start the close, the provider gets a grace period (one hour) to redeem what you signed, then everything left comes back to you. A provider can also release a channel at any time, which returns the rest at once.

bash
$ orrery channels
5HURjz…  provider CakCxW…  deposit $2.00  you signed $0.000136  redeemed $0.000136  open

$ orrery close 5HURjz… --wallet ~/.config/solana/orrery.json
closing 5HURjz…; the provider has 3600s to redeem, then run: orrery close 5HURjz… --wallet … --finish

$ orrery close 5HURjz… --wallet ~/.config/solana/orrery.json --finish
closed 5HURjz…; $1.999864 and the account rent are back in your wallet

09Run a provider

Put a provider node in front of any OpenAI-compatible server: vLLM, SGLang, Ollama, llama.cpp, or API capacity you hold. Routers anywhere can then pay you per answer. There is no application, no stake to post and nobody who can delist you.

  1. Serve a model locally with an OpenAI-compatible server, or have an API key.
  2. Make it reachable at a public HTTPS URL (a reverse proxy, a tunnel, or a host with a public IP). Routers call /v1/manifest, /v1/chat/completions and /orrery/voucher on it.
  3. Write provider.json with your prices (next section).
  4. Register with your wallet, then start the node.
bash
orrery provider register --config provider.json --wallet ~/.config/solana/provider-wallet.json
orrery provider show     --config provider.json      # what the chain now says, including your node key
orrery provider start    --config provider.json

Registering lists you on chain with your endpoint and the sha-256 of your price list; routers ignore a price list that does not match it. Your wallet stays cold: the node runs on its own key (created at ~/.orrery/provider/node.json), which can redeem and post enclave claims but never touches what you have earned. Send the node key about 0.01 SOL for redemption fees. Redemptions go straight to your wallet's USDC account. To change prices or the URL, edit the file and run register again; it updates the listing.

upstreams
vLLM        "baseUrl": "http://127.0.0.1:8000/v1"
SGLang      "baseUrl": "http://127.0.0.1:30000/v1"
Ollama      "baseUrl": "http://127.0.0.1:11434/v1"
llama.cpp   "baseUrl": "http://127.0.0.1:8080/v1"
OpenRouter  "baseUrl": "https://openrouter.ai/api/v1", "apiKeyEnv": "OPENROUTER_API_KEY"

Keep it running with any process manager. A systemd unit:

/etc/systemd/system/orrery-provider.service
[Unit]
Description=Orrery provider node
After=network-online.target

[Service]
ExecStart=/usr/bin/env orrery provider start --config /etc/orrery/provider.json
Environment=OPENROUTER_API_KEY=...
Restart=always
User=orrery

[Install]
WantedBy=multi-user.target

Only standard chat fields (messages, sampling settings, tools, response format) reach your upstream. Fields that would let a caller spend your key on something your price list does not cover, such as fallback model lists, plugins or provider routing, are dropped, and so is n.

10provider.json

provider.json
{
  "name": "My GPU",
  "region": "eu-west",
  "listen": 7272,
  "publicUrl": "https://gpu.example.org",
  "rpcUrl": "https://your-rpc.example.com",
  "settleMint": "EPjFWJd5Wm8eUi4wSPdf8qJxQAXnmSeKEr5mVGYLm3CY",
  "wallet": "~/.config/solana/provider-wallet.json",
  "upstream": { "baseUrl": "http://127.0.0.1:8000/v1" },
  "models": [
    { "id": "llama-3.3-70b", "upstreamModel": "meta-llama/Llama-3.3-70B-Instruct",
      "context": 131072, "maxOutput": 8192,
      "price": { "input": 120000, "output": 300000 } }
  ],
  "redeem": { "everySecs": 300, "minUnits": 50000 }
}
FieldMeaning
name, regionshown to routers and in orrery providers
listen, hostlocal port (default 7272, or PORT) and bind address (default 0.0.0.0)
publicUrlthe HTTPS address routers use, up to 120 characters, written on chain
rpcUrl, settleMintSolana RPC and the settlement mint (mainnet USDC)
wallet or authoritythe wallet that owns the listing and receives redemptions (a file, or just its address)
nodeKey or nodeKeyEnvthe node's own key: a file path, or an environment variable holding the JSON key
dataDirwhere the node keeps vouchers until it redeems them; keep it on a disk that survives restarts
upstream.baseUrlyour OpenAI-compatible server
upstream.apiKey / apiKeyEnvthe upstream key, inline or (better) from an environment variable
upstream.headers, upstream.bodyextra headers, and fixed fields you add to every upstream call yourself
models[].idthe name routers ask for
models[].upstreamModelthe name your upstream knows it by, if different
models[].priceUSDC base units per million tokens: 120000 is $0.12
models[].maxOutput, contextcaps per request; the router reserves at most maxOutput tokens of payment
redeem.everySecs, minUnitshow often to cash vouchers, and the smallest amount worth a transaction

11The private route

A provider running inside a hardware enclave (Intel TDX, AMD SEV-SNP, or TDX with NVIDIA confidential computing) posts a claim on chain: the enclave type, the measured image, the hash of its attestation report, and the key prompts are encrypted to. Claims expire within 30 days.

Before sealing anything, the router fetches the report and checks that it hashes to the on-chain claim, names the same key, has not expired, and booted an image on your allow list (--enclave-images). Checking the hardware vendor's signature needs an external verifier; without one the router does not treat an enclave as verified. Development reports are labeled and refused unless you pass --allow-dev-enclaves.

12$OREY

The token launches on Meteora. In the program it has one role: providers can bond it behind their listing, and routers count the bond as 10% of reputation. A bond is never slashed; unbonding returns it after seven days, only to the provider that posted it.

13The program

Program 7UHevY47LgbJv9hz4iymecR8FURy27jX55KYb1sxytZS on Solana.

  • Anyone can list a provider. Nobody, including the admin, can delist one.
  • Money in a channel goes only to its provider, with your signed voucher, or back to you.
  • There is no fee field and no third recipient.
  • The admin can tune the close grace period (10 minutes to 7 days), the unbonding delay (1 hour to 30 days) and the minimum deposit, and set the bond mint once.

14What can go wrong

IfThe most you lose
a provider stops answeringnothing: the router moves to the next provider, and it signs only after an answer has arrived
a provider overstates its token countsat most what the router reserved for that one answer (the listed price for maxOutput tokens); it pays the smaller of its own calculation and the provider's, never more than the reservation
your session key leakswhat is left in your open channels, which only their providers can redeem; close them
your router misbehavesat most --daily-cap per day
a provider's node key leaksnothing of the provider's: redemptions only ever go to the listing wallet

15Troubleshooting

You seeDo this
No models listed yet. or 0 providersyour RPC refuses getProgramAccounts; pass an RPC that allows it with --rpc
no wallet configuredstart the router with --wallet <keypair.json>
no provider on the network serves …check the name with orrery models
daily spending cap reachedraise --daily-cap or wait for tomorrow (UTC)
all providers failedsee orrery providers; try another route or model
a channel will not openthe wallet needs USDC for the deposit and a little SOL for fees
SyntaxError or Unsupported engineupgrade to Node.js 22 or newer
port 7171 in use--port 7172 and use that base URL

16Status

  • Built and tested: the program (13 tests), the router and provider node (13 tests), and a full local rehearsal of the program, three providers and a router (14 of 14 checks).
  • Package: orrery-node on npm. Source: github.com/orrery-node/orrery (MIT).
  • Not yet: the Anthropic Messages API, a built-in hardware attestation verifier.