Skip to content

fix(bidi): respect role from BidiTextInputEvent instead of hardcoding user#2083

Open
btdeviant wants to merge 4 commits intostrands-agents:mainfrom
btdeviant:fix/bidi-text-input-role
Open

fix(bidi): respect role from BidiTextInputEvent instead of hardcoding user#2083
btdeviant wants to merge 4 commits intostrands-agents:mainfrom
btdeviant:fix/bidi-text-input-role

Conversation

@btdeviant
Copy link
Copy Markdown

Motivation

The bidi agent loop hardcodes "role": "user" when appending messages from a BidiTextInputEvent, ignoring the event's role property entirely. This means callers who construct a BidiTextInputEvent with role="assistant" (e.g., for injecting assistant context into the conversation history) have that role silently overwritten. The role parameter on BidiTextInputEvent exists specifically to support this — it should be used.

Related Issues

None (no existing upstream issue for this bug).

Documentation PR

N/A — no documentation changes needed.

Type of Change

Bug fix

Public API Changes

No public API changes. BidiTextInputEvent already accepts a role parameter — this fix ensures the agent loop honors it.

# Before: role parameter is accepted but ignored by the agent loop
event = BidiTextInputEvent(text="hello", role="assistant")
# internally creates: {"role": "user", "content": [{"text": "hello"}]}  # role silently overwritten

# After: role parameter is respected
event = BidiTextInputEvent(text="hello", role="assistant")
# internally creates: {"role": "assistant", "content": [{"text": "hello"}]}  # correct

Testing

  • I ran hatch run prepare

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

… user

BidiTextInputEvent carries a role field but the bidi loop hardcoded
"user" when appending to message history. This prevented injecting
context/system messages with role="assistant" via GatewayBidiInput.
Changed versioning to dynamic based on git tags.
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!


if isinstance(event, BidiTextInputEvent):
message: Message = {"role": "user", "content": [{"text": event.text}]}
message: Message = {"role": event.role, "content": [{"text": event.text}]}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you elaborate a bit more on the use case here? Note that we do allow you to prefill the initial message history that is sent to the model with assistant messages (Agent(messages=...)). They are sent separately in start(). Curious though what it would mean for the user to send an assistant message to the model in the middle of a conversation.

Copy link
Copy Markdown
Member

@pgrayy pgrayy Apr 8, 2026

Choose a reason for hiding this comment

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

I also ran some tests against 2 models (1 from google and 1 from openai). Google rejected the assistant message with an error response and openai seemed to ignore it.

Note, there is also some hardcoding of roles in the model providers themselves that I had to update for the tests.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@pgrayy good catch on the Google test. Admittedly I'm using a custom adapter for an openai api compatible server (sglang / llama.cpp), and at the risk of being a bit presumptuous, I take your point that this PR may be premature given the official supported clients for BidiAgent are limited.

The use case it addresses is pushing context from async process as an input source, which through some other magic elicits unprompted engagement from the users perspective. A bit atypical I suppose. I can monkey patch around it, not a big deal, just took a bit of debugging to find out why assistant wasn't making it to the model - was a bit of a bear trap :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants