Observability
Use observability when you need step-level visibility into agent runtime behavior. It emits
span-like trace events for Ask AI and MCP tools: run start/end, prompt building, retrieval, model
calls, model responses, streaming handoff, tool calls, tool results, errors, retries, and timeouts.
Observability is separate from Analytics. It does not receive
page_view, search_query, api_ai_request, or mcp_tool; those usage events belong to
analytics.onEvent.
Quick Start
export default defineDocs({
observability: true,
});observability: true logs trace events to the console with the
[@farming-labs/docs:observability] prefix.
Live Local Logs
Use console observability when you want to watch Ask AI and MCP work as it happens:
export default defineDocs({
observability: {
console: "debug",
},
});Every trace event prints to the dev-server terminal with its traceId, spanId, name, status,
durationMs, previews, and metadata.
Callback
Use onEvent when you want to forward traces to a log drain, APM, OpenTelemetry bridge, database,
or your own debugging dashboard:
export default defineDocs({
observability: {
console: "debug",
async onEvent(event) {
await fetch("https://observability.example.com/events", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(event),
});
},
},
});Set console: false if you only want the callback and do not want terminal logs.
For metrics, aggregate by event.type, event.name, event.status, and event.durationMs. For
traces, group by event.traceId and order by startedAt or timestamp.
Event Shape
onEvent receives a normalized DocsObservabilityEvent:
interface DocsObservabilityEvent {
type: string;
timestamp: string;
source: "client" | "server" | "mcp";
traceId?: string;
spanId?: string;
parentSpanId?: string;
name?: string;
startedAt?: string;
endedAt?: string;
durationMs?: number;
status?: "started" | "success" | "error" | "retry" | "timeout";
inputPreview?: Record<string, unknown>;
outputPreview?: Record<string, unknown>;
url?: string;
path?: string;
referrer?: string;
locale?: string;
input?: {
query?: string;
question?: string;
feedbackComment?: string;
content?: string;
};
metadata?: Record<string, unknown>;
properties?: Record<string, unknown>;
}Example tool event:
{
traceId: "run_123",
spanId: "span_456",
parentSpanId: "run_123",
type: "tool.call",
name: "read_page",
startedAt: "2026-01-01T00:00:00.000Z",
endedAt: "2026-01-01T00:00:00.082Z",
durationMs: 82,
status: "success",
inputPreview: { page: "/docs/mcp" },
outputPreview: { chars: 4210 },
metadata: {
attempt: 1,
model: "gpt-5.2",
},
}Trace Events
Observability events describe runtime steps inside an agent run. They are span-like: use
traceId to group a run, spanId to identify a step, and parentSpanId to connect child steps to
their parent.
Ask AI Events
| Event | Meaning |
|---|---|
run.start | A new Ask AI run started. This is the root span for the request. |
user.input | The latest user message was accepted and summarized into safe counts. |
retrieval.query | Docs retrieval started for the user question. |
retrieval.result | Docs retrieval completed and produced measurable result counts. |
retrieval.error | Docs retrieval failed before the model call could use the context. |
prompt.build | The system prompt and retrieved docs context were assembled. |
model.call | The outbound model request started. |
model.response | The model provider returned successful response headers. |
model.stream | A streaming model response was handed back to the client. |
model.error | The model request failed, threw, or returned an error status. |
agent.final | The final response handoff was reached after a successful model call. |
run.error | The run ended unsuccessfully. |
run.end | The run ended, either successfully or after an error. |
MCP Tool Events
| Event | Meaning |
|---|---|
tool.call | An MCP tool call started, such as search_docs or read_page. |
tool.result | An MCP tool completed successfully and returned a result. |
tool.error | An MCP tool returned an error result or threw during execution. |
Generic Runtime Events
| Event | Meaning |
|---|---|
retry | A retry attempt was recorded for a failed or unstable step. |
timeout | A step timed out before it could complete. |
error | A generic run-level error was recorded outside a more specific event. |
Built-in trace events avoid raw user-authored text. They use lengths, counts, route names, model IDs, status codes, and content sizes so they are safer to aggregate.
Using Analytics Together
Configure both hooks when you want product analytics and runtime traces:
export default defineDocs({
analytics: {
async onEvent(event) {
await sendUsageEvent(event);
},
},
observability: {
console: "debug",
async onEvent(event) {
await sendTraceEvent(event);
},
},
});In that setup:
analytics.onEventreceives events likepage_view,search_query,api_ai_request, andmcp_toolobservability.onEventreceives events likerun.start,prompt.build,model.call, andtool.result
Options
| Option | Type | Default |
|---|---|---|
enabled | boolean | true when object is passed |
console | boolean | "log" | "info" | "debug" | true for observability: true |
includeInputs | boolean | false |
onEvent | (event) => void | Promise<void> | undefined |
How is this guide?