Skip to content
telemetry.dev
Esc
navigateopen⌘Jpreview
On this page

opencode

Trace opencode agent turns, model calls, tools, subagents, usage, cost, and session events.

@telemetry-dev/opencode connects the opencode plugin API to telemetry.dev. It requires opencode 1.15.11 or later.

What it captures

A prompt produces one trace with this shape:

invoke_agent
├── chat {model}
│   ├── execute_tool {tool}
│   └── execute_tool task
│       └── invoke_agent
└── chat {model}
  • invoke_agent records the prompt, agent name, and opencode session ID.
  • chat {model} records provider, model, finish reason, usage, host-reported cost, and errors.
  • execute_tool {tool} records the tool-call ID, arguments, result, duration, and error state.
  • Task subagents nest under the open span from the parent session.
  • Session creation, compaction, and error events become logs.

Assistant output text is not captured. The completed assistant event supplies metadata and usage, but it does not supply final text.

Reasoning tokens count as output tokens. The span also keeps separate reasoning, cache-read, and cache-write token values.

Set up the integration

Make a project at telemetry.dev. Then copy an API key from the project’s setup page.

Set the API key in the environment that starts opencode:

export TELEMETRY_DEV_API_KEY=td_live_...
export TELEMETRY_DEV_ENVIRONMENT=development
export OTEL_SERVICE_NAME=opencode

Select one plugin setup after the package becomes public.

Project plugin file

Install the package:

npm install @telemetry-dev/opencode
pnpm add @telemetry-dev/opencode
yarn add @telemetry-dev/opencode
bun add @telemetry-dev/opencode

Add .opencode/plugin/telemetry-dev.ts:

import { telemetryDevPlugin } from "@telemetry-dev/opencode";

export const TelemetryDev = telemetryDevPlugin();

opencode finds project plugin files in this directory.

opencode configuration

The /server export supplies opencode’s PluginModule shape. Add it to opencode.json:

{
  "plugin": [
    ["@telemetry-dev/opencode/server", { "environment": "production" }]
  ]
}

Keep the API key out of opencode.json. Configuration tuple options take precedence over factory options.

Session lifecycle

A chat.message event starts invoke_agent. The span closes on one of these signals:

  • A modern session.status event with status.type set to idle
  • A legacy session.idle event
  • Plugin disposal

If session.compacted follows the error, the integration removes the stale error. Otherwise, the integration applies the error when the session settles.

Plugin disposal closes open tool, chat, and agent spans. It marks spans without an error as incomplete and waits for a flush.

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 opencode OpenTelemetry service name.

Options

telemetryDevPlugin() accepts TelemetryDevPluginOptions. The type contains SDK options except registerGlobal, plus agentName.

Option Type Default Description
agentName string opencode 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 opencode 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 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 plugin does not throw them into opencode.

The integration forces registerGlobal to false. The first initialization in a process supplies the SDK options.

Use captureInput, captureOutput, and mask to control content:

import { telemetryDevPlugin } from "@telemetry-dev/opencode";

export const TelemetryDev = telemetryDevPlugin({
  captureInput: false,
  captureOutput: false,
  mask: (value, { key }) => key === "password" ? "[REDACTED]" : value,
});

Open the trace explorer after a prompt completes. For API key setup, refer to the quickstart.

Last updated on August 3, 2026

Was this page helpful?