Pi coding agent
Trace pi agent loops, model calls, tool executions, usage, cost, and lifecycle events.
@telemetry-dev/pi adds telemetry.dev to @earendil-works/pi-coding-agent. It targets pi 0.82.1 and accepts pi 0.80.4 or later.
What it captures
Each prompt produces one trace with this shape:
invoke_agent
├── chat {model}
│ ├── execute_tool {toolName}
│ └── execute_tool {toolName}
└── chat {model}
invoke_agentrecords the prompt, final assistant text, result, and session ID.chat {model}records provider, models, response ID, finish reason, token usage, and pi’s estimated USD cost.execute_tool {toolName}records the tool-call ID, arguments, result, and error state.- Session, turn, compaction, model-change, and shutdown events become logs.
Tool spans nest under the chat span that issued the tool call. A tool without a matching chat span nests under invoke_agent.
Only text blocks become assistant output. Thinking and tool-call blocks do not become output, but usage can include reasoning tokens.
Set up the integration
Make a project at telemetry.dev. Then copy an API key from the project’s setup page.
Set these variables in the environment that starts pi:
export TELEMETRY_DEV_API_KEY=td_live_...
export TELEMETRY_DEV_ENVIRONMENT=development
export OTEL_SERVICE_NAME=pi
The integration reads all setup values from the environment when pi loads the package entry.
Pi package
After the public release, add the package to ~/.pi/agent/settings.json:
{
"packages": ["npm:@telemetry-dev/pi"]
}
The package manifest points to ./dist/register.mjs. The public @telemetry-dev/pi/register entry exports telemetryDevExtension() with environment setup.
Extension file
If pi can resolve the package, add ~/.pi/agent/extensions/telemetry-dev.ts:
import { telemetryDevExtension } from "@telemetry-dev/pi";
export default telemetryDevExtension();
Use the factory form when you must set options in code:
import { telemetryDevExtension } from "@telemetry-dev/pi";
export default telemetryDevExtension({
agentName: "pair-programmer",
captureInput: false,
captureOutput: true,
});
Span lifecycle
agent_start opens the invoke_agent span. Retries and compaction can start the agent loop again, but they keep the same span.
This behavior lets a later retry replace a retryable result before the prompt settles. session_shutdown closes an unfinished loop and waits for the final flush.
Pi does not supply TTFT or request-duration values. The integration measures chat duration from message_start to message_end with the local clock.
Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
TELEMETRY_DEV_API_KEY |
Yes | None | Ingest API key. Without a key, the integration is a no-op. |
TELEMETRY_DEV_BASE_URL |
No | https://ingest.telemetry.dev |
OTLP ingest base URL. |
TELEMETRY_DEV_ENVIRONMENT |
No | production |
Environment on exported telemetry. |
OTEL_SERVICE_NAME |
No | pi |
OpenTelemetry service name. |
Options
telemetryDevExtension() accepts TelemetryDevExtensionOptions. The type contains SDK options except registerGlobal, plus agentName.
| Option | Type | Default | Description |
|---|---|---|---|
agentName |
string |
pi |
Value for gen_ai.agent.name. |
apiKey |
string |
TELEMETRY_DEV_API_KEY |
Ingest API key. |
baseUrl |
string |
TELEMETRY_DEV_BASE_URL or production ingest |
Ingest base URL. |
environment |
string |
TELEMETRY_DEV_ENVIRONMENT or production |
Deployment environment. |
serviceName |
string |
OTEL_SERVICE_NAME or pi |
Service name on each trace. |
enabled |
boolean |
true |
Set to false for a complete no-op. |
exportMode |
"batched" | "immediate" |
batched |
Span export mode. |
captureInput |
boolean |
true |
Capture prompts and tool arguments. |
captureOutput |
boolean |
true |
Capture assistant text and tool results. |
mask |
(value, context) => unknown |
None | Change captured values before serialization. |
maxAttributeLength |
number |
65536 |
Maximum content attribute length. |
batch |
BatchOptions |
SDK defaults | Batch size, delay, queue, and timeout settings. |
spanFilter |
(span) => boolean |
None | Select spans for export. |
resourceAttributes |
Record<string, AttributeValue> |
None | Add OpenTelemetry resource attributes. |
logLevel |
"debug" | "info" | "warn" | "error" | "silent" |
warn |
SDK diagnostic level. |
fetch |
typeof fetch |
globalThis.fetch |
Custom fetch implementation. |
waitUntil |
(promise) => void |
None | Extend serverless work for export. |
onError |
(error) => void |
None | Receive integration errors. The extension does not throw them into pi. |
The integration forces registerGlobal to false. The first initialization in a process supplies the SDK options.
Open the trace explorer after a prompt settles. For API key setup, refer to the quickstart.