Agents don’t hold credit cards.
They hold VAGA — and settle
for exactly what they use.
VAGA Router gives VagaChain agents an OpenAI-compatible inference endpoint. Every request reserves a maximum VAGA bound on-chain, forwards to EUrouter, reconciles the provider’s actual EUR cost, settles actual + markup — and releases the unused reservation back to the agent.
curl http://127.0.0.1:8787/v1/chat/completions \ -H "Authorization: Bearer vcomp_..." \ -H "Content-Type: application/json" \ -H "Idempotency-Key: demo-0001" \ -d '{ "model": "openai/gpt-4o-mini", "messages": [{ "role": "user", "content": "Explain escrow in one line." }], "max_completion_tokens": 64 }'
The bearer token authenticates only. Payment happens on VagaChain: the router reserves first, settles the real cost after inference, and is safe to retry with the same Idempotency-Key.
Seven steps between a prompt and a settled receipt.
Every inference is a durable operation with persisted state transitions — reserved before the provider call, reconciled against real usage, settled or released on-chain.
- 01
Credential
The agent authenticates with a bearer credential (vcomp_…), issued by a controller-signed Ed25519 request and revocable at any time. The token authenticates only — payment never touches it.
- 02
Quote
Before any VAGA moves, the router performs an authenticated live lookup of the exact EUrouter model record. It must expose EUR prompt/completion pricing and support the requested endpoint and capabilities.
- 03
Reserve
A conservative upper bound — UTF-8 input bytes ×2 + 64 tokens plus the requested output limit — is converted to VAGA base units with one upward rounding and reserved on VagaChain with a block TTL.
- 04
Infer
Exactly one forward to EUrouter. Streaming is passed through as raw SSE. Once the provider window opens, the request is never retried — ambiguity is marked, not guessed.
- 05
Reconcile
The provider's actual EUR cost is extracted from the generation or response usage. An unverifiable cost releases the full reservation — the agent is never charged for uncertainty.
- 06
Settle
On-chain settlement of actual cost + configured markup, derived from deterministic quote, settlement, review, and run hashes. Reserve, settle, and release are idempotent and durable across restarts.
- 07
Release
The unused remainder of the reservation returns to the agent's escrow — back to zero — and the OpenAI-compatible response is returned with an x-vaga-compute-operation-id reference.
Exact money, to the 12th decimal.
VAGA settles in integer base units — 10¹² per token. The router reserves the worst case, then charges one final, upward-rounded conversion of the provider's actual EUR cost.
Micro-charges survive the rounding: even 10⁻²⁰ EUR converts to at least one base unit — every settlement is an exact integer amount on VagaChain, never a float.
Mirrors the backend conversion ceil(cost · (1+markup) · 10¹² ÷ eur_per_vaga). The reservation uses the output limit; after inference the router settles EUrouter’s returned actual cost and releases the remainder. Rate, markup, and prices here are illustrative (.env.example defaults); the real request bound also uses canonical-JSON input bytes ×2 + 64 tokens.
Models come from /v1/models — nothing else.
The catalog is the authenticated, live EUrouter listing filtered by the router to models with verifiable EUR pricing and bounded text inference. No hardcoded model lists, no cached catalogs.
Issue a vcomp_ credential — signed outside the browser.
Credentials are issued from a controller-signed Ed25519 request against the agent's registered controller key. This frontend never accepts private key material: you sign with your agent CLI or the documented node one-liner, and the signature is verified locally against the public key before anything is sent.
This frontend never accepts seeds or private keys. The signature is checked locally against your public controller key, then verified server-side by the backend.
Fill in agent id and controller key…
Sign externally · node one-liner (localhost tooling)
…
what the backend checks
- · the controller key is registered on the VagaChain agent
- · the Ed25519 signature over the canonical message verifies
- · the nonce is canonical and the issue hash was never used before (replay protection)
- · expiry is a millisecond UTC ISO timestamp within the configured max lifetime
Speak OpenAI. Settle on VagaChain.
Three OpenAI-compatible endpoints, two signed credential endpoints, one health probe. Everything below mirrors the running backend contract — including what happens when things go wrong.
- GET/v1/models
Authenticated live model catalog (EUrouter-shaped, filtered to safe models).
- POST/v1/chat/completions
OpenAI-compatible chat. Requires Idempotency-Key (recommended).
- POST/v1/responses
OpenAI Responses API shape. Same billing pipeline.
- GET/v1/operations/:id
Settlement & receipt status for the caller's own operations — foreign or unknown ids are a non-enumerable 404.
- POST/v1/credentials
Controller-signed issue. Returns the raw vcomp_ token exactly once.
- POST/v1/credentials/:id/revoke
Controller-signed revocation. Immediate 401s afterwards.
- GET/healthz
Unauthenticated process health check.
- Authorization
- Bearer vcomp_… — authentication only; payment is on-chain VAGA.
- Idempotency-Key
- Recommended. Same key + same body replays the settled response; different body with same key → 409.
- x-vaga-compute-operation-id
- Returned on every inference response — the durable operation reference (op_…).
- Retry-After
- Present on retryable 503s; retry with the identical Idempotency-Key.
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.VAGA_ROUTER_TOKEN, // vcomp_… (auth only)
baseURL: "https://api.vagarouter.dnsstack.pro/v1"
});
const completion = await client.chat.completions.create(
{
model: "openai/gpt-4o-mini",
messages: [{ role: "user", content: "ping" }],
max_completion_tokens: 64
},
{ headers: { "Idempotency-Key": "agent-run-42" } }
);Point any OpenAI SDK at the router base URL and pay with VAGA. The local backend listens on http://127.0.0.1:8787/v1; the public gateway is served via Cloudflare in front of the same process.
{
"id": "resp-…",
"model": "openai/gpt-4o-mini",
"choices": [{
"message": { "role": "assistant", "content": "Escrow = " … },
"finish_reason": "stop"
}],
"usage": { "prompt_tokens": 21, "completion_tokens": 14 }
}| HTTP | Code | Meaning | Retry |
|---|---|---|---|
| 401 | invalid_bearer_token / credential_expired_or_revoked | Credential missing, unknown, expired, or revoked. | no |
| 402 | insufficient_balance | Agent liquid VAGA is below the reservation bound. | no |
| 400 | model_not_found / model_capability_unsupported | Live catalog rejected the model or its pricing. | no |
| 400 | unsupported_request / unsupported_input_modality | Bounded-inference rules: text only, n=1, no unbounded features. | no |
| 409 | Idempotency-Key conflict | Same key used with a different request body. | no |
| 409 | provider_call_ambiguous | Provider outcome unknown — never blindly retried. | no |
| 503 | reservation_pending / settlement_pending | Durable operation in progress. | yes · same key |
| 502 | provider_request_failed | No billable result; reservation fully released. | new request |
Streaming requests are raw SSE passthrough: after the provider window opens, nothing is retried. Interrupted provider calls become recovery_required — visible as 409 with the operation id, reconciled by the backend, never duplicated.
Run a real request. Watch it settle.
This talks to the live VAGA Router backend: real reservation, real EUrouter inference, real settlement. Every run carries an Idempotency-Key and returns its durable operation id.
reserve → infer → settle → release
connect a credential and run
The frontend holds no private keys and no provider secrets. Your controller seed signs in memory and is gone when the tab closes.
The vcomp_ credential is sent only as an Authorization header. It never touches analytics, logs, or third parties — payment runs over VagaChain.
The VagaChain RPC and the backend database stay on loopback. The public gateway fronts the router process only — never the chain node.
Every request yields a durable operation id and a hash-only inference receipt commitment — evidence without exposing payload content.