feat!: Add ManagedResult, RunnerResult, and Runner protocol; rename invoke() to run()#148
Open
jsonbailey wants to merge 13 commits intomainfrom
Open
feat!: Add ManagedResult, RunnerResult, and Runner protocol; rename invoke() to run()#148jsonbailey wants to merge 13 commits intomainfrom
jsonbailey wants to merge 13 commits intomainfrom
Conversation
b0ca696 to
d403590
Compare
a564649 to
bd4cd68
Compare
bd4cd68 to
45441da
Compare
a997b91 to
d0b3436
Compare
45441da to
27bcfc0
Compare
d0b3436 to
e56f69a
Compare
27bcfc0 to
ff47ec2
Compare
jsonbailey
commented
Apr 29, 2026
369242d to
b8d3fad
Compare
…nvoke() to run() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
b8d3fad to
4e28ae6
Compare
The new track_tool_calls method at line 413 (with summary storage and dedup guard) was being shadowed by the older method at line 559 (which only fired per-tool events). Merge them into a single method that both stores to the summary and fires per-tool events.
7352a34 to
adfd9f0
Compare
Previously, metrics_extractor(result) was called twice — once in the public track_metrics_of/track_metrics_of_async to read duration_ms, and again inside _track_from_metrics_extractor to track success, tokens, and tool calls. Extract metrics once in the public method and pass the resulting metrics + elapsed_ms into the private helper, which now also handles the duration tracking.
adfd9f0 to
b4d15df
Compare
ManagedModel and ManagedAgent now require a Runner. The compat shims (_invoke_runner, isinstance(result, RunnerResult) branches, Union type annotations) are removed; result handling is direct on RunnerResult fields. The deprecated ManagedModel.invoke() is preserved for backwards compat but now delegates to run() and adapts the ManagedResult into the legacy ModelResponse shape. ModelRunner and AgentRunner protocol definitions remain in place so downstream provider packages that import them continue to work.
- Drop the inconsistent 'if metrics else None' guard on reported_ms; the next line already dereferences metrics.success unconditionally. - Use 'is not None' for tool_calls so an explicit empty list still triggers tracking (preserves the distinction between 'not tracked' and 'tracked with no calls').
Drop the deprecated invoke() method from the managed layer along with its dedicated test class and the warnings/LDAIMetrics/ModelResponse imports that were only needed by it. Type definitions in providers/ remain so downstream provider packages keep building.
…unner] The factory's downstream consumers (ManagedModel, ManagedAgent) now take Runner; aligning the factory's return types lets us drop the type: ignore comments at the ManagedModel/ManagedAgent call sites. Provider package PRs will update their concrete implementations to match. Judge still takes ModelRunner, so its call site picks up the type: ignore[arg-type] in its place — that's resolved later in the cleanup PR when Judge migrates to Runner.
Move the metrics_extractor call inside _track_from_metrics_extractor so extraction errors are caught and logged without bubbling up. When extraction fails or returns None, only the wall-clock duration is tracked — success/error is left untouched since the underlying model call itself succeeded. Also tighten the tool_calls check to access metrics.tool_calls directly, mirroring how metrics.usage is accessed.
keelerm84
approved these changes
Apr 30, 2026
- Judge now accepts Runner instead of ModelRunner - evaluate() calls runner.run(output_type=...) instead of invoke_structured_model - response.parsed replaces StructuredResponse.data; None guard added - evaluate_messages() accepts RunnerResult instead of ModelResponse - Tests updated to use RunnerResult and mock_runner.run Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2 tasks
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes 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 4d86c9c. Configure here.
…ics]], remove defensive getattr
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.

Summary
Introduces the new managed-layer return type `ManagedResult`, the unified `Runner` protocol, and extends `LDAIMetricSummary` with `tool_calls`, `duration_ms` (renamed from `duration`), and `resumption_token`.
Stack
This is part of the AIC-2388 stacked PR series. Targets `main` (PR #147 merged).
Order: PR 7 ✅ → PR 8 (this) → PR 8-openai → PR 8-langchain → Cleanup → PR 9 → PR 10 → PR 11 → PR 11-openai → PR 11-langchain → PR 12
Test plan
🤖 Generated with Claude Code
Note
Medium Risk
Breaking API surface changes (
invoke()removed/renamed, new result types) that ripple to all SDK consumers and provider implementations; runtime behavior is mostly unchanged but type/contract mismatches could cause integration failures.Overview
Introduces a unified
Runnerprotocol and new result types: provider-levelRunnerResult(with optionalparsedstructured output) and managed-layerManagedResult(adds aggregatedLDAIMetricSummaryand optional async judgeevaluations).Updates the managed APIs to use the new runner contract:
ManagedModel.invoke()is replaced byManagedModel.run()returningManagedResult,ManagedAgent.run()now returnsManagedResult, andJudgenow callsRunner.run(..., output_type=...)and evaluates fromRunnerResultcontent/parsed output.Extends metrics/tracking by adding
tool_callsandduration_mstoLDAIMetrics, addingtool_calls,duration_ms(deprecatingduration), andresumption_tokentoLDAIMetricSummary, and enhancingLDAIConfigTracker.track_metrics_of(_async)to prefermetrics.duration_msand automatically emit per-tool$ld:ai:tool_callevents whentool_callsare present; tests and exports are updated accordingly.Reviewed by Cursor Bugbot for commit cc792ec. Bugbot is set up for automated code reviews on this repo. Configure here.