Traces
Pi Agent Traces
Trace current Pi Agent model turns, streams, tool calls, usage, costs, and agent identity through the Inference platform.
Using legacy @mariozechner/pi-ai? Use the
PI AI integration.
Inference platform instruments current Pi Agent applications built with
@earendil-works/pi-agent-core and @earendil-works/pi-ai. Each Pi Models
collection owns its providers. Pass that collection to the Inference platform so each model
turn emits an OpenInference LLM span.
This guide is tested with @earendil-works/pi-agent-core@0.84.1 and
@earendil-works/pi-ai@0.84.1.
Pi Agent is available for TypeScript. There is no Python equivalent for this integration.
What Is Captured
- One LLM span per model turn, named like
pi-agent.<provider>.turn - Calls through
stream,streamSimple,complete, andcompleteSimple - System prompts, input messages, assistant output, model name, and provider
- Tool call IDs, names, and JSON arguments from assistant messages
- Token usage, prompt cache read/write counts, finish reason, and total cost
- Errors, aborts, and exception details
- Active
agentSpan()identity, includingagent.id,agent.name,agent.role, andsession.id
Install
bun add @inference/tracing@0.1.9 @earendil-works/pi-agent-core@0.84.1 @earendil-works/pi-ai@0.84.1Configure Export
Set the Inference Tracing endpoint and token before your app starts. Generate a token at API Keys.
export INFERENCE_OTLP_ENDPOINT="https://telemetry.inference.net"
export INFERENCE_API_KEY="<your-token>"
export INFERENCE_SERVICE_NAME="pi-agent"
export ANTHROPIC_API_KEY="<your-anthropic-api-key>"Initialize Tracing
Create the Pi Models collection before tracing setup. Pass the collection as
piAgent. You can add providers before or after setup.
import { createModels } from "@earendil-works/pi-ai";
import { anthropicProvider } from "@earendil-works/pi-ai/providers/anthropic";
import { setup } from "@inference/tracing";
const models = createModels();
const tracing = await setup({
serviceName: process.env.INFERENCE_SERVICE_NAME ?? "pi-agent",
autoInstrument: false,
modules: { piAgent: models },
});
models.setProvider(anthropicProvider());Pi uses a separate Models collection for each application. Inference platform cannot
find that collection through package auto-detection. Pass it as
modules.piAgent or call instrumentPiAgent(models, tracing).
For manual initialization, use the Pi Agent subpath helper before the agent makes its first model call.
import { createModels } from "@earendil-works/pi-ai";
import { setup } from "@inference/tracing";
import { instrumentPiAgent } from "@inference/tracing/pi-agent";
const models = createModels();
const tracing = await setup({ autoInstrument: false });
instrumentPiAgent(models, tracing);Run An Agent
Pass models.streamSimple.bind(models) to the current Pi Agent. Wrap the run
in agentSpan() to group all model turns under one stable agent identity.
The following example uses an Anthropic model. It assumes you ran the setup block above.
import { Agent } from "@earendil-works/pi-agent-core";
import { agentSpan } from "@inference/tracing";
const model = models.getModel("anthropic", "claude-sonnet-4-6");
if (!model) throw new Error("Pi model not found");
const agent = new Agent({
initialState: {
systemPrompt: "You answer order questions in one short sentence.",
model,
},
sessionId: "order-abc-123",
streamFn: models.streamSimple.bind(models),
});
await agentSpan(
{
agentId: "pi-support-agent",
agentName: "Pi Support Agent",
spanName: "pi-support-agent.run",
sessionId: "order-abc-123",
role: "support",
system: "pi-agent",
},
async (span) => {
const input = "Summarize order ABC-123.";
span.setInput(input);
await agent.prompt(input);
span.setOutput(agent.state.messages.at(-1));
},
);
await tracing.shutdown();Expected spans:
pi-support-agent.runAGENT span- One or more
pi-agent.anthropic.turnLLM child spans
Trace Tool Execution
Pi returns model tool calls in assistant messages and executes AgentTool
functions locally. Inference platform records the requested tool name, ID, and arguments
on the LLM span. Wrap local execution with manualSpan() when you also want a
TOOL span for the work.
import { type AgentTool } from "@earendil-works/pi-agent-core";
import { Type } from "@earendil-works/pi-ai";
import { manualSpan, SpanKindValues } from "@inference/tracing";
const parameters = Type.Object({ orderId: Type.String() });
const lookupOrder: AgentTool<typeof parameters> = {
name: "lookup_order",
label: "Look up order",
description: "Look up an order by ID.",
parameters,
execute: async (toolCallId, { orderId }) =>
manualSpan(
{
spanName: "lookup_order",
spanKind: SpanKindValues.TOOL,
toolName: "lookup_order",
toolCallId,
input: { orderId },
},
async (span) => {
const order = { orderId, status: "shipped", eta: "Friday" };
span.setOutput(order);
return {
content: [{ type: "text" as const, text: JSON.stringify(order) }],
details: order,
};
},
),
};Add lookupOrder to initialState.tools. A tool round trip then produces:
- A
pi-agent.<provider>.turnLLM span with the requested tool call - A
lookup_orderTOOL span for local execution - Another
pi-agent.<provider>.turnLLM span for the final answer
Verify in the Inference platform
Filter traces by your service.name, for example pi-agent. A successful run
shows the AGENT span with nested Pi Agent LLM spans. Each LLM span includes
input/output, model metadata, usage, finish reason, and tool call attributes.
If no Pi Agent spans appear:
- Pass the
Modelscollection asmodules: { piAgent: models }. - Instrument the collection before the agent makes its first model call.
- Add providers through the instrumented collection's
setProvider()method. - Consume streaming results or await
agent.prompt()before shutdown. - Call
await tracing.shutdown()before a short-lived process exits.