Skip to content

[BREAKING] Python: Trim final FRC to match service storage#4803

Open
TaoChenOSU wants to merge 1 commit intomicrosoft:mainfrom
TaoChenOSU:taochen/python-implementation-of-4792
Open

[BREAKING] Python: Trim final FRC to match service storage#4803
TaoChenOSU wants to merge 1 commit intomicrosoft:mainfrom
TaoChenOSU:taochen/python-implementation-of-4792

Conversation

@TaoChenOSU
Copy link
Contributor

@TaoChenOSU TaoChenOSU commented Mar 19, 2026

Motivation and Context

Closes #4609

Description

Python implementation of .Net PR #4792

This change is a behavioral break, but only for very limited circumstances, e.g. when using function call termination.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

@TaoChenOSU TaoChenOSU self-assigned this Mar 19, 2026
@github-actions github-actions bot changed the title Trim final FRC to match service storage Python: Trim final FRC to match service storage Mar 19, 2026
@TaoChenOSU TaoChenOSU changed the title Python: Trim final FRC to match service storage [BREAKING] Python: Trim final FRC to match service storage Mar 19, 2026
@TaoChenOSU TaoChenOSU moved this to In Review in Agent Framework Mar 19, 2026
@markwallace-microsoft
Copy link
Member

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _agents.py3824787%466, 470, 525, 937, 974, 990, 1090–1094, 1150, 1178, 1372, 1388, 1390, 1403, 1409, 1445, 1447, 1456–1461, 1466, 1468, 1474–1475, 1482, 1484–1485, 1493–1494, 1497–1499, 1509–1514, 1518, 1523, 1525
   _types.py10518691%58, 67–68, 122, 127, 146, 148, 152, 156, 158, 160, 162, 180, 184, 210, 232, 237, 242, 246, 276, 686–687, 846–847, 1232, 1304, 1339, 1359, 1369, 1413, 1545–1547, 1737, 1828–1833, 1858, 2026, 2038, 2289, 2313, 2408, 2639, 2845, 2914, 2925, 2927–2931, 2933, 2936–2944, 2954, 3162–3164, 3167–3169, 3173, 3178, 3182, 3266–3268, 3297, 3351, 3374–3378, 3384
TOTAL27153322288% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
5290 20 💤 0 ❌ 0 🔥 1m 25s ⏱️

@TaoChenOSU TaoChenOSU marked this pull request as ready for review March 19, 2026 23:57
Copilot AI review requested due to automatic review settings March 19, 2026 23:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Aligns Python agent session history storage with service-side behavior by trimming trailing function-result content that is produced locally at termination (e.g., middleware/tool termination), mirroring the .NET behavior described in #4792 and addressing #4609.

Changes:

  • Add store_final_function_result_content run option to control whether trailing tool/function-result messages are stored in history.
  • Implement trimming logic in RawAgent to filter trailing tool-role messages that contain only function_result content before running after-run providers.
  • Add unit + integration coverage for filtering behavior across non-streaming and streaming runs.

Reviewed changes

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

File Description
python/packages/core/agent_framework/_agents.py Adds the filtering implementation and threads the new option through the agent run lifecycle before persisting history.
python/packages/core/agent_framework/_types.py Extends ChatOptions typing with the new store_final_function_result_content flag.
python/packages/core/tests/core/test_store_final_function_result_content.py Adds tests validating default filtering behavior, opt-out, and streaming behavior.

Comment on lines 1115 to 1118
opts = dict(options) if options else {}
existing_additional_args: dict[str, Any] = opts.pop("additional_function_arguments", None) or {}
store_final_frc: bool = opts.pop("store_final_function_result_content", False)

Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

store_final_function_result_content is only read from per-run options (via opts.pop(...)) and does not consider Agent.default_options. If a user sets this flag as a default option, it will (1) be ignored for filtering (ctx value remains False) and (2) be forwarded down to client.get_response() via co, potentially breaking clients that reject unknown options. Consider deriving the effective flag from the merged options (run overrides defaults), then removing it from the options dict passed to the client.

Copilot uses AI. Check for mistakes.
Comment on lines 3115 to +3120
# System/instructions
instructions: str

# History storage
store_final_function_result_content: bool

Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

store_final_function_result_content is included in ChatOptions, which is documented as “Common request settings for AI services”. This key is agent-side history-storage behavior (not a provider request parameter), so its presence in ChatOptions can mislead users/custom clients into passing it to client.get_response(). Consider clarifying in the comment/docs that this option is Agent-only and not forwarded to providers (or splitting non-provider run options into a separate TypedDict).

Copilot uses AI. Check for mistakes.
Comment on lines +164 to +166
with patch("agent_framework._tools.DEFAULT_MAX_ITERATIONS", 2):
agent = Agent(client=client, name="test-agent")
session = agent.create_session()
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

Tests cover per-run options={"store_final_function_result_content": ...} but don’t cover configuring this behavior via Agent(default_options=...). Given default_options is a common way to set run defaults, add a test to ensure the default is honored and that the flag is not forwarded to the underlying chat client options.

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

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

this can just be part of the test_function_invocation_logic.py test suite

instructions: str

# History storage
store_final_function_result_content: bool
Copy link
Member

Choose a reason for hiding this comment

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

is this common enough to have to be part of the core chat options? not sure I like that, it also is not really a service side setting, which is what is the target for the ChatOptions, so we might want to use client_kwargs for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: Inconsistent session states from MiddlewareTermination with store=False vs store=True

4 participants