- Use
@squasher-ai/agentin your app or agent runtime - Send Langfuse-style batch events to Squasher’s AI ingest endpoint
Option 1: Agent SDK + OpenRouter
This is the best path when you want session tracking, tool calls, and agent spans in addition to plain generations.- the generation itself
- prompt, completion, total, reasoning, and cached input tokens (from the AI SDK’s
usage.outputTokenDetails/inputTokenDetails) - the model and provider (with the AI SDK’s
.chat/.responsessuffix stripped) - assistant text output (
text) and, only withcaptureReasoning: true, provider-supplied reasoning text (reasoningText) - cost in USD, captured automatically when OpenRouter returns it on
providerMetadata.openrouter.usage.cost(use@openrouter/ai-sdk-provideror passproviderOptions: { openrouter: { usage: { include: true } } }to enable cost in the response). When the provider doesn’t report cost, Squasher computes it server-side from your token counts × the public model rate table — no extra config required. - tool calls and their input/output (sanitized to JSON-safe values, or omitted in
privacyMode) - the enclosing session / run
Option 2: Direct HTTP ingest (no SDK)
If you don’t want to install an SDK, POST batch events directly. The endpoint is Langfuse-compatible: trace, generation, span, agent, tool, and event types are all accepted in the same batch and arrive on the AI -> Sessions / Requests views the same way an SDK call would.type values:
Field reference for
generation-create:
id,traceId,parentObservationIdname,model,provider,modelParametersstartTime,endTime,completionStartTime(ISO 8601)input,output— any JSON. Put your assistant text underoutput.textand reasoning text underoutput.reasoningto surface them in the dashboard.usageDetails— Langfuse-style map. Squasher readsinput/prompt_tokens/input_tokens,output/completion_tokens/output_tokens,total, plusoutput_reasoning_tokens,input_cached_tokens,input_cache_read,input_cache_write,accepted_prediction_tokens,rejected_prediction_tokens.usage— legacy alias supportingpromptTokens,completionTokens,totalTokens,totalCost.costDetails— map withinput,output,cache_read_input_tokens,total. If you only have a single number, send{ "total": 0.00123 }.level(DEFAULT/WARNING/ERROR),statusMessage,version,environment,metadatapromptName,promptVersionfor prompt-management linking
OpenRouter-specific tips
- Set
providerexplicitly toopenrouterwhen you emit custom events. - Pass the fully qualified model string (for example
openai/gpt-4.1-nanooranthropic/claude-3.5-sonnet). - For automatic cost capture through the SDK, either use
@openrouter/ai-sdk-provider(which surfaces cost onproviderMetadata.openrouter.usage.cost) or passproviderOptions: { openrouter: { usage: { include: true } } }tostreamText/generateText. - For raw HTTP ingest, send
costDetails.total(USD) when you have it.
Cost without doing anything
You don’t have to attach cost yourself. If a generation arrives with token counts but nocostDetails / cost_usd / gen_ai.response.cost, Squasher computes the cost server-side from a maintained per-model rate table — the same approach Langfuse and Helicone take. Provider-reported cost always wins over the computed estimate, so if you start sending OpenRouter’s usage.cost later, the dashboard switches to the exact number with no other changes on your side.
The rates come from models.dev, the open-source community-maintained AI model database. It covers ~3,700 models across the major frontier providers (OpenAI, Anthropic, Google, x-ai, DeepSeek, Meta-Llama, Mistral, Cohere, Groq, Fireworks, Together, OpenRouter pass-throughs, and ~100 others) with cached-input rates where the provider supports prompt caching.
Squasher refreshes model rates regularly. Models that are not in the table show cost 0 until the next refresh; if a model you depend on is missing or mispriced, open a PR on the models.dev repo and the rate flows through automatically.
Verify
After you send traffic, open your project and go to:- AI -> Dashboard for aggregate cost, request, and latency charts
- AI -> Requests for individual generations and tool calls
- AI -> Sessions to follow a chat/session timeline
- AI -> Users to break usage down by user
Billing behavior
Squasher counts completed generations as AI requests for plan enforcement and billing.- On free plans, Squasher drops additional AI requests after the monthly included quota is exhausted.
- On paid plans, Squasher keeps ingesting and records overage usage once you go beyond the included monthly AI request quota.