Repository navigation
feat(evaluations): export each offline row as one trace - #170
Merged
ccschmitz-launchdarkly merged 4 commits intoOct 27, 2026
Merged
Conversation
ccschmitz-launchdarkly
marked this pull request as ready for review
October 22, 2026 21:15
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4b9e771. Configure here.
EvaluationsModule.run opens a launchdarkly.dataset_row root per row on the tracer provider init_client registered, then parents the generation, its tool calls, and each criterion's evaluate span beneath it. Every span shares the row's UUID5 gen_ai.conversation.id and carries launchdarkly.evaluation_run.id / .row_index. A provider handler traces its own call. For a plain function the runner writes the chat and execute_tool spans itself, only when the handler opened no SDK span. Content follows the existing capture_content gate. Core conversation.py gains two feature-neutral primitives, stamp_span_attributes and count_sdk_spans; everything evaluation-specific lives in evaluations/spans.py.
ccschmitz-launchdarkly
force-pushed
the
ccschmitz/offline-eval-conversation-spans-17b3
branch
from
October 23, 2026 16:53
4b9e771 to
5d02ea7
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lush in a finally When the active tracer provider lacks ConversationIdSpanProcessor, the SDK span count stays 0 even when the handler traced itself, so the runner wrote its own chat and tool spans as well. Both observer.count == 0 sites now also require _sdk_processor_is_active() (lifecycle.py). A test with a foreign TracerProvider checks each chat span is written once. Ending the row spans now runs in a try whose finally flushes the SDK events and the tracer provider. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
Pushed f684f98 (merge of origin/main) and fa2e25e:
Trade-off: under a foreign provider, a handler that traces nothing gets no runner-written chat span. Needs a human reviewer. |
4 tasks done
# Conflicts: # packages/client/src/launchdarkly_ai_server/evaluations/runner.py
apucacao
approved these changes
Oct 27, 2026
apucacao
left a comment
Contributor
There was a problem hiding this comment.
Approving based on the provided evidence. 👍 This is cool!
ccschmitz-launchdarkly
deleted the
ccschmitz/offline-eval-conversation-spans-17b3
branch
October 27, 2026 15:16
Merged
apucacao
pushed a commit
that referenced
this pull request
Oct 27, 2026
🤖 I have created a release *beep* *boop* --- <details><summary>launchdarkly-ai-server: 0.5.0</summary> ## [0.5.0](launchdarkly-ai-server-0.4.0...launchdarkly-ai-server-0.5.0) (2026-10-27) ### ⚠ BREAKING CHANGES * **skills:** promote Agent Skills to core ([#210](#210)) * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Experimental * **evaluations:** export each offline row as one trace ([#170](#170)) ([fc241df](fc241df)) * **evaluations:** normalize text behaviors ([7cee8c8](7cee8c8)) ### Features * **skills:** export the Claude Agents skills handler from the package root ([#217](#217)) ([5d46dbb](5d46dbb)) * **skills:** promote Agent Skills to core ([#210](#210)) ([715815f](715815f)) ### Bug Fixes * **client:** show a judge an output of 0 or false, and render non-string values as JSON ([7cee8c8](7cee8c8)) * **client:** strip whitespace from LD_BASE_URI, LD_STREAM_URI and LD_EVENTS_URI in init_client ([1629123](1629123)) * **judges:** a judge config's outputFormat must not reach the provider ([#86](#86)) ([d8b893d](d8b893d)) * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) * **skills:** coalesce a watcher's debounce window into one reconcile ([#215](#215)) ([b214bbd](b214bbd)) * **skills:** default FDv2SkillStore endpoints from LD_BASE_URI and LD_STREAM_URI ([1629123](1629123)) </details> <details><summary>launchdarkly-ai-python: 0.4.0</summary> ## [0.4.0](launchdarkly-ai-python-0.3.0...launchdarkly-ai-python-0.4.0) (2026-10-27) ### ⚠ BREAKING CHANGES * **skills:** promote Agent Skills to core ([#210](#210)) ### Features * **skills:** promote Agent Skills to core ([#210](#210)) ([715815f](715815f)) </details> <details><summary>launchdarkly-ai-claude-agents: 0.3.0</summary> ## [0.3.0](launchdarkly-ai-claude-agents-0.2.6...launchdarkly-ai-claude-agents-0.3.0) (2026-10-27) ### ⚠ BREAKING CHANGES * **skills:** promote Agent Skills to core ([#210](#210)) * **claude-agents:** switch the built-ins off by default and load no host settings ([#201](#201)) * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Features * **skills:** export the Claude Agents skills handler from the package root ([#217](#217)) ([5d46dbb](5d46dbb)) * **skills:** promote Agent Skills to core ([#210](#210)) ([715815f](715815f)) ### Bug Fixes * **claude-agents:** switch the built-ins off by default and load no host settings ([#201](#201)) ([f99d538](f99d538)) * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-claude-messages: 0.3.0</summary> ## [0.3.0](launchdarkly-ai-claude-messages-0.2.5...launchdarkly-ai-claude-messages-0.3.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-openai-agents: 0.3.0</summary> ## [0.3.0](launchdarkly-ai-openai-agents-0.2.6...launchdarkly-ai-openai-agents-0.3.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-vercel-agents: 0.2.0</summary> ## [0.2.0](launchdarkly-ai-vercel-agents-0.1.1...launchdarkly-ai-vercel-agents-0.2.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-litellm-agents: 0.2.0</summary> ## [0.2.0](launchdarkly-ai-litellm-agents-0.1.1...launchdarkly-ai-litellm-agents-0.2.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-openai-messages: 0.3.0</summary> ## [0.3.0](launchdarkly-ai-openai-messages-0.2.5...launchdarkly-ai-openai-messages-0.3.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-vercel-messages: 0.2.0</summary> ## [0.2.0](launchdarkly-ai-vercel-messages-0.1.1...launchdarkly-ai-vercel-messages-0.2.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-litellm-messages: 0.2.0</summary> ## [0.2.0](launchdarkly-ai-litellm-messages-0.1.1...launchdarkly-ai-litellm-messages-0.2.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-langchain-agents: 0.3.0</summary> ## [0.3.0](launchdarkly-ai-langchain-agents-0.2.6...launchdarkly-ai-langchain-agents-0.3.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-langchain-messages: 0.3.0</summary> ## [0.3.0](launchdarkly-ai-langchain-messages-0.2.5...launchdarkly-ai-langchain-messages-0.3.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-opencode-agents: 0.3.0</summary> ## [0.3.0](launchdarkly-ai-opencode-agents-0.2.0...launchdarkly-ai-opencode-agents-0.3.0) (2026-10-27) ### ⚠ BREAKING CHANGES * **opencode-agents:** honor AI Config tools ([#216](#216)) * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Experimental * **evaluations:** normalize text behaviors ([7cee8c8](7cee8c8)) ### Features * **opencode-agents:** honor AI Config tools ([#216](#216)) ([b5a63ec](b5a63ec)) ### Bug Fixes * **client:** show a judge an output of 0 or false, and render non-string values as JSON ([7cee8c8](7cee8c8)) * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> <details><summary>launchdarkly-ai-typesafe: 0.2.0</summary> ## [0.2.0](launchdarkly-ai-typesafe-0.1.1...launchdarkly-ai-typesafe-0.2.0) (2026-10-27) ### ⚠ BREAKING CHANGES * handlers now forward the AI Config's model parameters to the provider, limited to each handler's list in TESTING.md 1.12. Configs that set parameters which used to be ignored now take effect. ### Bug Fixes * pass AI Config model parameters through to every provider handler ([#107](#107)) ([e3afb3f](e3afb3f)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Overview** > This is a **Release Please** cut that bumps versions across the monorepo (notably `launchdarkly-ai-server` **0.5.0**, `launchdarkly-ai-python` **0.4.0**, and matching minor bumps on provider adapters). The edits are manifest entries, `pyproject.toml` / `__version__` strings, and new **CHANGELOG** sections for 2026-10-27. > > The release notes capture several **breaking** runtime changes already on `main`: **Agent Skills** move from experimental to core (`launchdarkly_ai_server.skills`), **AI Config model parameters** are now forwarded to every provider handler (configs that previously ignored them will behave differently), **Claude Agents** defaults built-in tools off and stops loading host settings, and **OpenCode Agents** now honor AI Config tools. The core client also documents judge fixes (`outputFormat` not sent to providers), URI trimming in `init_client`, skills watcher/store fixes, and experimental evaluation trace export. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 4138892. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

