Skip to main content
The llm primitive is a full wrapper over OpenRouter. It gives your agent a single, OpenAI-compatible chat-completions endpoint that routes to 300+ models across Anthropic, OpenAI, Google, Meta, Mistral, and more — with provider routing, fallbacks, and streaming. You don’t manage an OpenRouter account or key: Naive holds the key and bills each call in Naive credits based on the exact cost OpenRouter returns. There are two ways to use it:
  1. The typed primitivenaive.llm.chat() / naive.llm.stream() / naive.llm.models() in the SDK (plus CLI, MCP, and the agent toolset).
  2. The drop-in proxy — point any OpenAI or OpenRouter client’s baseURL at Naive and keep your existing code.

CLI First

Endpoints

EndpointTypeDescriptionCost
POST /v1/llm/chat/completionsSync or streamingOpenAI/OpenRouter-compatible chat completionPer-token (see Credits)
GET /v1/llm/modelsSyncList routable models (optionally filtered)Free
GET /v1/llm/generation?id=SyncUsage/cost stats for a prior completionFree
The request and response bodies are exactly OpenRouter’s (which are in turn OpenAI-compatible) — Naive forwards them through. See OpenRouter’s API reference for the full schema.

Chat completions

Response (OpenAI-shaped, plus credits_used):

Key parameters

ParamTypeDescription
modelstringModel id with provider prefix, e.g. anthropic/claude-sonnet-4.6, openai/gpt-5.2.
messagesarrayOpenAI-style chat messages. (Either messages or prompt is required.)
modelsstring[]Optional fallback chain — OpenRouter tries them in order if earlier ones are unavailable.
providerobjectOpenRouter provider routing preferences (order, only, ignore, sort, allow_fallbacks, data_collection, …).
streambooleanStream the response as SSE.
temperature, top_p, max_tokens, tools, response_format, …Forwarded as-is to OpenRouter.

Provider routing & fallbacks

Because the body is OpenRouter’s, you get its routing controls for free:

Streaming

Streaming is Server-Sent Events. The final chunk carries the usage object (including cost); Naive bills it after the stream closes.

Use Naive instead of OpenRouter (drop-in proxy)

If you already use the OpenAI or OpenRouter SDK, you don’t need to change your code — just change the baseURL and key. Naive injects the OpenRouter key server-side and bills your credits.
The proxy is a transparent passthrough: every path under /v1/proxy/openrouter/* maps to https://openrouter.ai/api/v1/* (so chat/completions, models, generation, etc. all work). It is authenticated by your Naive api key and is not Account-Kit gated — use the typed /v1/llm routes when you want per-tenant AccountKit enforcement.

Multi-tenant

Like other primitives, the typed routes are AccountKit-gated and per-user:
Toggle the llm primitive on/off per Account Kit in the dashboard (Account Kits → Primitives → Generation), or via primitives_config.llm.enabled. See Account Kits.

Billing

Naive bills the exact cost OpenRouter reports for each request (usage.cost, in USD) times a small markup, converted to credits ($0.05 = 1 credit). There’s no per-model rate table to keep in sync — token-heavy models simply cost more. Costs are charged after the response completes (after the final chunk, for streams). Listing models is free. See Credits.

Agent tools

The llm primitive is part of agentTools(): the model can route its own sub-calls with naive_run_primitive(primitive: "llm", method: "chat", arguments: { model, messages }), or list models with method: "models".

Error Handling

ErrorCauseRecovery
insufficient_creditsNot enough creditsTop up — see Credits
not_configuredOpenRouter key not set on the deploymentAgentProfile must set OPENROUTER_API_KEY
provider_errorOpenRouter/upstream model errorInspect the message; retry or try another model
invalid_inputMissing messages/promptProvide one
forbiddenllm disabled by the Account KitEnable it in the kit