One OpenRouter key gives you 400+ models across 60+ providers. AgentGuard Spend sits in your runtime and enforces per-task spend caps + capability gates + signed audit receipts on every call. Your CFO assigns which models which teams can use for which tasks. You ship.
OpenRouter consolidates billing across Anthropic, OpenAI, Google, Bedrock, Cohere, Mistral, Meta, DeepSeek, and 50+ others. AgentGuard enforces the policy that decides which to use.
OpenRouter falls back when a provider goes down. AgentGuard records each fallback as a signed decision so you can prove resilience to procurement.
Code reviews go to haiku at $0.10/1M. Payment approvals require gpt-5.5 with a payment-execute capability claim. Read-only research allows any model under $0.20/1M.
Every decision is Ed25519-signed and hash-chained. Auditors verify the entire chain at /verify in their browser.
# Node / TypeScript
npm install @agentguard-run/spend openai
# Python
pip install agentguard-spend openai
export OPENROUTER_API_KEY=sk-or-v1-...
Stored in your env. AgentGuard never reads it.
import OpenAI from 'openai';
import {
withSpendGuard,
setCostOverride,
type SpendPolicy,
} from '@agentguard-run/spend';
import { randomBytes } from 'node:crypto';
import * as ed from '@noble/ed25519';
// Register OpenRouter model pricing (v0.3.0 will sync this automatically
// via `agentguard models --sync-pricing`). Values are cents per 1k tokens.
setCostOverride('anthropic/claude-opus-4-7', { inputCentsPerKtok: 2.0, outputCentsPerKtok: 10.0 });
setCostOverride('anthropic/claude-sonnet-4-6', { inputCentsPerKtok: 0.3, outputCentsPerKtok: 1.5 });
setCostOverride('anthropic/claude-haiku-4-5', { inputCentsPerKtok: 0.1, outputCentsPerKtok: 0.5 });
setCostOverride('openai/gpt-5', { inputCentsPerKtok: 0.5, outputCentsPerKtok: 1.5 });
setCostOverride('openai/gpt-5-mini', { inputCentsPerKtok: 0.05, outputCentsPerKtok: 0.2 });
const policy: SpendPolicy = {
id: 'code-review-team-v1',
name: 'Code review team',
scope: { tenantId: 'acme', teamId: 'engineering' },
caps: [
// Soft daily cap: at $50/day, downgrade to haiku
{ amountCents: 5000, window: 'per_day', action: 'downgrade',
downgradeTo: 'anthropic/claude-haiku-4-5',
reason: 'over $50/day, drop to haiku' },
// Hard daily ceiling: at $200/day, block
{ amountCents: 20000, window: 'per_day', action: 'block',
reason: 'hard daily ceiling' },
// Per-minute burst guard: catches runaway loops
{ amountCents: 500, window: 'per_minute', action: 'block',
reason: 'runaway loop detection' },
],
mode: 'enforce',
version: 1,
effectiveFrom: new Date().toISOString(),
};
// Your signing keys. Generated once, kept in your KMS or local secret store.
const privateKey = new Uint8Array(randomBytes(32));
const publicKey = await ed.getPublicKeyAsync(privateKey);
// Standard OpenAI client pointed at OpenRouter
const client = new OpenAI({
apiKey: process.env.OPENROUTER_API_KEY,
baseURL: 'https://openrouter.ai/api/v1',
});
// Wrap it. That is all.
const guarded = withSpendGuard(client, {
policy,
scope: { tenantId: 'acme', teamId: 'engineering', userId: 'alice' },
config: { signingKeys: { privateKey, publicKey } },
});
// Use any OpenRouter model. AgentGuard enforces locally before the call fires.
const completion = await guarded.chat.completions.create({
model: 'anthropic/claude-opus-4-7',
messages: [{ role: 'user', content: 'Review this PR for security issues...' }],
});
import os
from openai import OpenAI
from agentguard_spend import with_spend_guard, set_cost_override
from agentguard_spend.types import SpendPolicy, SpendCap
set_cost_override('anthropic/claude-opus-4-7', {'inputCentsPerKtok': 2.0, 'outputCentsPerKtok': 10.0})
set_cost_override('anthropic/claude-haiku-4-5', {'inputCentsPerKtok': 0.1, 'outputCentsPerKtok': 0.5})
set_cost_override('openai/gpt-5', {'inputCentsPerKtok': 0.5, 'outputCentsPerKtok': 1.5})
policy = SpendPolicy(
id='code-review-team-v1',
name='Code review team',
scope={'tenantId': 'acme', 'teamId': 'engineering'},
caps=[
SpendCap(amountCents=5000, window='per_day', action='downgrade',
downgradeTo='anthropic/claude-haiku-4-5',
reason='over $50/day, drop to haiku'),
SpendCap(amountCents=20000, window='per_day', action='block',
reason='hard daily ceiling'),
SpendCap(amountCents=500, window='per_minute', action='block',
reason='runaway loop detection'),
],
mode='enforce',
version=1,
effectiveFrom='2026-05-28T00:00:00Z',
)
client = OpenAI(
api_key=os.environ['OPENROUTER_API_KEY'],
base_url='https://openrouter.ai/api/v1',
)
guarded = with_spend_guard(client, policy=policy,
scope={'tenantId': 'acme', 'teamId': 'engineering', 'userId': 'alice'})
completion = guarded.chat.completions.create(
model='anthropic/claude-opus-4-7',
messages=[{'role': 'user', 'content': 'Review this PR for security issues...'}],
)
agentguard serve # opens http://localhost:8787
Local dashboard reads from ~/.agentguard/<scope>/decisions.ndjson. Each decision is a signed receipt. Click any receipt to verify it.
agentguard verify --trace latest
Or share a receipt link to /verify and they can validate it in their browser without installing anything.
| Task | Recommended model | Fallback (downgrade) | Why |
|---|---|---|---|
| Code review | anthropic/claude-haiku-4-5 | none (cheapest already) | Strong reasoning at $0.10/1M |
| Risk analysis | openai/gpt-5 | openai/gpt-5-mini | Best price-perf ratio |
| Payment approval | anthropic/claude-opus-4-7 | none — block on cap | Highest reasoning, no downgrade |
| Chargeback evidence | anthropic/claude-sonnet-4-6 | anthropic/claude-haiku-4-5 | Long context for transcripts |
| Agent support | openai/gpt-5-mini | none | Fast and cheap |
| Repo scan | google/gemini-3.1-pro | openai/gpt-5-mini | Long context window |
When you call OpenRouter, pass an app header so they can attribute usage and show your app in the rankings:
const client = new OpenAI({
apiKey: process.env.OPENROUTER_API_KEY,
baseURL: 'https://openrouter.ai/api/v1',
defaultHeaders: {
'HTTP-Referer': 'https://your-app.example.com',
'X-Title': 'Your App Name',
},
});
agentguard models — interactive TUI to pick from OpenRouter's catalog with live pricingagentguard models --sync-pricing — auto-import all OpenRouter pricing into cost table (no manual setCostOverride calls)agentguard wizard — 90-second guided setup that picks a task template, selects models, sets caps, and writes a working policy + snippet