Skip to content

fix(python-sdk): align ReasoningMessageStartEvent.role with TypeScript SDK - #1193

Merged
AlemTuzlak merged 1 commit into
mainfrom
fix/issue-1169-reasoning-role-mismatch
Apr 2, 2026
Merged

AlemTuzlak merged 1 commit into
mainfrom
fix/issue-1169-reasoning-role-mismatch

Conversation

@NathanTarbert

@NathanTarbert NathanTarbert commented Feb 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #1169

  • Changed ReasoningMessageRole from Literal["assistant"] to Literal["reasoning"] in the Python SDK's events.py
  • This aligns the Python SDK with the TypeScript SDK, which uses z.literal("reasoning") for the same field
  • Both SDKs already agreed on role: "reasoning" in their ReasoningMessage type definitions — only the Python event definition was out of sync

Root Cause

The Python SDK's ReasoningMessageStartEvent defined role as Literal["assistant"] (line 284 of events.py), while the TypeScript SDK defined it as z.literal("reasoning") (line 255 of events.ts). This made the two SDKs wire-incompatible: a Python backend emitting REASONING_MESSAGE_START with role="assistant" would be rejected by the TypeScript client's Zod parser, which expects "reasoning".

Changes

  • sdks/python/ag_ui/core/events.py (line 284): Changed ReasoningMessageRole = Literal["assistant"] to ReasoningMessageRole = Literal["reasoning"]
  • sdks/python/tests/test_events.py: Added two regression tests:
    • test_reasoning_message_start_event_role_is_reasoning — verifies creation, serialization, and deserialization with role="reasoning"
    • test_reasoning_message_start_event_rejects_assistant_role — verifies that role="assistant" is now rejected with a ValidationError

Test plan

  • New tests fail before the fix (confirmed: role="reasoning" rejected by Literal["assistant"])
  • New tests pass after the fix
  • Full Python SDK test suite passes (64 tests, 0 failures)
  • CI passes

@NathanTarbert
NathanTarbert requested a review from a team as a code owner February 27, 2026 19:02
@vercel

vercel Bot commented Feb 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ag-ui-dojo Ready Ready Preview, Comment Apr 2, 2026 10:58am

Request Review

@pkg-pr-new

pkg-pr-new Bot commented Feb 27, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@ag-ui/a2a-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2a-middleware@1193

@ag-ui/a2ui-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2ui-middleware@1193

@ag-ui/mcp-apps-middleware

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mcp-apps-middleware@1193

@ag-ui/middleware-starter

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/middleware-starter@1193

@ag-ui/a2a

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/a2a@1193

@ag-ui/adk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/adk@1193

@ag-ui/ag2

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/ag2@1193

@ag-ui/agno

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/agno@1193

@ag-ui/aws-strands

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/aws-strands@1193

@ag-ui/claude-agent-sdk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/claude-agent-sdk@1193

@ag-ui/crewai

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/crewai@1193

@ag-ui/langchain

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langchain@1193

@ag-ui/langgraph

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langgraph@1193

@ag-ui/langroid

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/langroid@1193

@ag-ui/llamaindex

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/llamaindex@1193

@ag-ui/mastra

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/mastra@1193

@ag-ui/pydantic-ai

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/pydantic-ai@1193

@ag-ui/server-starter

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/server-starter@1193

@ag-ui/server-starter-all-features

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/server-starter-all-features@1193

@ag-ui/vercel-ai-sdk

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/vercel-ai-sdk@1193

create-ag-ui-app

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/create-ag-ui-app@1193

@ag-ui/client

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/client@1193

@ag-ui/core

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/core@1193

@ag-ui/encoder

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/encoder@1193

@ag-ui/proto

pnpm add https://pkg.pr.new/ag-ui-protocol/ag-ui/@ag-ui/proto@1193

commit: 7a5ad14

@NathanTarbert NathanTarbert left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Code Review — PR #1193

Verdict: Looks good to merge

This is a clean, minimal, and correct fix for the cross-SDK wire-incompatibility described in issue #1169.


Root Cause Confirmation

The issue is a straightforward type literal mismatch. The Python SDK defined ReasoningMessageRole = Literal["assistant"] while:

  • The TypeScript SDK uses z.literal("reasoning") for ReasoningMessageStartEventSchema.role
  • Both SDKs already agree that the ReasoningMessage type uses role: "reasoning"

So the Python event definition was the clear outlier. This PR correctly changes Literal["assistant"] to Literal["reasoning"], bringing the Python SDK in line with the TypeScript SDK and with the Python SDK's own ReasoningMessage type in types.py (line 144).

