Skip to content

fix: respect A2A Message.role in inbound event conversion - #5224

Closed
giulio-leone wants to merge 2 commits into
google:mainfrom
giulio-leone:fix/a2a-inbound-role-mapping
Closed

giulio-leone wants to merge 2 commits into
google:mainfrom
giulio-leone:fix/a2a-inbound-role-mapping

Conversation

@giulio-leone

Copy link
Copy Markdown
Contributor

Summary

Fixes #5186.

convert_a2a_message_to_event() hard-coded role='model' on the GenAI Content it produced, ignoring the A2A Message.role field. This caused Role.user messages to be restored as model events.

Additionally, the task-history fallback in convert_a2a_task_to_event() (in event_converter.py) blindly took history[-1] without checking Message.role, so a trailing user message could be misattributed as agent output.

Root Cause

  • event_converter.py: Content(role="model", ...) was hard-coded in two places inside convert_a2a_message_to_event().
  • to_adk_event.py: _create_event() hard-coded role="model" with no way to override.
  • event_converter.py: convert_a2a_task_to_event() fallback path used a2a_task.history[-1] unconditionally.

Changes

File Change
converters/utils.py New a2a_role_to_genai_role() helper (Role.agent→"model", Role.user→"user")
converters/event_converter.py Use helper in convert_a2a_message_to_event(); filter history fallback to agent-role messages only
converters/to_adk_event.py Add role param to _create_event(); pass mapped role from convert_a2a_message_to_event()
test_event_converter.py Regression tests for role mapping + history fallback
test_to_adk.py Regression tests for role mapping
test_utils.py Unit tests for a2a_role_to_genai_role()

Testing

All 86 converter tests pass (test_event_converter.py, test_to_adk.py, test_utils.py).

@google-cla

google-cla Bot commented Apr 9, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@adk-bot

adk-bot commented Apr 9, 2026

Copy link
Copy Markdown
Collaborator

Response from ADK Triaging Agent

Hello @giulio-leone, thank you for creating this PR!

Before we can review your contribution, could you please sign our Contributor License Agreement (CLA)? You can find more information at https://cla.developers.google.com/.

Additionally, since this PR is a bug fix, could you please provide logs or a screenshot demonstrating that the fix is working as expected? This will help the reviewers to better understand and verify your changes.

Thank you!

@adk-bot adk-bot added the core [Component] This issue is related to the core interface and implementation label Apr 9, 2026
@giulio-leone

Copy link
Copy Markdown
Contributor Author

Added focused regression coverage for the fix:

  • test_event_converter.py: verifies Role.user is restored as user and that task-history fallback ignores trailing user messages
  • test_to_adk.py: verifies inbound event conversion preserves the mapped role
  • test_utils.py: verifies a2a_role_to_genai_role() mappings

Local result: 86 converter tests passed (test_event_converter.py, test_to_adk.py, test_utils.py).

This reproduces the original bug path and confirms that user-role messages are no longer misattributed as model output.

@giulio-leone
giulio-leone force-pushed the fix/a2a-inbound-role-mapping branch 2 times, most recently from 877d702 to f22ca7d Compare April 9, 2026 03:01
@rohityan rohityan self-assigned this Apr 9, 2026
@rohityan

Copy link
Copy Markdown
Collaborator

Hi @giulio-leone , Thank you for your contribution! We appreciate you taking the time to submit this pull request.
Please fix formatting errors by running autoformat.sh

@rohityan rohityan added the request clarification [Status] The maintainer need clarification or more information from the author label Apr 13, 2026
convert_a2a_message_to_event() hard-coded role='model' on the GenAI
Content it produced, ignoring the A2A Message.role field. This caused
Role.user messages to be misattributed as model output.

Additionally, the task-history fallback in convert_a2a_task_to_event()
blindly took history[-1] without checking Message.role, so a trailing
user message could be restored as agent output.

Changes:
- Add a2a_role_to_genai_role() helper in utils.py (Role.agent→'model',
  Role.user→'user').
- event_converter.py: use the helper instead of hard-coded 'model' in
  convert_a2a_message_to_event(); filter history fallback to agent-role
  messages only.
- to_adk_event.py: add role parameter to _create_event(); pass mapped
  role from convert_a2a_message_to_event().
- Regression tests for role restoration and history fallback.
@giulio-leone
giulio-leone force-pushed the fix/a2a-inbound-role-mapping branch from d39ec54 to 8cb01e3 Compare April 14, 2026 01:43
@giulio-leone

Copy link
Copy Markdown
Contributor Author

Rebased onto the current main, ran ./autoformat.sh, and kept the final diff scoped to the PR file (src/google/adk/a2a/converters/event_converter.py).

Local revalidation after the rebase:

  • isort --check on the 6 touched converter files
  • pyink --check --diff --config pyproject.toml on the same 6 files
  • PYTHONPATH=$PWD/src python -m pytest tests/unittests/a2a/converters/ → 154 passed

I also rechecked the role-conversion path locally to confirm the behavior is still intact after the formatting-only update: Role.user stays user, Role.agent stays model, and task-history fallback still ignores trailing user messages.

@rohityan rohityan added a2a [Component] This issue is related a2a support inside ADK. and removed core [Component] This issue is related to the core interface and implementation labels Jul 9, 2026
@adk-bot adk-bot added the core [Component] This issue is related to the core interface and implementation label Jul 11, 2026
copybara-service Bot pushed a commit that referenced this pull request Jul 22, 2026
@adk-bot

adk-bot commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Thank you @giulio-leone for your contribution! 🎉

Your changes have been successfully imported and merged via Copybara in commit 968845f.

Closing this PR as the changes are now in the main branch.

@adk-bot adk-bot added the merged [Status] This PR is merged label Jul 22, 2026
@adk-bot adk-bot closed this Jul 22, 2026
FrigaZzz pushed a commit to FrigaZzz/adk-python that referenced this pull request Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a2a [Component] This issue is related a2a support inside ADK. core [Component] This issue is related to the core interface and implementation merged [Status] This PR is merged request clarification [Status] The maintainer need clarification or more information from the author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A2A inbound message conversion ignores Message.role, always maps to "model"

4 participants