EvaluationsModule.runnow exports each dataset row as one trace, on the tracer providerinit_clientalready registers. The$ld:ai:offline-evals:generationand:criterionevents are unchanged.Spec: launchdarkly/ai-sdks-monorepo#60 (
TESTING.md§8.10). Frontend: launchdarkly/gonfalon#74117.What each row exports
gen_aioperation, so the conversation view treats it as an envelope. Its status is ERROR when the handler raised.chatandexecute_toolspans itself. It does so only when the handler opened no SDK span, so nothing is traced twice.evaluatespan.capture_contentgate, which is off by default. There is no separate evaluation switch.Where the code lives
Core
conversation.pygains two primitives that don't know about evaluations:stamp_span_attributes(write-if-absent attributes on SDK spans in a block) andcount_sdk_spans. Everything evaluation-specific is inevaluations/spans.py.Verified on staging
Project
default, envai-o-11-y, with a plain-function handler and thelookup_capitaltool. Each run produced one trace with the five spans above andpassed=1.enable-evaluation-run-conversation-spansis still off in that environment, so the run page shows the synthetic waterfall. The trace links show the exported spans.Known gaps
generation_incompletecriterion event for a failed row. §8.8.6 tracks that separately.gen_ai.system_instructionsas its raw JSON part array.EvaluationsModule.runnow exports each dataset row as one trace, on the tracer providerinit_clientalready registers. The$ld:ai:offline-evals:generationand:criterionevents are unchanged.Spec: launchdarkly/ai-sdks-monorepo#60 (
TESTING.md§8.10). Frontend: launchdarkly/gonfalon#74117.What each row exports
gen_aioperation, so the conversation view treats it as an envelope. Its status is ERROR when the handler raised.chatandexecute_toolspans itself. It does so only when the handler opened no SDK span, so nothing is traced twice.evaluatespan.capture_contentgate, which is off by default. There is no separate evaluation switch.Where the code lives
Core
conversation.pygains two primitives that don't know about evaluations:stamp_span_attributes(write-if-absent attributes on SDK spans in a block) andcount_sdk_spans. Everything evaluation-specific is inevaluations/spans.py.Verified on staging
Project
default, envai-o-11-y, with a plain-function handler and thelookup_capitaltool. Each run produced one trace with the five spans above andpassed=1.Trace search defaults to the last 15 minutes, which no longer covers these runs. The trace links set
startDateandendDateand do not setrelativeTime. Each window is the root span, padded by 15 minutes on either side. The run page's conversation query omits its own window and lets the backend resolve the span range, so those links do not carry a time bound.2026-10-22T21:10:38.640Z,1600467ns. The tree, model, usage, tool name, and score are present. No content attributes.2026-10-22T21:10:38.740Z,2044814ns. Input and output messages, tool arguments and results, the judge prompt and completion, and the explanation are all present.enable-evaluation-run-conversation-spansis still off in that environment, so the run page shows the synthetic waterfall. The trace links show the exported spans. Preview is gonfalon#74117 atc497293cd.Known gaps
generation_incompletecriterion event for a failed row. §8.8.6 tracks that separately.gen_ai.system_instructionsas its raw JSON part array.