Preserve inbound A2A message role instead of hardcoding assistant - #1122
PratikDhanave (PratikDhanave) wants to merge 2 commits into
Conversation
The client inbound path hardcoded message.RoleAssistant for A2A messages and task-status messages, discarding the actual A2A role. A peer message with the user role was reported as assistant. Map the role via a shared agentRole helper (agent -> assistant, otherwise user), matching the hosting-side toAgentMessage and the Python client. Artifacts carry no role and stay assistant.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Streaming task status messages can still report inbound user roles as assistant.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (2)
What changed in this PR
Preserves inbound A2A message roles when converting responses into framework messages.
Changes:
- Added shared A2A-to-framework role mapping.
- Applied role preservation to messages and task-status updates.
- Added a user-role response test.
| File | Description |
|---|---|
provider/a2aprovider/a2a.go |
Adds role mapping for inbound responses. |
provider/a2aprovider/a2a_test.go |
Tests preservation of user-role messages. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| role := message.RoleAssistant | ||
| if e.Status.Message != nil { | ||
| messageID = e.Status.Message.ID | ||
| role = agentRole(e.Status.Message.Role) |
| // A response message carrying the A2A user role must map to RoleUser, not be | ||
| // hardcoded to assistant, matching the Python client. | ||
| func TestRunPreservesInboundUserRole(t *testing.T) { |
This comment has been minimized.
This comment has been minimized.
Add a role assertion for the input-required task-status message path (yieldTask) so the user-role mapping cannot regress, and restore the TestRunWithValidUserMessage doc comment to its own test.
|
Scope: user-visible behavior (bug fix), internal-only (helper is unexported) Changed Go contract: No exported API added or changed. Observable behavior fix in Upstream evidence reviewed:
Result: aligned. This is a pure bug fix restoring parity with the existing Python client behavior (and the Go hosting-side mapping), with no exported API surface change. The No inline findings. No exported API changed, so
|


The client inbound path passed a literal
message.RoleAssistantfor A2A messages (*a2a.Message) and task-status messages, discarding the role carried on the inbound message. So a peer message with the A2A user role was reported as assistant.The hosting side already maps this (
toAgentMessage:agent→ assistant, otherwise user), and the Python client does the same (role="assistant" if msg.role == A2ARole.ROLE_AGENT else "user") — the client-path hardcode was an oversight.Change
agentRolehelper and use it for the*a2a.Messagecase and the two task-status-message cases (streamingTaskStatusUpdateEventandyieldTaskinput-required). Artifacts carry no role, so they stay assistant.Test
TestRunPreservesInboundUserRole: a response*a2a.MessagewithMessageRoleUsernow maps toRoleUser. Fails before (assistant), passes after. The existingMessageRoleAgent → assistantassertion still holds.