What's Good

  1. Minimal and scoped fix — exactly one line changed in production code (events.py L284), which is the right scope for this bug.
  2. Comment updated — the old comment # Text message role for reasoning messages (only assistant can reason) is replaced with a neutral # Text message role for reasoning messages, which is appropriate since the semantic meaning changed.
  3. Tests are well-structured:
    • test_reasoning_message_start_event_role_is_reasoning covers creation, serialization (model_dump), and deserialization (via TypeAdapter with camelCase JSON, simulating the TypeScript wire format). This is thorough.
    • test_reasoning_message_start_event_rejects_assistant_role is a good negative/regression test ensuring the old value is now properly rejected.
  4. PR description is accurate and complete — it clearly states the root cause, the change, and the test plan.

Minor Observations (non-blocking)

  1. No default value set: ReasoningMessageStartEvent.role has no default, unlike TextMessageStartEvent which defaults to "assistant". Since Literal["reasoning"] has only one possible value, setting role: ReasoningMessageRole = "reasoning" as a default would be a nice ergonomic improvement (users wouldn't need to pass role="reasoning" explicitly every time). However, this matches the current behavior (no default was set before either), so it is not a regression and could be a separate enhancement.

  2. CI status: The python check passes. There are two failing checks (build and dojo / langgraph-typescript) which appear to be pre-existing/unrelated failures (the build failure is in the TypeScript build pipeline, and langgraph-typescript is an integration test — neither should be affected by a one-line Python SDK type literal change).

Conclusion

The fix directly addresses the root cause, is minimal, introduces no regressions, and includes comprehensive tests. Ready to merge.

@danilagamma

Copy link
Copy Markdown

@NathanTarbert AGUI protocol defines role in Reasoning events as "assistant" (JS SDK docs, Python SDK docs)

What is the source of truth for role: reasoning?

@AlemTuzlak

Copy link
Copy Markdown
Contributor

@danilagamma the docs were wrong, the role is reasoning

@AlemTuzlak
AlemTuzlak force-pushed the fix/issue-1169-reasoning-role-mismatch branch from f51b2f5 to 7a5ad14 Compare April 2, 2026 10:55
…nt" to "reasoning"

The Python SDK defined ReasoningMessageRole as Literal["assistant"] while
the TypeScript SDK used z.literal("reasoning"), making the two SDKs
wire-incompatible. A Python backend emitting REASONING_MESSAGE_START with
role "assistant" would be rejected by the TypeScript client's Zod parser.

Both SDKs already agree that ReasoningMessage.role should be "reasoning"
(types.py L144, types.ts L104), so the Python event definition was the
one out of sync.

Fixes #1169
@github-actions

github-actions Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Python Preview Packages

Version 0.0.0.dev1775127364 published to TestPyPI.

Warning: These packages are built from contributor code that may not yet have been vetted for correctness or security. Install at your own risk and do not use in production.

Install with uv

Add the TestPyPI index to your pyproject.toml:

[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
explicit = true

Then install the packages you need:

# Core SDK
uv add 'ag-ui-protocol==0.0.0.dev1775127364' --index testpypi

# Integrations (each already depends on the matching ag-ui-protocol preview)
uv add 'ag-ui-langgraph==0.0.0.dev1775127364' --index testpypi
uv add 'ag-ui-crewai==0.0.0.dev1775127364' --index testpypi
# NOTE: ag-ui-agent-spec depends on pyagentspec (git-only, not on PyPI).
# You will need to install pyagentspec separately from its git repo.
uv add 'ag-ui-agent-spec==0.0.0.dev1775127364' --index testpypi
uv add 'ag_ui_adk==0.0.0.dev1775127364' --index testpypi
uv add 'ag_ui_strands==0.0.0.dev1775127364' --index testpypi

Install with pip

pip install \
  --index-url https://test.pypi.org/simple/ \
  --extra-index-url https://pypi.org/simple/ \
  ag-ui-protocol==0.0.0.dev1775127364

Use --extra-index-url https://pypi.org/simple/ so pip can resolve
transitive dependencies (pydantic, fastapi, etc.) from real PyPI.


Commit: 2ed2416

@AlemTuzlak
AlemTuzlak merged commit 7802d72 into main Apr 2, 2026
29 checks passed
@AlemTuzlak
AlemTuzlak deleted the fix/issue-1169-reasoning-role-mismatch branch April 2, 2026 11:03

This branch was successfully deployed

1 active deployment
Preview — 7a5ad141 Deployed Apr 2, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: ag-ui-protocol SDK mismatch: ReasoningMessageStartEvent.role — Python "assistant" vs TypeScript "reasoning"

3 participants