OpenCode
OpenCode is traced through the Langfuse OpenCode plugin, pointed at the Langfuse-compatible endpoint Oodle serves. The plugin rebuilds each turn from OpenCode's own events: one trace per user message, a generation per model step with tokens and cost, a tool observation per tool call, and events for retries, compaction and reasoning. No collector, no code change.
Oodle is a managed observability platform for metrics, logs, traces and agent traces. It ingests OpenTelemetry natively, so the snippet on this page is the complete setup.
Each trace shows the full transcript, the token counts and cost of every call, the agent structure (runs, steps and tool calls) and Signals: labels for loops, rate limits, refusals and tool failures, detected as the trace arrives.
Sign up for free to get an instance ID and an API key, or see the Agent Observability overview first.
You will need:
OODLE_INSTANCE: your Oodle instance ID (ap1, us1)OODLE_API_KEY: an Oodle API key (ap1, us1)API_DOMAIN: your Oodle API domain, shown on the tile
Open the OpenCode tile on the ap1, us1 page to
get these filled in for you, or let an agent do the setup with
/oodle-onboarding set up the opencode_observability integration.
Enable the plugin
Add to ~/.config/opencode/opencode.json, or to a project-level
opencode.json / opencode.jsonc:
{
"$schema": "https://opencode.ai/config.json",
"experimental": {
"openTelemetry": true
},
"plugin": ["@langfuse/opencode-observability-plugin@latest"]
}
OpenCode installs the plugin from npm on its next start.
Keep experimental.openTelemetry on. It is part of the plugin's setup,
and the plugin warns [Tracing disabled] in the OpenCode log without
it.
Give the plugin the Oodle credentials
Either as environment variables, in the shell that runs opencode or
the environment of the OpenCode server:
export LANGFUSE_BASE_URL="https://<API_DOMAIN>/v1/api/instance/<OODLE_INSTANCE>/langfuse"
export LANGFUSE_PUBLIC_KEY="default"
export LANGFUSE_SECRET_KEY="<OODLE_API_KEY>"
export LANGFUSE_SERVICE_NAME="opencode"
export LANGFUSE_ENVIRONMENT="production"
# Optional: who ran the session, for the Users page
export LANGFUSE_USER_ID="$(git config user.email)"
Or as the plugin's config file, ~/.config/opencode/opencode-langfuse.json:
{
"publicKey": "default",
"secretKey": "<OODLE_API_KEY>",
"baseUrl": "https://<API_DOMAIN>/v1/api/instance/<OODLE_INSTANCE>/langfuse",
"serviceName": "opencode",
"environment": "production",
"userId": "your-user-id"
}
Only the public key, the secret key and the base URL are required.
The public key is always default; the secret key is your Oodle API
key. Environment variables, when both keys are set, take precedence
over the file.
The service name is where the traces are filed. Without it they land
under unknown_service:opencode. The user id is what the Users page
groups on.
Verify
Restart OpenCode and run a session. Then:
- ap1, us1 lists one trace per user message,
filtered on service
opencode. Open one: the Transcript tab has the prompt and the reply, and the tree has anopencode.generationper model step with model, tokens and cost, and one span per tool call named after the tool. - Sessions groups the turns of one OpenCode session.
- Agent Graph draws the OpenCode agent (
build,plan, or the custom agent that ran the turn), its model calls and its tools.
What is sent
The plugin sends prompts, assistant messages, reasoning and tool inputs and outputs straight to Oodle. There is no collector in the path to redact them, so do not enable it for sessions whose content must not leave the machine.
Why the plugin
OpenCode can also export over OTEL_EXPORTER_OTLP_ENDPOINT when
experimental.openTelemetry is set. This integration uses the plugin
instead because the plugin traces the conversation: one trace per user
turn, every tool call as a span with its arguments and result, the
session id on every span, the agent that ran the turn, and a flush at
the end of each turn so a one-shot opencode run arrives whole.
Troubleshooting
- No traces at all: check the plugin is listed in
opencode.jsonand restart OpenCode. The OpenCode log (~/.local/share/opencode/log/) showsOTEL tracing initialized → <base url>when the plugin is running. Missing langfuse credentialsin the log: bothLANGFUSE_PUBLIC_KEYandLANGFUSE_SECRET_KEYmust be set, or the config file must hold both keys.- Traces under
unknown_service:opencode: setLANGFUSE_SERVICE_NAME, orserviceNamein the file. - No cost on a model: OpenCode reports the cost it computes from its own model list. A custom provider or model it does not price arrives with no cost, and Oodle then prices it from its model list, which may not carry it either.
Support
If you need assistance or have any questions, please reach out to us through:
- Email at [email protected]