Skip to content

feat(evaluations): return tool errors to the model and mark eval spans for viewers - #203

Merged
ccschmitz-launchdarkly merged 1 commit into
mainfrom
ccschmitz/eval-tool-errors-row-envelope
Nov 5, 2026
Merged

ccschmitz-launchdarkly merged 1 commit into
mainfrom
ccschmitz/eval-tool-errors-row-envelope

Conversation

@ccschmitz-launchdarkly

@ccschmitz-launchdarkly ccschmitz-launchdarkly commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Why

This brings launchdarkly/python-ai-sdk#271 to TypeScript. Two problems came up running offline evals against staging. A tool that threw failed the whole row, so an eval couldn't test how an agent recovers from a broken tool. The Trace panel also couldn't show a failed row as a failed run, or show a score against its range.

Summary

  • evaluations-tools.ts returnToolErrors: wraps the row's tools outside the trajectory recorder. A throwing tool (sync, async, or one that returns a promise) returns "Error: <type>: <message>" to the model and the row continues. Sync tools stay sync. The recorder still logs the call as an error, so judges and execute_tool spans see it. Native tools pass through.
  • EvalTool constructor docs: the implementation gets one object of the model's arguments. What it returns goes back as the tool result, and a throw becomes the error result.
  • recordEvaluationOnSpan takes an optional scoreRange. Offline criteria pass [0, 1], which adds launchdarkly.evaluation.score.min / .max to gen_ai.evaluation.result and to the span. Online judges are unchanged.
  • startRowSpan sets gen_ai.operation.name=invoke_workflow.

Testing

  • New evaluations-tool-errors.test.ts: sync and async throws, the recorder still records the error, working and native tools are unchanged, and a non-Error throw. Span tests now assert invoke_workflow on the row root and the range on result events. The existing failed-tool test asserts the handler receives the error result.
  • packages/client: 2,194 tests pass. Typecheck, biome check, build and yarn api:check are clean.

Notes

  • Behavior change: a throwing tool no longer fails the row. Handler and model errors still do.
  • Merge order: merge after launchdarkly/gonfalon#77091, as with the Python PR. Until then the conversation header counts the invoke_workflow root as an extra LLM call.

Note

Overview
Offline eval rows no longer abort when an inline tool throws. returnToolErrors wraps each row’s tool map (outside the trajectory recorder) so sync throws, async rejections, and promise failures become "Error: <type>: <message>" tool results for the handler/model while the recorder still logs tool_error on execute_tool spans. Handler and model failures still fail the row.

Trace UX improvements: the dataset row root now sets gen_ai.operation.name=invoke_workflow, and offline criterion results add launchdarkly.evaluation.score.min / .max (0–1) on gen_ai.evaluation.result events and mirrored span attributes via an optional scoreRange on recordEvaluationOnSpan. Online judges are unchanged.

EvalTool docs now describe the single-args-object calling convention and throw-to-error-result behavior. New unit tests cover returnToolErrors / toolErrorResult; span tests assert the envelope operation name, score range (including when content capture is off), and that handlers receive the error string on failed tools.

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

…s for viewers

A throwing tool in an offline eval row now answers the model with
"Error: <type>: <message>" instead of failing the row; the trajectory
recorder still records the error. Row roots set
gen_ai.operation.name=invoke_workflow, and criterion results carry
launchdarkly.evaluation.score.min/max (0-1). Ports
launchdarkly/python-ai-sdk#271.
@ccschmitz-launchdarkly
ccschmitz-launchdarkly marked this pull request as ready for review November 4, 2026 17:43
@ccschmitz-launchdarkly
ccschmitz-launchdarkly merged commit 954fc69 into main Nov 5, 2026
14 checks passed
@ccschmitz-launchdarkly
ccschmitz-launchdarkly deleted the ccschmitz/eval-tool-errors-row-envelope branch November 5, 2026 01:21
@github-actions github-actions Bot mentioned this pull request Nov 5, 2026
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.

2 participants