Skip to content

feat: Introduce ManagedAgent and AgentRunner implementations#110

Open
jsonbailey wants to merge 8 commits intomainfrom
jb/aic-1664/managed-agent
Open

feat: Introduce ManagedAgent and AgentRunner implementations#110
jsonbailey wants to merge 8 commits intomainfrom
jb/aic-1664/managed-agent

Conversation

@jsonbailey
Copy link
Copy Markdown
Contributor

@jsonbailey jsonbailey commented Mar 25, 2026

feat: Add OpenAIAgentRunner with agentic tool-calling loop
feat: Add LangChainAgentRunner with agentic tool-calling loop
feat: Add OpenAIRunnerFactory.create_agent(config, tools) -> OpenAIAgentRunner
feat: Add LangChainRunnerFactory.create_agent(config, tools) -> LangChainAgentRunner
feat: Add ManagedAgent wrapper holding AgentRunner and LDAIConfigTracker
feat: Add LDAIClient.create_agent() returning ManagedAgent

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

Provide links to any issues in this repository or elsewhere relating to this pull request.

Describe the solution you've provided

Provide a clear and concise description of what you expect to happen.

Describe alternatives you've considered

Provide a clear and concise description of any alternative solutions or features you've considered.

Additional context

Add any other context about the pull request here.


Note

Medium Risk
Introduces a new managed agent execution path (LDAIClient.create_agent) and new provider-side agent runners, which changes how tool definitions, instructions, and token usage are interpreted/tracked. Risk is mainly around compatibility with provider SDKs (langchain / openai-agents) and correct tool/usage wiring rather than data/security concerns.

Overview
Adds first-class managed agent support to the server AI SDK via ManagedAgent and LDAIClient.create_agent(), enabling tracked agent-style invocations (instructions + tool calling) distinct from model and agent-graph flows.

Implements provider-side create_agent support for OpenAI and LangChain by introducing OpenAIAgentRunner (backed by openai-agents) and LangChainAgentRunner (backed by langchain.agents.create_agent), including tool binding/validation and aggregating token usage from agent runs.

Refactors token usage extraction to handle more response shapes (OpenAI chat completions vs agents RunResult, LangChain usage_metadata vs response_metadata) and centralizes native OpenAI tool mapping in openai_helper; updates tests accordingly and exports the new runners from provider packages.

Written by Cursor Bugbot for commit 268b669. This will update automatically on new commits. Configure here.

@jsonbailey jsonbailey changed the title feat: Introduce ManagedAgent and AgentRunner implementations feat: Introduce ManagedAgent and AgentRunner implementations (PR-5) Mar 25, 2026
@jsonbailey jsonbailey force-pushed the jb/aic-1664/managed-agent branch from c3f2da2 to bc8b945 Compare March 26, 2026 13:27
@jsonbailey jsonbailey changed the base branch from jb/aic-1664/runner-abcs to jb/aic-1664/graph-tracking-improvements March 26, 2026 13:28
@jsonbailey jsonbailey marked this pull request as ready for review March 26, 2026 13:28
@jsonbailey jsonbailey requested a review from a team as a code owner March 26, 2026 13:28
Copy link
Copy Markdown
Member

@keelerm84 keelerm84 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like bugbot has some good feedback on this one.

@jsonbailey jsonbailey force-pushed the jb/aic-1664/graph-tracking-improvements branch from 886e3b7 to a183f12 Compare March 26, 2026 17:49
Base automatically changed from jb/aic-1664/graph-tracking-improvements to main March 26, 2026 18:51
@jsonbailey jsonbailey force-pushed the jb/aic-1664/managed-agent branch from bc8b945 to c1b87a6 Compare March 26, 2026 19:20
@jsonbailey jsonbailey changed the title feat: Introduce ManagedAgent and AgentRunner implementations (PR-5) feat: Introduce ManagedAgent and AgentRunner implementations Mar 26, 2026
jsonbailey and others added 5 commits March 30, 2026 10:17
feat: Add OpenAIAgentRunner with agentic tool-calling loop
feat: Add LangChainAgentRunner with agentic tool-calling loop
feat: Add OpenAIRunnerFactory.create_agent(config, tools) -> OpenAIAgentRunner
feat: Add LangChainRunnerFactory.create_agent(config, tools) -> LangChainAgentRunner
feat: Add ManagedAgent wrapper holding AgentRunner and LDAIConfigTracker
feat: Add LDAIClient.create_agent() returning ManagedAgent
…ider helper tests

feat: add TestGetAIUsageFromResponse and TestGetToolCallsFromResponse test coverage for LangChainHelper
feat: add TestGetAIUsageFromResponse test coverage for OpenAIHelper
fix: update ManagedAgent.invoke to use track_metrics_of_async
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jsonbailey jsonbailey force-pushed the jb/aic-1664/managed-agent branch from e4b3830 to afe344e Compare March 30, 2026 16:13
@jsonbailey jsonbailey requested a review from keelerm84 March 30, 2026 19:20
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.


total = getattr(usage, 'total_tokens', None) or 0
inp = getattr(usage, 'input_tokens', None) or getattr(usage, 'prompt_tokens', None) or 0
out = getattr(usage, 'output_tokens', None) or getattr(usage, 'completion_tokens', None) or 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Falsy or-chain conflates zero tokens with missing attribute

Low Severity

The or-chain in get_ai_usage_from_response uses Python truthiness to fall through attribute lookups: getattr(usage, 'input_tokens', None) or getattr(usage, 'prompt_tokens', None) or 0. Because 0 is falsy, a legitimate input_tokens = 0 is treated the same as a missing attribute, causing the chain to fall through and check prompt_tokens. If a future SDK version exposes both field names on the same usage object, a zero input_tokens could incorrectly resolve to a non-zero prompt_tokens. Using is None checks instead of or would correctly distinguish "zero" from "absent."

Fix in Cursor Fix in Web

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