Generations are events that capture LLM calls and their responses. They represent interactions and conversations with an AI model. Generations are tracked as $ai_generation
events and can be used to create and visualize insights just like other PostHog events.


The LLM analytics > Generations tab displays a list of generations, along with a preview of key autocaptured properties. You can filter and search for generations by various properties.


What does each generation capture?
A generation event records the AI model’s inputs, generated output, and additional metadata – like token usage, latency, and cost – for each LLM call.
PostHog automatically logs and displays the generation and its data within a conversation view for contextual debugging and analysis. You can also view the raw JSON payload.
You can expect each generation to have the following properties (in addition to the default event properties):
Property | Description |
---|---|
$ai_model | The specific model, like gpt-5-mini or claude-4-sonnet |
$ai_latency | The latency of the LLM call in seconds |
$ai_tools | Tools and functions available to the LLM |
$ai_input | List of messages sent to the LLM |
$ai_input_tokens | The number of tokens in the input (often found in response.usage) |
$ai_output_choices | List of response choices from the LLM |
$ai_output_tokens | The number of tokens in the output (often found in response.usage ) |
$ai_total_cost_usd | The total cost in USD (input + output) |
... | See full list of properties |
When calling LLMs with our SDK wrappers, you can also enrich the $ai_generation
event with your own custom properties and PostHog attributes like groups and distinct IDs for identified users.
response = client.responses.create(model="gpt-5-mini",input=[{"role": "user", "content": "Tell me a fun fact about hedgehogs"}],posthog_distinct_id="user_123", # optionalposthog_trace_id="trace_123", # optionalposthog_properties={"custom_property": "value"}, # optionalposthog_groups={"company": "company_id_in_your_db"}, # optionalposthog_privacy_mode=False # optional)
How are generations, traces, and spans related?
Generations are nested under spans and traces.
A trace is the top-level entity that groups all related LLM operations, including spans and generations, together.
Spans are individual operations within a trace. Some spans represent generations, which are also uniquely identified using the $ai_span_id
property. However, most spans track other types of LLM operations such as tool calls, RAG retrieval, data processing, and more.


Event properties
A generation is a single call to an LLM.
Event name: $ai_generation
Core properties
Property | Description |
---|---|
$ai_trace_id | The trace ID (a UUID to group AI events) like conversation_id Must contain only letters, numbers, and special characters: - , _ , ~ , . , @ , ( , ) , ! , ' , : , | Example: d9222e05-8708-41b8-98ea-d4a21849e761 |
$ai_span_id | (Optional) Unique identifier for this generation |
$ai_span_name | (Optional) Name given to this generation Example: summarize_text |
$ai_parent_id | (Optional) Parent span ID for tree view grouping |
$ai_model | The model used Example: gpt-5-mini |
$ai_provider | The LLM provider Example: openai , anthropic , gemini |
$ai_input | List of messages sent to the LLM Example: [{"role": "user", "content": [{"type": "text", "text": "What's in this image?"}, {"type": "image", "image": "https://example.com/image.jpg"}, {"type": "function", "function": {"name": "get_weather", "arguments": {"location": "San Francisco"}}}]}] |
$ai_input_tokens | The number of tokens in the input (often found in response.usage) |
$ai_output_choices | List of response choices from the LLM Example: [{"role": "assistant", "content": [{"type": "text", "text": "I can see a hedgehog in the image."}, {"type": "function", "function": {"name": "get_weather", "arguments": {"location": "San Francisco"}}}]}] |
$ai_output_tokens | The number of tokens in the output (often found in response.usage) |
$ai_latency | (Optional) The latency of the LLM call in seconds |
$ai_http_status | (Optional) The HTTP status code of the response |
$ai_base_url | (Optional) The base URL of the LLM provider Example: https://api.openai.com/v1 |
$ai_request_url | (Optional) The full URL of the request made to the LLM API Example: https://api.openai.com/v1/chat/completions |
$ai_is_error | (Optional) Boolean to indicate if the request was an error |
$ai_error | (Optional) The error message or object |
Cost properties
Cost properties are optional as we can automatically calculate them from model and token counts. If you want, you can provide your own cost property instead.
Property | Description |
---|---|
$ai_input_cost_usd | (Optional) The cost in USD of the input tokens |
$ai_output_cost_usd | (Optional) The cost in USD of the output tokens |
$ai_total_cost_usd | (Optional) The total cost in USD (input + output) |
Cache properties
Property | Description |
---|---|
$ai_cache_read_input_tokens | (Optional) Number of tokens read from cache |
$ai_cache_creation_input_tokens | (Optional) Number of tokens written to cache (Anthropic-specific) |
Model parameters
Property | Description |
---|---|
$ai_temperature | (Optional) Temperature parameter used in the LLM request |
$ai_stream | (Optional) Whether the response was streamed |
$ai_max_tokens | (Optional) Maximum tokens setting for the LLM response |
$ai_tools | (Optional) Tools/functions available to the LLM Example: [{"type": "function", "function": {"name": "get_weather", "parameters": {...}}}] |
Example API call
curl -X POST "https://us.i.posthog.com/i/v0/e/" \-H "Content-Type: application/json" \-d '{"api_key": "<ph_project_api_key>","event": "$ai_generation","properties": {"distinct_id": "user_123","$ai_trace_id": "d9222e05-8708-41b8-98ea-d4a21849e761","$ai_model": "gpt-4o","$ai_provider": "openai","$ai_input": [{"role": "user", "content": [{"type": "text", "text": "Analyze this data and suggest improvements"}]}],"$ai_input_tokens": 150,"$ai_output_choices": [{"role": "assistant", "content": [{"type": "text", "text": "Based on the data, here are my suggestions..."}]}],"$ai_output_tokens": 280,"$ai_latency": 2.45,"$ai_http_status": 200,"$ai_base_url": "https://api.openai.com/v1","$ai_request_url": "https://api.openai.com/v1/chat/completions","$ai_is_error": false,"$ai_temperature": 0.7,"$ai_stream": false,"$ai_max_tokens": 500,"$ai_tools": [{"type": "function", "function": {"name": "analyze_data", "description": "Analyzes data and provides insights", "parameters": {"type": "object", "properties": {"data_type": {"type": "string"}}}}}],"$ai_cache_read_input_tokens": 50,"$ai_span_name": "data_analysis_chat"},"timestamp": "2025-01-30T12:00:00Z"}'