Skip to content

Python: Remove tool content returned after invocation limits - #7408

Merged
eavanvalkenburg merged 4 commits into
microsoft:mainfrom
eavanvalkenburg:python-function-limit-transcript-integrity
Jul 30, 2026
Merged

Python: Remove tool content returned after invocation limits#7408
eavanvalkenburg merged 4 commits into
microsoft:mainfrom
eavanvalkenburg:python-function-limit-transcript-integrity

Conversation

@eavanvalkenburg

@eavanvalkenburg eavanvalkenburg commented Jul 29, 2026

Copy link
Copy Markdown
Member

Motivation & Context

A provider can ignore tool_choice="none" after an invocation limit and return another local call that the framework
will not execute. Exposing that content leaves callers with an unanswered function call or local approval request.

Description & Review Guide

  • What are the major changes?
    • Remove locally actionable function calls and local approval requests returned after max_function_calls or max_iterations.
    • Preserve provider-executed informational call/result pairs and hosted approval requests.
    • Apply the filtering to streaming updates and finalized responses while preserving metadata-only updates.
    • Append the deterministic fallback without replacing retained provider transcript content.
    • Keep this PR's spec change to its unique scenario row; Python: Preserve declaration-only streaming metadata #7409 owns the shared gap and related-issue cleanup.
  • What is the impact of these changes?
    • Limit termination cannot expose an orphaned local tool call or approval prompt.
    • Provider-owned transcripts, hosted approvals, metadata, and finish information remain available to callers.
    • Streaming and non-streaming terminal behavior stay aligned.
    • Centralizing shared spec cleanup prevents repeated same-hunk conflicts as the focused PRs merge.
  • What do you want reviewers to focus on?
    • Filtering only locally actionable content after local tools are intentionally disabled.
    • Informational call/result atomicity, hosted approvals, metadata preservation, and fallback behavior.

Related Issue

Fixes #7045

Shared spec reconciliation is in #7409, which should merge after #7407 and #7408.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

Copilot AI review requested due to automatic review settings July 29, 2026 20:11
@agent-framework-automation agent-framework-automation Bot added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python labels Jul 29, 2026
@eavanvalkenburg
eavanvalkenburg marked this pull request as ready for review July 29, 2026 20:12
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _tools.py13688393%230–231, 408, 410, 423, 448–450, 458, 476, 490, 497, 504, 527, 529, 536, 544, 679, 713–715, 718–720, 722, 728, 779–781, 806, 832, 836, 874–876, 880, 1053, 1065, 1072–1075, 1096, 1104, 1118–1120, 1490, 1573, 1601, 1623, 1675–1676, 1733, 1780, 1787–1788, 1878, 1940–1941, 1971, 2067, 2081, 2084, 2097, 2100, 2123, 2130, 2139, 2143, 2168, 2202, 2270, 2299–2300, 2397, 2425, 2465, 2468, 2525, 2678, 2759, 3248
TOTAL46013447990% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
9510 34 💤 0 ❌ 0 🔥 1m 40s ⏱️

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the Python function-calling loop to prevent “orphaned” tool calls or approval requests from being surfaced to callers after the framework has intentionally disabled tool execution due to invocation limits. It aligns streaming and non-streaming behavior by filtering unexecutable tool-related content while preserving provider metadata updates and maintaining deterministic fallback behavior when no visible final content remains.

Changes:

  • Drop function_call and function_approval_request content from finalized responses once invocation limits disable tools, before applying the existing fallback logic.
  • Drop the same unexecutable tool content from streaming updates (while retaining metadata-only updates when present).
  • Add unit tests covering both max_function_calls and max_iterations for streaming and non-streaming paths, plus a metadata-preservation streaming case, and update specs/docs to reflect the new guarantee.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
python/packages/core/agent_framework/_tools.py Adds filtering helpers to remove unexecutable tool content from streamed updates and final responses after invocation limits disable tools, preserving metadata-only updates and existing fallback behavior.
python/packages/core/tests/core/test_function_invocation_logic.py Adds regression tests to ensure post-limit tool content is not exposed (streaming + non-streaming) and that metadata-only streaming updates remain visible after filtering.
python/packages/core/AGENTS.md Documents the new behavior that post-limit provider-emitted calls/approval requests are removed while metadata-only streaming updates remain visible.
docs/specs/004-python-function-calling-loop.md Updates the spec matrix to mark the #7045 scenario as covered by tests and calls out transcript integrity after limits.

Comment thread docs/specs/004-python-function-calling-loop.md Outdated
@eavanvalkenburg
eavanvalkenburg force-pushed the python-function-limit-transcript-integrity branch from bbb3ae2 to c62f2b2 Compare July 30, 2026 06:59
Comment thread python/packages/core/agent_framework/_tools.py Outdated
@eavanvalkenburg
eavanvalkenburg force-pushed the python-function-limit-transcript-integrity branch from c62f2b2 to 53729a9 Compare July 30, 2026 07:41
@eavanvalkenburg
eavanvalkenburg added this pull request to the merge queue Jul 30, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Jul 30, 2026
eavanvalkenburg and others added 3 commits July 30, 2026 10:20
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1ee1d250-d1e2-4c6f-8c36-aae0d94fe7a1
@eavanvalkenburg
eavanvalkenburg added this pull request to the merge queue Jul 30, 2026
Merged via the queue into microsoft:main with commit 0937233 Jul 30, 2026
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python

Projects

None yet

4 participants