Skip to content

feat: add opencode-ai instrumentation (LAM-1513)#287

Open
laminar-coding-agent[bot] wants to merge 1 commit into
mainfrom
lam-1513-opencode-python-instrumentation
Open

feat: add opencode-ai instrumentation (LAM-1513)#287
laminar-coding-agent[bot] wants to merge 1 commit into
mainfrom
lam-1513-opencode-python-instrumentation

Conversation

@laminar-coding-agent

@laminar-coding-agent laminar-coding-agent Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Ports the lmnr-ts OpencodeInstrumentation to Python. Wraps opencode_ai.resources.session.SessionResource.chat and its async counterpart so that when a Laminar span context is active, a synthetic {type: "text", text: "", synthetic: True, ignored: True, metadata: {lmnrSpanContext: ...}} part is appended to the outgoing parts. The Opencode server forwards the metadata back so the downstream LLM span re-parents onto the caller's trace.
  • Wires Instruments.OPENCODE into the enum, INSTRUMENTATION_INITIALIZERS, and a new OpencodeInstrumentorInitializer (only activates when opencode-ai is installed).
  • Adds opencode-ai==0.1.0a36 to [dependency-groups].dev and pins the _instruments spec to opencode-ai >= 0.1.0a0 (the SDK only ships pre-release alphas right now — a plain >= 0.1.0 fails BaseInstrumentor.instrument()'s version check and silently leaves chat unwrapped).
  • Adds 10 tests in tests/test_instrumentations/test_opencode/ driving the real opencode_ai client over httpx.MockTransport, mirroring the TS suite's nock-based assertions (span-context injection sync + async, no-injection-without-active-span, preserves existing parts, does not mutate caller's list, trace_id matches the observe span, nested observe uses the innermost span, response pass-through, sync/async coexistence).

Test plan

  • uv run pytest tests/test_instrumentations/test_opencode/ -v — 10/10 pass
  • uv run pytest tests/test_instrument_initializers.py — passes (enum/initializer length check)
  • Broader suite — no new regressions; the 4 failing test_langchain* cases are pre-existing on main (verified with git stash).

🤖 Generated with Claude Code


Note

Medium Risk
Moderate risk: introduces new runtime monkey-wrapping of opencode_ai sync/async SessionResource.chat, which could affect request payloads and compatibility as the upstream SDK evolves; changes are gated on package presence and covered by targeted tests.

Overview
Adds a new opencode-ai OpenTelemetry instrumentor that wraps SessionResource.chat (sync + async) to conditionally inject a synthetic parts entry containing the active Laminar span context, enabling downstream Opencode model spans to re-parent onto the caller’s trace.

Wires the new instrument into Instruments/initializer registration (activated only when opencode-ai is installed), pins opencode-ai==0.1.0a36 for dev testing, and adds a dedicated test suite validating injection behavior (including no-op without an active span, no mutation of caller parts, nested span selection, response passthrough, and sync/async coexistence).

Reviewed by Cursor Bugbot for commit 062b448. Bugbot is set up for automated code reviews on this repo. Configure here.

Mirrors the lmnr-ts OpencodeInstrumentation: wraps SessionResource.chat
(sync + async) and appends a synthetic text part carrying the current
Laminar span context, so the Opencode server can re-parent the downstream
LLM span onto the caller's trace.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant