Repository navigation
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The extractor validation accepts detectable async callables despite its synchronous contract, allowing child tools to execute before extraction fails and potentially leaving an unawaited coroutine.
1 open issue
What changed in this PR
Adds configurable response extraction to Python’s BaseAgent.as_tool(), addressing the Python portion of #2796 while preserving the default concatenated-text behavior.
Changes:
- Adds
"all","last", and synchronous callable return modes. - Applies extraction after response completion and pending-input checks, without filtering streaming callbacks.
- Documents the API and adds tests for selection, validation, extraction errors, approvals, and consent.
| File | Description |
|---|---|
python/packages/core/tests/core/test_agents.py |
Tests return modes, edge cases, streaming observers, and pending-input safeguards. |
python/packages/core/AGENTS.md |
Documents extraction semantics and unchanged streaming and session behavior. |
python/packages/core/agent_framework/_agents.py |
Adds the parameter, validation, response selection, and API documentation. |
Review effort: Balanced
| if not callable(return_mode) and return_mode not in ("all", "last"): | ||
| raise ValueError('return_mode must be "all", "last", or a synchronous callable returning str.') |
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: No findings
Scope: full PR (1 commit(s)): 35e9b3ccb304
Model: gpt-5.6-sol
Overview
The PR adds opt-in response extraction while preserving the existing concatenated-text default. Pending-input checks remain ahead of extraction, session-state merging remains protected by finally, and focused tests cover built-in modes, custom extractors, streaming observers, invalid configuration, and approval/consent behavior. No Critical, High, or Medium defect introduced by the authoritative diff was established.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.

Motivation & Context
When an agent is used as a tool, its result currently contains the concatenated response text, potentially including intermediate commentary alongside the final answer. This can add unnecessary text to the calling agent's context.
This change lets callers select the final assistant message or provide custom text extraction without writing a separate delegation wrapper.
Description & Review Guide
Some design choices behind this proposed implementation:
"last"selects the last assistant message rather than the last message of any role, so a trailing tool result is not mistaken for the answer."", without falling back to earlier commentary. Falling back could present a progress message as the final answer.AgentResponsebut return a string. This supports advanced filtering while keeping structured artifact forwarding outside this change.These are proposed semantics, not assumptions of an agreed design. In particular, feedback on the meaning of
"last"and combining built-in modes and a callable in one parameter would be helpful.What are the major changes?
Adds an optional
return_modeparameter toBaseAgent.as_tool():"all": preserves the existingresponse.textbehavior and remains the default."last": returns the last assistant message's text, or""when no assistant message exists. Empty or non-text final assistant messages do not fall back to earlier commentary.Callable[[AgentResponse], str]: extracts text from the complete final response.Invalid modes fail before execution. Custom extractors must return a string, and extraction errors propagate through the existing tool execution path.
Adds documentation and tests covering selection, streaming observers, empty responses, invalid configuration, extraction errors, and pending approvals and consent.
Before and after:
What is the impact of these changes?
This is an opt-in, backward-compatible Python API addition. Selection applies to the completed tool result, both with and without a streaming callback. Streaming callbacks continue receiving all updates, and approval and other pending-input checks run before extraction. Child execution, session persistence, and
AgentResponse.textsemantics are unchanged. The .NET implementation is not modified.What do you want reviewers to focus on?
The proposed
"last"semantics, synchronous callable contract, and suitability of this API addition for the current release line.Related Issue
Fixes #2796 (Python implementation).
Submitted as a proposed implementation for design review. Explicit maintainer agreement is still pending; the issue also discusses the separate .NET API.
AI Assistance
AI assistance details: GitHub Copilot assisted with design, implementation, tests, documentation, validation, and this PR description.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.