Scope
This covers events pushed viactx.chatTelemetry.push(...) in:
packages/orchestrator-core/src/chat/chat-pipeline.ts
packages/orchestrator-core/src/telemetry/chat-telemetry.ts
chat_pipeline_start or image rewrite logs.
Event transport
Each telemetry entry is:- Buffered in memory.
- Optionally persisted as NDJSON.
- Emitted to server logs as a structured log with
event: "chat_telemetry".
NODE_ENV=test. Set
CHAT_TELEMETRY_PERSIST=0 to keep telemetry in memory only.
- File:
CHAT_TELEMETRY_FILE, else.data/chat-telemetry.ndjsonin the data directory. The Docker image sets/app/.data/chat-telemetry.ndjson. - Buffer: the newest
CHAT_TELEMETRY_LIMITentries, default500, which are also what is reloaded from the file at startup.
Event schema
Fields fromChatTelemetryEntry:
- Required:
id,at,phase,session,requestedSlug,effectiveSlug,plannerSource,modelKey,modelUsed,promptHash,promptExcerpt,promptLength - Optional classification:
outcome,reason,reasonCategory - Optional plan shape:
intent,opCount,opTypes - Optional usage/cost:
inputTokens,outputTokens,totalTokens,cacheReadInputTokens,cacheCreationInputTokens,estimatedUsd - Optional timing:
totalDurationMs,planningDurationMs,firstPlanningTokenMs,applyDurationMs,imageResolutionDurationMs,planningAttempts, andtimelineStageonmilestonerows (request_received,first_token,first_structured_progress,plan_ready,first_op_applied,done) - Optional apply detail:
skippedOpCount,imagesRequested,imagesResolved - Optional planner context:
plannerTier(forced_deterministic,deterministic,llm_intent_router,full_llm,demo),contractMode(minimal,targeted,full),contractBytes,contractBlockCount,contextPackBytes,strictJsonEnabled,schemaRetryUsed,plannerRefusal,plannerIncomplete,compactContextEnabled,minimalContextEnabled - Optional change-log drift:
changelogMissingCount,changelogExtraCount,changelogFieldMislabelCount - Optional tool calls:
toolName,toolOk,toolLatencyMs,toolAttempts,toolErrorCode,correlationId - Optional suggestion pills:
suggestionIds,suggestionSources,clickedSuggestionId
reasonCategory values are from guardrail classification:
schema_violationambiguitynot_foundno_effective_changeplanner_refusalincomplete_outputmalformed_outputinternal_errorcanceledoperation_failedunsupported_by_site— the operation is valid, but the site declared it cannot honour it
Phases
phase is one of:
receivedmilestoneforced_plandeterministic_plan_generatedplan_attempt_failedplan_generatedplan_apply_failedrepair_attemptrepair_generatedtool_callresult
Outcomes
Emitted telemetry outcomes (chatTelemetry.push)
guardrail_failureneeds_clarificationplan_ready_for_approvalno_effective_changeappliedapply_failedapply_pending_plan_errorforced_duplicate_pageforced_create_pageplanner_exceptiondeterministic_plan_readycompound_deterministic_plan_readyattempt_${attempt}_failed(dynamic, e.g.attempt_1_failed)planning_exhaustedplanning_missingplanning_refusalplanning_incompleterepair_startedrepair_plan_generatedrepair_failedcontent_answervariation_request_redirectblocked_structural_capabilityllm_router_plan_readyllm_router_needs_clarificationtool_oktool_errorapi_errorempty_edit_plan
Debug-only outcomes (response payload, not telemetry rows)
validation_errorpending_plan_missingpending_plan_mismatchinfoblocked_demo_mode
Phase to outcome mapping
Common mappings in current implementation:received: nooutcomeforced_plan:forced_duplicate_page,forced_create_pagedeterministic_plan_generated:deterministic_plan_readyplan_attempt_failed:attempt_${attempt}_failedmilestone: nooutcome;timelineStagesays which point the turn reachedplan_generated: usually nooutcome(plan metadata + optional usage)tool_call:tool_okortool_errorplan_apply_failed:apply_failedrepair_attempt:repair_startedrepair_generated:repair_plan_generatedresult: terminal or branch outcomes such asapplied,needs_clarification,planning_exhausted,repair_failed, etc.
Telemetry APIs
The list and review endpoints are served by the standalone server. Library mode serves only the feedback endpoint below. On the standalone server these routes are not behind the access gate, and rows include prompt excerpts, so do not expose the server publicly. APUBLIC_DEMO answers 403 on them.
List entries (limit default 100, max 1000):
GET /telemetry/chat?limit=<n>&outcome=<outcome>&phase=<phase>&session=<session>
limit default 300, max 2000):
GET /telemetry/chat/review?limit=<n>&session=<session>
/telemetry/chat/review currently treats these as failure outcomes:
guardrail_failureapply_failedrepair_failedplanner_exceptionplanning_exhaustedplanning_missingplanning_refusalplanning_incompleteempty_edit_plan— anedit_planthat carried no operations. It answers 200 and reads as success to the user, which is exactly why it counts as a failure here.
POST /telemetry/chat/feedbackwith{ traceId, session, rating: "up" | "down", note? }GET /telemetry/chat/feedback?session=<session>&rating=<rating>&traceId=<id>&limit=<n>
Cache metrics
Cache-related fields:cacheReadInputTokenscacheCreationInputTokens
- OpenAI:
cacheReadInputTokensmaps tocached_tokens(from usage details) - Gemini: no cache fields are recorded
- Anthropic:
cacheReadInputTokensmaps tocache_read_input_tokens;cacheCreationInputTokensmaps tocache_creation_input_tokens
Source references
packages/orchestrator-core/src/telemetry/chat-telemetry.tspackages/orchestrator-core/src/chat/chat-pipeline.tsapps/orchestrator/src/index.ts(list and review endpoints)packages/orchestrator-core/src/errors.ts(reason categories)
What to read next
Token usage tracking
What each turn actually cost, per provider.
Chat troubleshooting
The playbook for a turn that produced the wrong operation, or none.