Enforce, don't just observe.

Your agents. Your machines.
Your rules.

Route to your own hardware — or approved cloud when you choose. Keep sensitive routes off unapproved providers; redact known credentials before dispatch. Refuse anything over budget. Kill loops in seconds. One ~5.5 MB Rust binary that decides before the money is spent, with an embedded control room at /ui so you can watch enforcement happen in real time.

Works with any OpenAI-compatible agent — point base_url at localhost:8787/v1.
Claude Code connects via ANTHROPIC_BASE_URL. Pre-release · MIT · dogfooded daily.

stoke :8787 — illustrative
route it fail over cap it kill it

Runaway agents turn retries and fan-out into spend.

Local nodes can be stranded, cold, or overloaded while a runaway agent turns retries and fan-out into spend. Stoke puts the circuit breaker before the provider call: it rejects loops, clamps fan-out, holds concurrent stream reservations, and only escalates to paid inference when your policy allows it.

Kill runaway loops

Loop detection and rate limits refuse repeated traffic before another provider call is made.

Clamp fan-out

Pre-dispatch ceilings limit how many billed provider calls one request may create.

Hold streamed spend

Concurrent streams reserve their possible cost before dispatch, so a burst cannot overshoot the key's cap.

Route by fit

Use model support, warm state, health, load, and policy to choose a route across your configured capacity.

Watch enforcement happen.

An embedded panel for your running Stoke gateway: decisions, budget state, routing, and node status in one view.

Illustrative preview. This button simulates panel events in your browser. It does not send traffic to a gateway.

Ready — no network request
STOKE / CONTROL ROOM● local preview
tracked
configured
live SSE
Decision feed
ALLOWEDlocal Ollama node · warm route selected
FALLBACKlocal node unavailable · next configured node
CLOUD ROUTEpolicy permits paid-provider escalation
BLOCKEDbudget cap reached · no upstream call
HOLDreservation held for concurrent stream · cap not overshot

Run the failure proof, not a simulation.

The repository smoke test exercises the pricing gate, PII redaction, loop refusal, streamed spend, in-flight holds, fan-out clamp, cache isolation, and fail-closed boot validation against local mock providers.

./scripts/smoke_spend.sh # ... SPEND FIREWALL SMOKE PASSED (pricing gate, streamed spend, in-flight holds, served-model billing, boot validation, fan-out clamp, full billing, cache isolation)
Read the runnable proof →

One endpoint for the capacity you configure.

Clients in front

Point OpenAI-compatible clients or Claude Code at Stoke. Production integrations stay in place.

Capacity behind it

Stoke discovers model inventory and health through /v1/nodes, then routes across configured Ollama nodes and gateways without manual topology selection.

1

GET /v1/nodes

Poll each configured Ollama or federated Stoke node for discovered models, warm state, health, and load.

2

Rank eligible capacity

Stoke filters by route policy, then prefers a healthy warm node with the lowest live load—without asking the client to map topology.

3

Return an inspectable decision

The response and logs identify the selected node and model; GET /v1/nodes remains the operator's live inventory view.

Two machines, one endpoint

Keep Ollama private on each machine. Add the second Stoke gateway as an authenticated remote provider; both machines then sit behind the same client URL.

# on the gateway receiving client traffic [[providers]] name = "studio" type = "stoke" base_url = "http://192.168.1.33:8787/v1" api_key_env = "STUDIO_STOKE_KEY" tier = "remote"

OPENAI_BASE_URL=http://localhost:8787/v1 stays unchanged for the client; Stoke discovers the remote inventory and chooses the eligible node.

One binary. Your infrastructure.

Open source, MIT licensed, and local by default. No hosted control plane or account required.

Read the docs →
# rolling prebuilt binary curl -sSf https://stokegate.com/install | sh -s -- --version nightly OPENAI_BASE_URL=http://localhost:8787/v1 ANTHROPIC_BASE_URL=http://localhost:8787

Short answers.

Is Stoke a hosted service?

No. Stoke is a self-hosted Rust gateway that runs on infrastructure you control.

Does it work with my existing OpenAI or Anthropic client?

Yes. Stoke accepts OpenAI-compatible clients and the Anthropic Messages API. Point the client at Stoke, then configure the upstream provider or local node.

Can I use local models across multiple machines?

Yes. Connect and configure the nodes or gateways, then Stoke can route across their discovered model and health state.

Is the panel demo above connected to a real gateway?

No. It is a browser-only preview of the panel's event shape. A running gateway exposes the real authenticated panel at GET /ui and the repeat-request demo at POST /ui/demo.

Where are the detailed configuration and routing docs?

Start with the guides, then read the README and architecture notes.

Refuse cloud fallback before a provider is called.

A route can be pinned to the tiers you approve. When no approved provider is available, Stoke fails closed with 403 rather than silently escalating to unapproved cloud capacity.

Per-route allowlist

Set allowed_tiers = ["local", "remote"] on a route and cloud fallback is denied before any provider is contacted.

Fail closed

Unknown tier names are rejected at boot; a route with no eligible approved provider returns 403, never an open gateway.

Credential hygiene

Known credentials are redacted before a request is dispatched to a provider.

# route policy allowed_tiers = ["local", "remote"] # no eligible approved provider HTTP 403 Forbidden Route policy forbids every provider for this model # built-in prompt redaction [builtins.pii_redact] replacement = "[REDACTED]" # inspectable route receipt "stoke_route": { "node": "studio", "auto": { "chosen": { "model": "your-35b-coder", "warm": true }, "counterfactual_usd_est": 0.0214 }}

Put your local capacity to work.

Align configured machines behind one policy gateway, then decide what reaches a paid provider.