Skip to content

Python: preserve mixed-pause recovery invariants - #8518

Closed
RongJie G (CorgiBoyG) wants to merge 1 commit into
microsoft:mainfrom
CorgiBoyG:fix/post-8428-mixed-batch-safety
Closed

RongJie G (CorgiBoyG) wants to merge 1 commit into
microsoft:mainfrom
CorgiBoyG:fix/post-8428-mixed-batch-safety

Conversation

@CorgiBoyG

Copy link
Copy Markdown

Motivation & Context

A mixed batch containing approval-required and Host-owned calls can finish local execution before the provider accepts the result-delivery request. If that request is invalidated, clearing the completed batch immediately loses the only replayable copy even though the approved local tool has already run.

PR #8449 bounded stateless pause-response ownership to user turns and rejected direct conflicting occurrence-identified Host results. This change builds on that merged work and closes the remaining #8436 gaps: stateful identified/id-less correlation, handling of extra Host replays, and recovery when provider result delivery is invalidated.

Description & Review Guide

  • What are the major changes?

    • Keep a serializable provider outbox until result delivery succeeds, then clear it.
    • Replay stored Host and local results without re-authorizing or re-executing approved tools.
    • Preserve charged invocation budgets across invalidation and session serialization, including cross-process duration rebasing and fail-closed validation of malformed state.
    • Match occurrence-identified Host results before id-less compatibility results when a call_id is reused.
    • Deduplicate equivalent extra Host replays only when they can be attributed to active Host occurrences, and reject conflicting extra responses before provider delivery.
    • Preserve provider continuation rollback for framework-created, non-authoritative sessions without granting them approval authority.
    • Update the function-calling specification, provider-invalidation decision record, core contributor guidance, and regression coverage.
  • What is the impact of these changes?

    • Approved local tool results are replayed after provider invalidation without re-running the tool.
    • Streaming and non-streaming paths use the same serializable outbox recovery flow.
    • Reused call_id batches no longer remain pending or forward contradictory/orphaned Host results.
    • Completed historical stateless batches remain inert under later identifier reuse.
    • No public API signatures change.
  • What do you want reviewers to focus on?

    • The outbox lifecycle: persist before provider delivery, retain on invalidation, and clear only after success.
    • The boundary between authoritative approval state and continuation cleanup.
    • How id-less Host replays are deduplicated without consuming an approval result.
    • The serialized duration-budget validation and fail-closed behavior.

Related Issue

Fixes #8436

Built on #8449, which has already been merged.

Validation

Run from python/:

  • uv run pytest packages/core/tests -q
  • uv run pytest packages/ag-ui/tests -q (1367 passed, 14 skipped)
  • uv run pytest packages/declarative/tests -q
  • uv run pytest packages/foundry_hosting/tests -q
  • uv run ruff check packages/core/agent_framework/_tools.py packages/core/tests/core/test_function_invocation_logic.py
  • uv run ruff format --check packages/core/agent_framework/_tools.py packages/core/tests/core/test_function_invocation_logic.py
  • uv run pyright packages/openai packages/core/agent_framework packages/core/tests/core/test_function_invocation_logic.py (0 errors, 0 warnings)
  • git diff --check

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 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.

🟡 Changes recommended

Cross-turn equal-result correlation can remain permanently pending, and malformed restored error counters can weaken the configured failure limit.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds reliable recovery for mixed approval/Host pause batches after provider invalidation.

Changes:

  • Persists and replays provider outboxes and invocation budgets.
  • Improves Host-result correlation and conflict handling.
  • Adds specifications, guidance, and regression coverage.
File summaries
File Description
python/packages/core/agent_framework/_tools.py Implements outbox recovery, budget restoration, and correlation logic.
python/packages/core/tests/core/test_function_invocation_logic.py Adds recovery and correlation tests.
python/packages/core/AGENTS.md Documents the outbox invariant.
docs/specs/004-python-function-calling-loop.md Updates function-loop requirements.
docs/decisions/0041-handle-provider-invalidated-responses.md Records the invalidation recovery decision.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread python/packages/core/agent_framework/_tools.py
Comment thread python/packages/core/agent_framework/_tools.py Outdated
@CorgiBoyG

Copy link
Copy Markdown
Author

Copilot review

@eavanvalkenburg

Copy link
Copy Markdown
Member

Closing this PR after full review because it combines two independent recovery problems and the provider-outbox portion needs revised input and streaming-delivery semantics. Please create two new PRs: one narrowly addressing #8573, and a separate draft addressing #8574. Reuse the relevant code and regression tests from this branch, but keep Host correlation separate from the durable outbox protocol; stack the outbox PR only if the correlation fix is a genuine prerequisite.

This branch was successfully deployed

1 active deployment
github-app-auth — 01b024f4 Deployed Sep 18, 2026 by CorgiBoyG via add_label #23304
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

Development

Successfully merging this pull request may close these issues.

Python: Mixed pause recovery can lose provider outbox state and mis-correlate Host results

3 participants