Skip to content

Python: preserve unmapped Anthropic and Mistral finish reasons - #7850

Merged
Giles Odigwe (giles17) merged 1 commit into
microsoft:mainfrom
YashvantHange:python-preserve-unmapped-finish-reasons
Aug 25, 2026
Merged

Python: preserve unmapped Anthropic and Mistral finish reasons#7850
Giles Odigwe (giles17) merged 1 commit into
microsoft:mainfrom
YashvantHange:python-preserve-unmapped-finish-reasons

Conversation

@YashvantHange

Copy link
Copy Markdown
Contributor

Motivation & Context

AnthropicChatClient and MistralChatClient look their finish reason maps up without a default, so any provider value the map does not cover reaches the caller as finish_reason=None — indistinguishable from a response that carries no finish reason at all. Anthropic's model_context_window_exceeded and Mistral's error are both lost this way, silently: nothing is logged, no exception is raised, and the OTel gen_ai span records no finish reason for those turns.

#7105 already fixed this for ag-ui, bedrock, claude, core, github_copilot, ollama, and openai. These two packages were missed. (gemini has the same gap and is covered separately by #7836 / #7837.)

Description & Review Guide

  • What are the major changes?
    A module-level _map_finish_reason helper in each of the two clients that falls back to the raw provider value, wrapped in FinishReason(...) so it type-checks under each package's strict Pyright config. It replaces three inline lookups in the Anthropic client (_process_message, and the message_start and message_delta branches of _process_stream_event) and two in the Mistral client (_parse_response, _parse_chunk). Tests cover the unmapped value in both the non-streaming and streaming paths, plus regressions for the already-mapped values and the absent case.

  • What is the impact of these changes?
    Callers that previously saw finish_reason=None for an unmapped provider value now see the raw provider string. That is the normalization Python: Normalize chat finish reasons #7105 established and it is the documented contract of the type: FinishReasonLiteral is the four known values, while FinishReason is a NewType("FinishReason", str) explicitly documented as accepting any string for extensibility, exactly as bedrock, claude and ollama already emit. Nothing in the repo branches on finish_reason, ChatResponse does not validate it, and ChatTelemetryLayer already filters non-standard values back out before they reach OTel. Every value currently in the two maps keeps mapping exactly as it does today, and an absent reason stays None, so no existing behavior narrows.

  • What do you want reviewers to focus on?
    Whether the two new helpers should instead be instance methods, to match bedrock/gemini, rather than module-level functions next to their maps as they are here — and whether Anthropic's model_context_window_exceeded would be better mapped explicitly to length rather than passed through as the raw value.

Verified locally on both packages: poe syntax, poe pyright, poe test-typing (pyright, pyrefly, ty, mypy, zuban) and poe test are all clean. The new "unmapped is preserved" tests fail on main before the change.

Related Issue

Fixes #7849

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.

The Anthropic and Mistral chat clients looked their finish reason maps up
without a default, so any provider value the map did not cover was reported
to the caller as no finish reason at all. Anthropic's
model_context_window_exceeded and Mistral's error both disappeared this way.

Fall back to the raw provider value instead, the way the other provider
clients have since microsoft#7105. Every already-mapped value keeps mapping as
before, and an absent reason stays absent.

Fixes microsoft#7849

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

Preserves previously unmapped Anthropic and Mistral finish reasons across standard and streaming responses.

Changes:

  • Adds provider-specific finish-reason mapping helpers with raw-value fallbacks.
  • Applies fallback mapping across all response paths.
  • Adds regression coverage for mapped, unmapped, and absent reasons.

Reviewed changes

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

File Description
python/packages/anthropic/agent_framework_anthropic/_chat_client.py Preserves unmapped Anthropic stop reasons.
python/packages/anthropic/tests/test_anthropic_client.py Tests Anthropic mapping and streaming behavior.
python/packages/mistral/agent_framework_mistral/_chat_client.py Preserves unmapped Mistral finish reasons.
python/packages/mistral/tests/mistral/test_mistral_chat_client.py Tests Mistral mapped, unmapped, and absent reasons.

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

