fix: preserve AG-UI reasoning message lifecycle - #942
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes the AG-UI hosting event converter so that reasoning and assistant text are emitted as distinct, correctly-ordered AG-UI message lifecycles, while also preserving a stable message ID across streaming deltas that omit ResponseUpdate.MessageID.
Changes:
- Track reasoning vs text as separate logical streams, allocate stable message IDs, and emit a complete
REASONING_START→REASONING_ENDlifecycle (closing reasoning before emitting text-like content). - Refactor “text-like” detection into a single helper used consistently for lifecycle decisions.
- Add handler-level regression tests covering mixed reasoning+text in a single update and stable IDs across no-messageID deltas.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| provider/aguiprovider/hosting_events.go | Reworks update-to-event conversion to manage reasoning/text lifecycles separately with stable ID allocation and explicit reasoning start/end closure. |
| provider/aguiprovider/hosting_test.go | Adds SSE decoding helpers and new regression tests asserting ordered lifecycles and stable/distinct message IDs. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Parity Review — AG-UI Reasoning Message Lifecycle FixScope: user-visible behavior (streaming AG-UI event sequence)
Result: aligned Parity AssessmentThe Go PR aligns well with the Python upstream behavior in
No exported API surface changed, so the
|
Summary
ResponseUpdate.MessageIDREASONING_START/REASONING_ENDlifecycleWhy
Responses providers can produce a single update containing both
TextReasoningContentandTextContentunder one upstream message ID. The previous converter pre-opened both AG-UI messages with that same ID, so clients keyed by message ID could merge visible reasoning into the assistant answer. Updates without a message ID also received a fresh ID per delta, fragmenting a single stream into many messages.The converter now tracks reasoning and text as separate logical streams and processes content in emission order, matching the Python Agent Framework AG-UI adapter behavior.
Testing
go test ./provider/aguiprovidergo vet ./provider/aguiprovidergo test ./...Added handler-level regressions for mixed reasoning/text updates and no-ID reasoning/text deltas.