
Security News
US Government Forces Anthropic to Pull Claude Fable Days After Launch
Anthropic says the directive cited national security concerns over a narrow jailbreak, but offered no specific technical details.
@ottorouter/ai-sdk
Advanced tools
A drop-in SDK for accessing AI models (OpenAI, Anthropic, Google, Moonshot, MiniMax, Z.AI) through the [OttoRouter](https://github.com/slashforge/ottorouter) proxy with automatic x402 payments via Solana USDC.
A drop-in SDK for accessing AI models (OpenAI, Anthropic, Google, Moonshot, MiniMax, Z.AI) through the OttoRouter proxy with automatic x402 payments via Solana USDC.
All you need is a Solana wallet — the SDK handles authentication, payment negotiation, and provider routing automatically.
Normal API requests use bearer auth. The SDK signs a wallet nonce once to exchange for a short-lived OttoRouter token, reuses that token across requests, and refreshes it automatically when needed.
bun add @ottorouter/ai-sdk ai
# or
npm install @ottorouter/ai-sdk ai
import { createOttoRouter } from "@ottorouter/ai-sdk";
import { generateText } from "ai";
const ottorouter = createOttoRouter({
auth: { privateKey: process.env.SOLANA_PRIVATE_KEY! },
});
const { text } = await generateText({
model: ottorouter.model("claude-sonnet-4-20250514"),
prompt: "Hello!",
});
console.log(text);
The SDK auto-resolves which provider to use based on the model name. It returns ai-sdk compatible model instances that work directly with generateText(), streamText(), etc.
Under the hood, the first protected request exchanges wallet auth headers for a bearer token via POST /v1/auth/wallet-token. Subsequent requests reuse Authorization: Bearer <token> until refresh is needed.
Models are resolved to providers by prefix:
| Prefix | Provider | API Format |
|---|---|---|
claude- | Anthropic | Messages |
gpt-, o1, o3, o4, codex- | OpenAI | Responses |
gemini- | Native | |
kimi- | Moonshot | OpenAI Chat |
MiniMax- | MiniMax | Messages |
z1- | Z.AI | OpenAI Chat |
ottorouter.model("claude-sonnet-4-20250514"); // → anthropic
ottorouter.model("gpt-4o"); // → openai
ottorouter.model("gemini-2.5-pro"); // → google
ottorouter.model("kimi-k2"); // → moonshot
Override auto-resolution when needed:
const model = ottorouter.provider("openai").model("gpt-4o");
const model = ottorouter
.provider("anthropic", "anthropic-messages")
.model("claude-sonnet-4-20250514");
const ottorouter = createOttoRouter({
// Required: Solana wallet private key (base58)
auth: { privateKey: "..." },
// Optional: OttoRouter API base URL (default: https://api.ottorouter.org)
baseURL: "https://api.ottorouter.org",
// Optional: Solana RPC URL (default: https://api.mainnet-beta.solana.com)
rpcURL: "https://api.mainnet-beta.solana.com",
// Optional: Payment callbacks
callbacks: {
/* see Payment Callbacks */
},
// Optional: Cache configuration
cache: {
/* see Caching */
},
// Optional: Payment options
payment: {
/* see Payment Options */
},
// Optional: Custom model→provider mappings
modelMap: {
"my-custom-model": "openai",
},
// Optional: Register custom providers
providers: [
{
id: "my-provider",
apiFormat: "openai-chat",
modelPrefix: "myp-",
},
],
});
Monitor and control the payment lifecycle:
Request authentication and payment signing are separate: bearer auth is used for normal OttoRouter HTTP requests, while your wallet still signs the x402 payment transaction during topups.
const ottorouter = createOttoRouter({
auth: { privateKey: "..." },
callbacks: {
// Called when a 402 is received and payment is needed
onPaymentRequired: (amountUsd, currentBalance) => {
console.log(`Payment required: $${amountUsd}`);
},
// Called when the SDK is signing a transaction
onPaymentSigning: () => {
console.log("Signing payment...");
},
// Called after successful payment
onPaymentComplete: ({ amountUsd, newBalance, transactionId }) => {
console.log(`Paid $${amountUsd}, balance: $${newBalance}`);
},
// Called on payment failure
onPaymentError: (error) => {
console.error("Payment failed:", error);
},
// Called after each request with cost info (streaming & non-streaming)
onBalanceUpdate: ({
costUsd,
balanceRemaining,
inputTokens,
outputTokens,
}) => {
console.log(`Cost: $${costUsd}, remaining: $${balanceRemaining}`);
},
// Optional: interactive approval before payment
onPaymentApproval: async ({ amountUsd, currentBalance }) => {
// return 'crypto' to pay, 'fiat' for fiat flow, 'cancel' to abort
return "crypto";
},
},
});
const ottorouter = createOttoRouter({
auth: { privateKey: "..." },
payment: {
// 'auto' (default) — pay automatically
// 'approval' — call onPaymentApproval before each payment
topupApprovalMode: "auto",
// Auto-pay without approval if wallet USDC balance >= threshold
autoPayThresholdUsd: 5.0,
// Max retries for a single API request (default: 3)
maxRequestAttempts: 3,
// Max total payment attempts per wallet (default: 20)
maxPaymentAttempts: 20,
},
});
By default, the SDK automatically injects cache_control: { type: 'ephemeral' } on the first system block and the last message for Anthropic models. This saves ~90% on cached token costs.
// Default: auto caching (1 system + 1 message breakpoint)
createOttoRouter({ auth });
// Disable completely
createOttoRouter({ auth, cache: { anthropicCaching: false } });
// Manual: SDK won't inject cache_control — set it yourself in messages
createOttoRouter({ auth, cache: { anthropicCaching: { strategy: "manual" } } });
// Custom breakpoint count and placement
createOttoRouter({
auth,
cache: {
anthropicCaching: {
systemBreakpoints: 2, // cache first 2 system blocks
systemPlacement: "first", // 'first' | 'last' | 'all'
messageBreakpoints: 3, // cache last 3 messages
messagePlacement: "last", // 'first' | 'last' | 'all'
},
},
});
// Full custom transform
createOttoRouter({
auth,
cache: {
anthropicCaching: {
strategy: "custom",
transform: (body) => {
// modify body however you want
return body;
},
},
},
});
| Option | Default | Description |
|---|---|---|
strategy | 'auto' | 'auto', 'manual', 'custom', or false |
systemBreakpoints | 1 | Number of system blocks to cache |
messageBreakpoints | 1 | Number of messages to cache |
systemPlacement | 'first' | Which system blocks: 'first', 'last', 'all' |
messagePlacement | 'last' | Which messages: 'first', 'last', 'all' |
cacheType | 'ephemeral' | The cache_control.type value |
Provider-agnostic caching at the OttoRouter proxy layer:
createOttoRouter({
auth,
cache: {
promptCacheKey: "my-session-123",
promptCacheRetention: "in_memory", // or '24h'
},
});
cachedContent at the application level// OttoRouter account balance
const balance = await ottorouter.balance();
// { walletAddress, balance, totalSpent, totalTopups, requestCount }
// On-chain USDC balance
const wallet = await ottorouter.walletBalance("mainnet");
// { walletAddress, usdcBalance, network }
// Wallet address
console.log(ottorouter.walletAddress);
Register providers at init or runtime:
// At init
const ottorouter = createOttoRouter({
auth,
providers: [
{ id: "my-provider", apiFormat: "openai-chat", modelPrefix: "myp-" },
],
});
// At runtime
ottorouter.registry.register({
id: "another-provider",
apiFormat: "anthropic-messages",
models: ["specific-model-id"],
});
// Map a specific model to a provider
ottorouter.registry.mapModel("some-model", "openai");
| Format | Description | Used by |
|---|---|---|
openai-responses | OpenAI Responses API | OpenAI |
anthropic-messages | Anthropic Messages API | Anthropic, MiniMax |
openai-chat | OpenAI Chat Completions (compatible) | Moonshot, Z.AI |
google-native | Google GenerativeAI native |
Use the x402-aware fetch wrapper directly:
ottorouter.fetch() uses bearer auth for normal requests and automatically refreshes the OttoRouter access token on 401 once before retrying.
const customFetch = ottorouter.fetch();
const response = await customFetch('https://api.ottorouter.org/v1/messages', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ model: 'claude-sonnet-4-20250514', messages: [...] }),
});
import {
fetchBalance,
fetchWalletUsdcBalance,
getPublicKeyFromPrivate,
addAnthropicCacheControl,
createOttoRouterFetch,
createWalletContext,
} from "@ottorouter/ai-sdk";
// Get wallet address from private key
const address = getPublicKeyFromPrivate(privateKey);
// Fetch balance without creating a full OttoRouter instance
const balance = await fetchBalance({ privateKey });
// Fetch on-chain USDC
const usdc = await fetchWalletUsdcBalance({ privateKey }, "mainnet");
// Create a standalone x402-aware fetch
const ottorouterFetch = createOttoRouterFetch({
wallet: createWalletContext({ privateKey }),
baseURL: "https://api.ottorouter.org",
});
createWalletContext() remains available for advanced usage. Its wallet headers are now intended for token exchange only; regular API traffic should go through createOttoRouter(), ottorouter.fetch(), createOttoRouterFetch(), or fetchBalance() so bearer auth refresh is handled automatically.
ottorouter.model('claude-sonnet-4-20250514') — the SDK resolves this to Anthropic@ai-sdk/anthropic) pointed at the OttoRouter proxyAuthorization: Bearer <token> into normal API requests401 by refreshing the bearer token once and retrying/v1/topup HTTP request itself uses bearer authai SDK v6+ as a peer dependencyMIT
FAQs
A drop-in SDK for accessing AI models (OpenAI, Anthropic, Google, Moonshot, MiniMax, Z.AI) through the [OttoRouter](https://github.com/slashforge/ottorouter) proxy with automatic x402 payments via Solana USDC.
We found that @ottorouter/ai-sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Anthropic says the directive cited national security concerns over a narrow jailbreak, but offered no specific technical details.

Security News
A network of 152 Chrome live wallpaper extensions hid ad tracking and made extension-driven traffic look like Google search clicks.

Company News
Socket’s first CISO brings deep experience securing high-growth SaaS companies as open source supply chain threats accelerate.