@giles17

Copy link
Copy Markdown
Contributor

/review

@github-actions

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/anthropic/agent_framework_anthropic
   _chat_client.py5423493%483, 486, 572, 709, 809, 843, 933, 972–973, 1051, 1053, 1083–1084, 1166–1168, 1172–1174, 1178–1181, 1216, 1332, 1342, 1394, 1542–1543, 1560, 1573, 1586, 1611–1612
packages/mistral/agent_framework_mistral
   _chat_client.py4621097%285, 287–289, 296, 300, 304, 307–308, 310
TOTAL48078449490% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
9725 36 💤 0 ❌ 0 🔥 2m 35s ⏱️

@github-actions github-actions Bot 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.

MAF Automated Review — Iteration 1

Result: No findings
Scope: full PR (1 commit(s)): f1c6f571aa84
Model: gpt-5.6-sol

Overview

The PR centralizes finish-reason normalization in both providers, preserving known mappings while passing through non-empty unknown values under the core extensible FinishReason contract. Streaming and non-streaming paths are covered, absent values remain None, and existing aggregation and tool-call behavior are unchanged. The added tests and established provider precedent prevent a publishable compatibility, architectural, or security concern.

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.

@giles17
Giles Odigwe (giles17) added this pull request to the merge queue Aug 24, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 24, 2026
@YashvantHange

Copy link
Copy Markdown
Contributor Author

Giles Odigwe (@giles17) can you put this in merge-queue again ?

Mohammed Sanaullah (sanaullahmohammed) pushed a commit to sanaullahmohammed/NexusOps that referenced this pull request Sep 3, 2026
Updated
[Microsoft.Agents.AI](https://github.com/microsoft/agent-framework) from
1.19.0 to 1.20.0.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.Agents.AI's
releases](https://github.com/microsoft/agent-framework/releases)._

## 1.20.0

## What's Changed
* .NET: Bump AWSSDK.Extensions.Bedrock.MEAI from 4.0.6.10 to 4.0.101.8
by @​dependabot[bot] in
microsoft/agent-framework#7829
* .NET: Stabilize Foundry recovery tests by @​rogerbarreto in
microsoft/agent-framework#7817
* .NET: fix: preserve Responses logprobs field by @​he-yufeng in
microsoft/agent-framework#5860
* .NET: Honor cancellation for Foundry-hosted workflow responses by
@​rogerbarreto with @​Copilot in
microsoft/agent-framework#7842
* .NET: Use Responses API for hosted web search in AG-UI by
@​rogerbarreto with @​Copilot in
microsoft/agent-framework#7843
* .NET: Bump Aspire.Hosting from 13.1.0 to 13.5.2 by @​dependabot[bot]
in microsoft/agent-framework#7826
* .NET: Suppress false positive Zip Slip alert by @​SergeyMenshykh in
microsoft/agent-framework#7858
* .NET: added Mem0Sharp integration for in-memory storage in agent
samples. by @​jihadkhawaja in
microsoft/agent-framework#7792
* .NET: Annotate DevUI aggregator static-analysis false positives by
@​SergeyMenshykh in
microsoft/agent-framework#7864
* .NET: Rename CommunityToolkit.VectorData.CosmosNoSql to AzureCosmosDB
by @​adamsitnik in
microsoft/agent-framework#7878
* .NET: chore: upgrades aspnet openapi dependency by @​baywet in
microsoft/agent-framework#7870
* .NET: Simplify A2A function tool samples by @​SergeyMenshykh in
microsoft/agent-framework#7861
* .NET: Bump Azure.AI.AgentServer.Invocations from 1.0.0-beta.5 to
1.0.0-beta.6 by @​dependabot[bot] in
microsoft/agent-framework#7886
* .NET: docs: updates the contributing information for CFS users by
@​baywet in microsoft/agent-framework#7869
* Bump CommunityToolkit.VectorData.InMemory from 1.0.0 to 1.0.1 by
@​dependabot[bot] in
microsoft/agent-framework#7888
* .NET: Remove retired OpenAI Assistants integration tests by
@​rogerbarreto in microsoft/agent-framework#7896
* .NET: Simplify A2A client-server sample by @​SergeyMenshykh in
microsoft/agent-framework#7891
* Bump Dapr.AI.Microsoft.Extensions from 1.18.4 to 1.18.5 by
@​dependabot[bot] in
microsoft/agent-framework#7889
* .NET: docs/workflow fileinput sample dotnet by @​baywet in
microsoft/agent-framework#7913
* .NET: Add timeout for wait-for-first-completion by @​westey-m in
microsoft/agent-framework#7911
* .NET: Fix duplicate Foundry AgentHost port binding by @​rogerbarreto
in microsoft/agent-framework#7932
* .NET: tests: removes dependency on fluent assersion because of
licensing concerns by @​baywet in
microsoft/agent-framework#7938
* .NET: docs(decisions): resolve duplicate ADR sequence numbers (0016,
0021, 0024) by @​jluocsa in
microsoft/agent-framework#6046
* .NET: Bump Azure.Core from 1.61.0 to 1.62.0 by @​dependabot[bot] in
microsoft/agent-framework#7954
* .NET: Improve Cosmos DB Emulator startup reliability by @​TheovanKraay
in microsoft/agent-framework#3932
* .NET: add public API analyzers by @​baywet in
microsoft/agent-framework#7935
* .NET: Update version for 1.20.0 release by @​SergeyMenshykh in
microsoft/agent-framework#7972

## New Contributors
* @​madanmishra1223 made their first contribution in
microsoft/agent-framework#7705
* @​YashvantHange made their first contribution in
microsoft/agent-framework#7850
* @​jihadkhawaja made their first contribution in
microsoft/agent-framework#7792
* @​adamsitnik made their first contribution in
microsoft/agent-framework#7878
* @​baywet made their first contribution in
microsoft/agent-framework#7870
* @​Namraa310806 made their first contribution in
microsoft/agent-framework#7901
* @​Sweetteabittersugar made their first contribution in
microsoft/agent-framework#7903
* @​shoemoney made their first contribution in
microsoft/agent-framework#7837
* @​jluocsa made their first contribution in
microsoft/agent-framework#6046

**Full Changelog**:
microsoft/agent-framework@dotnet-1.19.0...dotnet-1.20.0

Commits viewable in [compare
view](microsoft/agent-framework@dotnet-1.19.0...dotnet-1.20.0).
</details>

Updated
[Microsoft.Agents.AI.OpenAI](https://github.com/microsoft/agent-framework)
from 1.19.0 to 1.20.0.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.Agents.AI.OpenAI's
releases](https://github.com/microsoft/agent-framework/releases)._

## 1.20.0

## What's Changed
* .NET: Bump AWSSDK.Extensions.Bedrock.MEAI from 4.0.6.10 to 4.0.101.8
by @​dependabot[bot] in
microsoft/agent-framework#7829
* .NET: Stabilize Foundry recovery tests by @​rogerbarreto in
microsoft/agent-framework#7817
* .NET: fix: preserve Responses logprobs field by @​he-yufeng in
microsoft/agent-framework#5860
* .NET: Honor cancellation for Foundry-hosted workflow responses by
@​rogerbarreto with @​Copilot in
microsoft/agent-framework#7842
* .NET: Use Responses API for hosted web search in AG-UI by
@​rogerbarreto with @​Copilot in
microsoft/agent-framework#7843
* .NET: Bump Aspire.Hosting from 13.1.0 to 13.5.2 by @​dependabot[bot]
in microsoft/agent-framework#7826
* .NET: Suppress false positive Zip Slip alert by @​SergeyMenshykh in
microsoft/agent-framework#7858
* .NET: added Mem0Sharp integration for in-memory storage in agent
samples. by @​jihadkhawaja in
microsoft/agent-framework#7792
* .NET: Annotate DevUI aggregator static-analysis false positives by
@​SergeyMenshykh in
microsoft/agent-framework#7864
* .NET: Rename CommunityToolkit.VectorData.CosmosNoSql to AzureCosmosDB
by @​adamsitnik in
microsoft/agent-framework#7878
* .NET: chore: upgrades aspnet openapi dependency by @​baywet in
microsoft/agent-framework#7870
* .NET: Simplify A2A function tool samples by @​SergeyMenshykh in
microsoft/agent-framework#7861
* .NET: Bump Azure.AI.AgentServer.Invocations from 1.0.0-beta.5 to
1.0.0-beta.6 by @​dependabot[bot] in
microsoft/agent-framework#7886
* .NET: docs: updates the contributing information for CFS users by
@​baywet in microsoft/agent-framework#7869
* Bump CommunityToolkit.VectorData.InMemory from 1.0.0 to 1.0.1 by
@​dependabot[bot] in
microsoft/agent-framework#7888
* .NET: Remove retired OpenAI Assistants integration tests by
@​rogerbarreto in microsoft/agent-framework#7896
* .NET: Simplify A2A client-server sample by @​SergeyMenshykh in
microsoft/agent-framework#7891
* Bump Dapr.AI.Microsoft.Extensions from 1.18.4 to 1.18.5 by
@​dependabot[bot] in
microsoft/agent-framework#7889
* .NET: docs/workflow fileinput sample dotnet by @​baywet in
microsoft/agent-framework#7913
* .NET: Add timeout for wait-for-first-completion by @​westey-m in
microsoft/agent-framework#7911
* .NET: Fix duplicate Foundry AgentHost port binding by @​rogerbarreto
in microsoft/agent-framework#7932
* .NET: tests: removes dependency on fluent assersion because of
licensing concerns by @​baywet in
microsoft/agent-framework#7938
* .NET: docs(decisions): resolve duplicate ADR sequence numbers (0016,
0021, 0024) by @​jluocsa in
microsoft/agent-framework#6046
* .NET: Bump Azure.Core from 1.61.0 to 1.62.0 by @​dependabot[bot] in
microsoft/agent-framework#7954
* .NET: Improve Cosmos DB Emulator startup reliability by @​TheovanKraay
in microsoft/agent-framework#3932
* .NET: add public API analyzers by @​baywet in
microsoft/agent-framework#7935
* .NET: Update version for 1.20.0 release by @​SergeyMenshykh in
microsoft/agent-framework#7972

## New Contributors
* @​madanmishra1223 made their first contribution in
microsoft/agent-framework#7705
* @​YashvantHange made their first contribution in
microsoft/agent-framework#7850
* @​jihadkhawaja made their first contribution in
microsoft/agent-framework#7792
* @​adamsitnik made their first contribution in
microsoft/agent-framework#7878
* @​baywet made their first contribution in
microsoft/agent-framework#7870
* @​Namraa310806 made their first contribution in
microsoft/agent-framework#7901
* @​Sweetteabittersugar made their first contribution in
microsoft/agent-framework#7903
* @​shoemoney made their first contribution in
microsoft/agent-framework#7837
* @​jluocsa made their first contribution in
microsoft/agent-framework#6046

**Full Changelog**:
microsoft/agent-framework@dotnet-1.19.0...dotnet-1.20.0

Commits viewable in [compare
view](microsoft/agent-framework@dotnet-1.19.0...dotnet-1.20.0).
</details>

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: Anthropic and Mistral chat clients drop unmapped finish reasons

3 participants