
exploring-llm-costs
Investigate LLM spend in PostHog — total cost over time, cost by model, provider, user, trace, or custom dimension, token and cache-hit economics, and cost regressions. Use when the user asks "how much are we spending on LLMs?", "which model / user / feature is most expensive?", "why did cost spike?", wants to build a cost dashboard or alert, or pastes a trace URL and asks about its cost.
- Installs
- 208
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/posthog/ai-plugin --skill exploring-llm-costs- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads exploring-llm-costs automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Exploring LLM costs
PostHog attaches per-call cost metadata to every $ai_generation and $ai_embedding
event at ingestion time. Every cost question reduces to an aggregation over those
two event types — the interesting variation is only in how you group, filter, and
compare.
This skill covers the common cost investigations: total spend, breakdowns (model, provider, user, trace, custom property), token and cache-hit analysis, regression debugging, and materializing results as insights, dashboards, or alerts.
Tools
| Tool | Purpose |
|---|---|
posthog:query-trends | Native cost trends with supported sums, breakdowns, and comparisons |
posthog:execute-sql | Ad-hoc HogQL for any cost aggregation — the workhorse of this skill |
posthog:query-llm-traces-list | List traces with rolled-up cost, token, and error metrics |
posthog:query-llm-trace | Cost breakdown of a single trace across all its events |
posthog:read-data-schema | Discover which custom properties exist for breakdowns |
posthog:insight-create | Materialize a cost chart as a saved insight |
posthog:dashboard-create | Bundle cost insights into a dashboard |
posthog:alert-create | Alert when cost crosses a threshold |
posthog:generate-app-url | Build region- and project-qualified links back to the UI |
Core rules
Three rules cover most of what goes wrong:
- Sum
$ai_total_cost_usdfor rollups, never the components. Components drop request and web-search fees. The UI's cost cells sum$ai_total_cost_usdoverevent IN ('$ai_generation', '$ai_embedding'); mirror that. Full schema and rationale in cost properties. - Always include both
$ai_generationand$ai_embeddingin cost queries unless the project demonstrably does not use embeddings — missing them silently under-counts.$ai_traceand$ai_spancarry no rollup cost; some SDK wrappers duplicate$ai_total_cost_usdonto$ai_traceso don't include it in rollups or you'll double-count. - Always set a time range. Cost queries without one scan the full events table.
$ai_total_cost_usd is set at ingestion via one of three paths (passthrough,
custom pricing, automatic lookup). When a cost looks wrong, read
$ai_cost_model_source first — see cost sources
for the precedence rules and a diagnostic query.
Cache-hit math depends on whether the provider reports cache tokens inclusively
or exclusively of $ai_input_tokens. Always branch on the per-event
$ai_cache_reporting_exclusive flag, never on provider name — see
cache accounting for the exclusive-vs-inclusive
formula.
distinct_id is the canonical user dimension. Customers often attach custom
properties (feature, tenant_id, workflow_name) — discover them with
posthog:read-data-schema before grouping. Don't guess names.
Workflow: total spend in a window
posthog:execute-sql
SELECT round(sum(toFloat(properties.$ai_total_cost_usd)), 4) AS total_cost_usd
FROM events
WHERE event IN ('$ai_generation', '$ai_embedding')
AND timestamp >= now() - INTERVAL 30 DAY
Workflow: cost breakdowns
Every cost question is a variation of the same template — group by a dimension,
aggregate $ai_total_cost_usd. See breakdown patterns
for ready-to-run recipes:
- Cost over time (daily)
- Cost by model
- Cost by user (top spenders)
- Cost by trace (top expensive traces)
- Cost by custom dimension
- Cost-per-call distribution
- Input vs output vs cache economics
Workflow: inspect a single trace's cost
When the user pastes a trace URL and asks about its cost, fetch the trace and surface the per-event breakdown:
posthog:query-llm-trace
{ "traceId": "<trace_id>", "dateRange": {"date_from": "-30d"} }
Sum $ai_total_cost_usd across the returned events, grouped by span name or
model, to show which step(s) drove the cost. The trace response already
includes totalCost as a convenience.
Workflow: debug a cost regression
"Our LLM bill jumped — why?" is almost always one of: more calls, bigger prompts, a new model, or a change in cache-hit rate. Work through them in order — see regression debugging for the 5-step playbook.
Workflow: materialize as an insight, dashboard, or alert
After ad-hoc queries answer the question, persist them as insights, bundle
into a dashboard, or wire up alerts. See materializing
for ready-to-run JSON for posthog:insight-create, posthog:dashboard-create,
and posthog:alert-create.
Constructing UI links
Never hand-write https://app.posthog.com/... links. That host drops the region and the
project prefix, so the user is redirected to login instead of the page you meant.
- Prefer the canonical URL the tool returns.
query-llm-traces-listandquery-llm-tracereturn_posthogUrl— surface that value. For a single trace, append?timestamp=<url_encoded_iso>(the trace's earliest event time) to that URL; the returned link carries no timestamp, and without one the trace page scans from a fixed early date instead of the ten-minute window around the trace. - Otherwise build the link with
generate-app-url. It resolves the correct region host and/project/<id>/prefix (e.g.https://us.posthog.com/project/2/ai-observability/traces). Pass concrete ids viaparams, never inline them into the path.- Dashboard:
generate-app-url {url: "/ai-observability/dashboard"} - Traces list (sort by cost):
generate-app-url {url: "/ai-observability/traces"} - Generations list:
generate-app-url {url: "/ai-observability/generations"} - Users list (per-user cost):
generate-app-url {url: "/ai-observability/users"} - Single trace:
generate-app-url {url: "/ai-observability/traces/{id}", params: {id: "<trace_id>"}}
- Dashboard:
generate-app-url cannot express query params, so append the ?timestamp=<url_encoded_iso>
described above to a single-trace link yourself.
Always surface a UI link so the user can verify visually.
Keeping this skill current
Provider reporting behavior (which tokens are inclusive vs exclusive, which costs show up where) shifts over time and can differ between SDK versions for the same provider. To avoid rot:
- Branch on event-level flags (
$ai_cache_reporting_exclusive,$ai_cost_model_source) rather than hardcoded provider or model names. Those flags are ingestion's resolved answer for the specific event and are the right source of truth. $ai_total_cost_usdis always authoritative for rollups — prefer it over summing components, which can drift as new cost categories are added.- For anything not covered here (new cost categories, changes to
pricing lookup, provider additions), run
posthog:docs-searchfor "calculating costs" or "AI observability" first rather than trusting a hardcoded rule in this file. - If you find this skill contradicting the UI, trust the UI and flag the skill for an update.
Tips
- Always set a time range — cost queries without one scan the full events table
- Token, cost, model, and
$ai_trace_idproperties are onevents— but message content ($ai_input/$ai_output_choices) lives only on theposthog.ai_eventstable; load theexploring-llm-tracesskill if you need content alongside cost - Always include
$ai_embeddingalongside$ai_generationwhen summing cost; embeddings are cheap per-call but add up at scale - Costs are written at ingestion (see Calculating LLM costs) — if
$ai_total_cost_usdis missing or zero, read$ai_cost_model_sourcefirst:passthroughmeans the SDK supplied costs;custommeans custom token prices;openrouter/manualmean automatic lookup; missing means the model wasn't matched (unusual custom model, fine-tune). Grep:countIf(properties.$ai_total_cost_usd IS NULL)per(model, source) - Custom pricing uses per-token prices, not per-million — if a custom-priced model looks ~1M× too expensive or too cheap, that's almost always the bug
- Exclude errored calls from cost totals only when explicitly asked — providers still charge for many error modes, and including them gives the truthful bill
- For per-user totals, exclude rows where
distinct_id = properties.$ai_trace_id— some SDKs default distinct_id to the trace ID when no user is set - Cost is additive across
$ai_generation+$ai_embeddingevents within a trace; summing on$ai_spangives zero.$ai_tracemay carry$ai_total_cost_usdfrom some SDK wrappers — don't include it in rollups or you'll double-count.$ai_evaluationevents also carry cost but are not part of the stock UI rollups; include them only when the user explicitly wants evaluation spend in the total - Cache-hit rate depends on
$ai_cache_reporting_exclusive— branch on the event-level flag rather than on provider or model name. Provider behavior and SDK versions drift; the flag is ingestion's resolved answer for that specific event - When answering "why is X expensive?", show the cost and the token split — the user almost always wants to know whether to shrink prompts, shrink outputs, or switch models
- Before building a custom dashboard, check whether the stock
/ai-observability/dashboardtiles already answer the question — re-creating them is churn - For large tenants, materialize common cost queries as insights and reuse via
insight-query; ad-hoc SQL is fine for one-offs but re-running it on every dashboard load is expensive
References
- cost properties — full property schema, total-cost rationale, event-set rules
- cost sources — how costs get set at ingestion plus a diagnostic query
- cache accounting — exclusive vs inclusive providers, cache-hit-rate formula
- breakdown patterns — SQL recipes for every common breakdown
- regression debugging — 5-step playbook for cost spikes
- materializing — insight, dashboard, and alert JSON
Related skills
analyzing-expensive-users— who drives the spend, and whether their usage pattern explains itexploring-llm-traces— inspect the expensive traces the breakdowns point at
FAQ
What does the exploring-llm-costs skill do?
Investigate LLM spend in PostHog — total cost over time, cost by model, provider, user, trace, or custom dimension, token and cache-hit economics, and cost regressions. Use when the user asks "how much are we spending on LLMs?", "which model / user / feature is most expensive?", "why did cost spike?", wants to build a cost dashboard or alert, or pastes a trace URL and asks about its cost.
How do I install exploring-llm-costs?
Run npx skills add https://github.com/posthog/ai-plugin --skill exploring-llm-costs in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/exploring-llm-costs/ (personal) or .claude/skills/exploring-llm-costs/ (project).
Which AI agents can use exploring-llm-costs?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is exploring-llm-costs safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains exploring-llm-costs?
It is published by posthog in posthog/ai-plugin, and it is an official skill from the maker of the technology it covers. It has 208 recorded installs.
More from posthog/ai-plugin
instrument-product-analytics
posthog/ai-plugin
Add PostHog product analytics events to track user behavior. Use after implementing new features or reviewing PRs to ensure meaningful user actions are captured. Also handles initial PostHog SDK setup if not yet installed.
instrument-feature-flags
posthog/ai-plugin
Add PostHog feature flags to gate new functionality. Use after implementing features or reviewing PRs to ensure safe rollouts with feature flag controls. Also handles initial PostHog SDK setup if not yet installed.
cleaning-up-stale-feature-flags
posthog/ai-plugin
Identify stale feature flags in a PostHog project and clean up the code that checks them. Use when the user wants to find, audit, or remove unused, fully rolled out, or abandoned feature flags, run a feature flag hygiene review or a weekly cleanup, reduce feature flag tech debt, or asks "which flags can I remove?". When the agent can read and edit a repository it performs the code cleanup itself: tested local changes, and one draft PR per flag when the user authorizes publishing. Agents without repository access generate a tailored cleanup prompt instead. Covers staleness detection, dependency checking, retained-path rules, and the code-first ordering. This skill does not archive or otherwise change a flag in PostHog.
auditing-experiments-flags
posthog/ai-plugin
Audit PostHog experiments and feature flags for configuration issues, staleness, and best-practice violations. Read when the user asks to audit, health-check, or review experiments or feature flags, check flag hygiene, or verify experiment setup.
querying-posthog-data
posthog/ai-plugin
Explains how to query PostHog data, defaulting to typed runners for supported product analytics. Read it before you write HogQL/SQL. Also read it before you call execute-sql against PostHog. Use it to find or aggregate PostHog entities. These entities include insights, dashboards, cohorts, feature flags, experiments, surveys, hog flows, warehouse data, and persons. Use it for trends, funnels, retention, lifecycle, paths, stickiness, web analytics, error tracking, logs, sessions, and LLM traces. Before you calculate a governed business or telemetry measure, check system.informationschema.metrics for an approved definition. Examples include MRR, activation, billable usage, active organizations, and failure rates. Use the approved definition before you derive a measure from raw events or use a typed domain tool. It also covers HogQL differences, system table schemas, functions, query examples, and schema discovery.
creating-experiments
posthog/ai-plugin
Guides agents through experiment creation: reading the project's setup with experiment-setup-context, defining the hypothesis, configuring rollout and bucketing, setting up analytics and running time, and reporting which choices are guesses. Delegates rollout decisions to configuring-experiment-rollout and metric setup to configuring-experiment-analytics. TRIGGER when: user asks to create a new experiment or A/B test, OR when you are about to call experiment-create. DO NOT TRIGGER when: user is updating an existing experiment, managing lifecycle, or only browsing experiments.
Popular ai & agents skills
google-agents-cli-publish
google/agents-cli
This skill should be used when the user wants to "publish an agent", "publish my ADK agent", "register an agent with Gemini", "publish to Gemini" (formerly Gemini Enterprise), or needs guidance on the agents-cli publish gemini command. Also use when the user wants to "manage agents in Agent Registry", "list/update/delete registered agents", or "register an MCP server". Covers ADK vs A2A registration modes, programmatic and interactive usage, flag reference, auto-detection from deployment metadata, Agent Registry fleet management, and troubleshooting. Part of the agents-cli skills suite. Do NOT use for deployment (use google-agents-cli-deploy).
google-agents-cli-eval
google/agents-cli
This skill should be used when the user wants to "run an evaluation", "evaluate my agent", "evaluate my ADK agent", "write an eval dataset", "analyze eval failures", "compare eval results", "optimize agent", or needs guidance on the Gemini platform eval methodology and the Quality Flywheel. Covers eval metrics, dataset schema, LLM-as-judge scoring, and common failure causes. Applies to any agents-cli project, whatever framework the agent is written in. Do NOT use for agent API code patterns (ADK: use google-agents-cli-adk-code), deployment (use google-agents-cli-deploy), or project scaffolding (use google-agents-cli-scaffold).
skill-creator
anthropics/skills
Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, edit, or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.
codex-pet
prime-skills/runcomfy-agent-skills
Codex Pet generator on RunComfy. Build a Codex-compatible Codex Pet spritesheet.webp + pet.json from a single reference image, drop it into ${CODEXHOME:-$HOME/.codex}/pets/ / and Codex picks it up as a custom Codex Pet next to the 8 built-ins. This skill produces the exact Codex Pet atlas Codex expects (1536x1872 PNG/WebP, 8 cols x 9 rows, 192x208 cells, 9 animation states — idle, running-right, running-left, waving, jumping, failed, waiting, running, review). Calls OpenAI GPT Image 2 edit ONCE via the local RunComfy CLI as runcomfy run openai/gpt-image-2/edit to produce a canonical Codex Pet pose, then assembles all 9 animation rows programmatically with ImageMagick micro-transforms — no Codex Pro, no $imagegen, no OPENAIAPIKEY required, only RUNCOMFYTOKEN. Triggers on "codex pet", "create codex pet", "make codex pet", "hatch codex pet", "/hatch image", "desktop pet codex", "codex pets", "spritesheet.webp", or any explicit ask to build a custom pet for OpenAI Codex.
full-output-enforcement
leonxlnx/taste-skill
Overrides default LLM truncation behavior. Enforces complete code generation, bans placeholder patterns, and handles token-limit splits cleanly. Apply to any task requiring exhaustive, unabridged output.
executing-plans
obra/superpowers
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available