Exploring LLM Clusters
Automate repetitive workflows and reduce manual effort
Example: Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Learn new skills, understand complex topics, get expert guidance
Example: Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Enhance output quality through reviews, suggestions, and refinements
Example: Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
Time estimate: 15-45 minutes depending on use case complexity
Prerequisites
Submit your Claude Code skill and start earning
epx add PostHog/skills --skill exploring-llm-clustersCompatible with
Supported agents
Identify usage patterns by analyzing AI/LLM traffic clusters generated via embedding similarity and Temporal workflows.
Use SQL queries to retrieve cluster metadata, compute cost and latency metrics, and identify high-error or high-cost traffic segments.
Drill into specific traces using trace IDs to inspect representative samples and verify AI-generated cluster descriptions.
| name | exploring-llm-clusters |
| description | 'Investigate LLM analytics clusters — understand usage patterns in AI/LLM traffic, compare cluster behavior, compute cost/latency metrics, and drill into individual traces within clusters.' |
Use this skill when investigating LLM analytics clusters — understanding what patterns exist in your AI/LLM traffic, comparing cluster behavior, and drilling into individual clusters.
| Tool | Purpose |
|---|---|
posthog:llm-analytics-clustering-jobs-list | List clustering job configurations for the team |
posthog:llm-analytics-clustering-jobs-retrieve | Get a specific clustering job by ID |
posthog:execute-sql | Query cluster run events and compute metrics |
posthog:query-llm-traces-list | Find traces belonging to a cluster |
posthog:query-llm-trace | Inspect a specific trace in detail |
PostHog clusters LLM traces (or individual generations) by embedding similarity.
A Temporal workflow runs periodically or on-demand, producing cluster events stored as
$ai_trace_clusters (trace-level) or $ai_generation_clusters (generation-level).
Each cluster event contains:
$ai_clustering_run_id — unique run identifier (format: <team_id>_<level>_<YYYYMMDD>_<HHMMSS>[_<job_id>])$ai_clustering_level — "trace" or "generation"$ai_window_start / $ai_window_end — time window analyzed$ai_total_items_analyzed — number of traces/generations processed$ai_clusters — JSON array of cluster objects$ai_clustering_params — algorithm parameters used$ai_clusters){
"cluster_id": 0,
"size": 42,
"title": "User authentication flows",
"description": "Traces involving login, signup, and token refresh operations",
"traces": {
"<trace_or_generation_id>": {
"distance_to_centroid": 0.123,
"rank": 0,
"x": -2.34,
"y": 1.56,
"timestamp": "2026-03-28T10:00:00Z",
"trace_id": "abc-123",
"generation_id": "gen-456"
}
},
"centroid_x": -2.1,
"centroid_y": 1.4
}
cluster_id: -1 is the noise/outlier cluster (items that didn't fit any cluster)traces are keyed by trace ID (trace-level) or generation event UUID (generation-level)rank orders items by proximity to centroid (0 = closest)x, y are 2D coordinates for visualization (UMAP/PCA/t-SNE reduced)Each team can have up to 5 clustering jobs. A job defines:
"trace" or "generation"Default jobs named "Default - trace" and "Default - generation" are auto-created
and disabled when a custom job is created for the same level.
posthog:execute-sql
SELECT
JSONExtractString(properties, '$ai_clustering_run_id') as run_id,
JSONExtractString(properties, '$ai_clustering_level') as level,
JSONExtractString(properties, '$ai_window_start') as window_start,
JSONExtractString(properties, '$ai_window_end') as window_end,
JSONExtractInt(properties, '$ai_total_items_analyzed') as total_items,
timestamp
FROM events
WHERE event IN ('$ai_trace_clusters', '$ai_generation_clusters')
AND timestamp >= now() - INTERVAL 7 DAY
ORDER BY timestamp DESC
LIMIT 10
posthog:execute-sql
SELECT
JSONExtractString(properties, '$ai_clustering_run_id') as run_id,
JSONExtractString(properties, '$ai_clustering_level') as level,
JSONExtractString(properties, '$ai_clustering_job_id') as job_id,
JSONExtractString(properties, '$ai_clustering_job_name') as job_name,
JSONExtractString(properties, '$ai_window_start') as window_start,
JSONExtractString(properties, '$ai_window_end') as window_end,
JSONExtractInt(properties, '$ai_total_items_analyzed') as total_items,
JSONExtractRaw(properties, '$ai_clusters') as clusters,
JSONExtractRaw(properties, '$ai_clustering_params') as params
FROM events
WHERE event IN ('$ai_trace_clusters', '$ai_generation_clusters')
AND JSONExtractString(properties, '$ai_clustering_run_id') = '<run_id>'
LIMIT 1
The clusters field is a JSON array. Parse it to see cluster titles, sizes, and descriptions.
Important: The clusters JSON can be very large (thousands of trace IDs with coordinates).
When the result is too large for inline display, it auto-persists to a file.
Use print_clusters.py from scripts/ to get a readable summary.
For trace-level clusters, compute cost/latency/token metrics:
posthog:execute-sql
SELECT
JSONExtractString(properties, '$ai_trace_id') as trace_id,
sum(toFloat(properties.$ai_total_cost_usd)) as total_cost,
max(toFloat(properties.$ai_latency)) as latency,
sum(toInt(properties.$ai_input_tokens)) as input_tokens,
sum(toInt(properties.$ai_output_tokens)) as output_tokens,
countIf(properties.$ai_is_error = 'true') as error_count
FROM events
WHERE event IN ('$ai_generation', '$ai_embedding', '$ai_span')
AND timestamp >= parseDateTimeBestEffort('<window_start>')
AND timestamp <= parseDateTimeBestEffort('<window_end>')
AND JSONExtractString(properties, '$ai_trace_id') IN ('<trace_id_1>', '<trace_id_2>', ...)
GROUP BY trace_id
For generation-level clusters, match by event UUID:
posthog:execute-sql
SELECT
toString(uuid) as generation_id,
toFloat(properties.$ai_total_cost_usd) as cost,
toFloat(properties.$ai_latency) as latency,
toInt(properties.$ai_input_tokens) as input_tokens,
toInt(properties.$ai_output_tokens) as output_tokens,
if(properties.$ai_is_error = 'true', 1, 0) as is_error
FROM events
WHERE event = '$ai_generation'
AND timestamp >= parseDateTimeBestEffort('<window_start>')
AND timestamp <= parseDateTimeBestEffort('<window_end>')
AND toString(uuid) IN ('<gen_uuid_1>', '<gen_uuid_2>', ...)
Once you've identified interesting clusters, use the trace tools to inspect individual traces:
posthog:query-llm-trace
{
"traceId": "<trace_id_from_cluster>",
"dateRange": {"date_from": "<window_start>", "date_to": "<window_end>"}
}
avg(cost), avg(latency), sum(cost) per clustertraces field)rank (closest to centroid = most representative)query-llm-trace to understand the patterntitle and description for the AI-generated summaryerror_countitems_with_errors / total_itemshttps://app.posthog.com/llm-analytics/clustershttps://app.posthog.com/llm-analytics/clusters/<url_encoded_run_id>https://app.posthog.com/llm-analytics/clusters/<url_encoded_run_id>/<cluster_id>Always surface these links so the user can verify visually in the PostHog UI.
cluster_id: -1) contains outliers that didn't fit any patternllm-analytics-clustering-jobs-list to understand what clustering configs are activequery-llm-trace for deep inspectionAI-first code editor with Composer
Before installing skills in Cursor, ensure your development environment meets these requirements:
node --versionexploring-llm-clustersExecute the skills CLI command in your project's root directory to begin installation:
epx add PostHog/skills --skill exploring-llm-clustersFetches exploring-llm-clusters from PostHog/skills and configures it for Cursor.
The CLI shows a list of agents. Use arrow keys and space to select Cursor:
Confirm successful installation by checking the skill directory location:
.cursor/skills/exploring-llm-clusters
Restart Cursor to activate exploring-llm-clusters. Access via /exploring-llm-clustersin your agent's command palette.
Learn more:View source on GitHubSkills CLI docsAbout CursorWhat are agent skills?
Steps
Common Pitfalls
✓ Do
✗ Don't
💡 Pro Tips
✓ Use when
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
✗ Avoid when
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
instrument-product-analytics
PostHog/skills · PostHog · same repo
instrument-llm-analytics
PostHog/skills · PostHog · same repo
instrument-feature-flags
PostHog/skills · PostHog · same repo
query-examples
PostHog/skills · PostHog · same repo
integration-react-react-router-7-framework
PostHog/skills · PostHog · same repo
logs-python
PostHog/skills · PostHog · same repo
We added exploring-llm-clusters from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
exploring-llm-clusters is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
I recommend exploring-llm-clusters for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.
exploring-llm-clusters reduced setup friction for our internal harness; good balance of opinion and flexibility.
exploring-llm-clusters fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
exploring-llm-clusters reduced setup friction for our internal harness; good balance of opinion and flexibility.
Keeps context tight: exploring-llm-clusters is the kind of skill you can hand to a new teammate without a long onboarding doc.
exploring-llm-clusters fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
We added exploring-llm-clusters from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
I recommend exploring-llm-clusters for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.
showing 1-10 of 61