Skip to content

fix: keep streaming working for output schemas with field aliases - #314

Merged
Eigenwise merged 2 commits into
Eigenwise:mainfrom
darshjoshi:fix/stream-aliased-output-schema
Oct 19, 2026
Merged

Eigenwise merged 2 commits into
Eigenwise:mainfrom
darshjoshi:fix/stream-aliased-output-schema

Conversation

@darshjoshi

Copy link
Copy Markdown
Contributor

run_stream() and run_async_stream() fail at the end of the stream when the output schema has a field alias. run() works fine with the same schema.

Both streaming methods rebuild the final response like this:

self.output_schema(**last_response.model_dump())

model_dump() keys the data by field name, but a field declared with alias= only accepts its alias on input. So the whole response streams fine and then fails validation. The reply also never gets added to history.

Repro with a real model (gpt-4o-mini through Instructor):

class Reply(BaseIOSchema):
    """A short reply."""
    chat_message: str = Field(..., alias="chatMessage", description="The reply text")

agent = AtomicAgent[BasicChatInputSchema, Reply](AgentConfig(client=instructor.from_openai(openai.OpenAI()), model="gpt-4o-mini"))

On main:

run(): Reply(chat_message='Hello there!')
run_stream() raised ValidationError ['1 validation error for Reply', 'chatMessage', "  Field required [type=missing, input_value={'chat_message': 'Hello there!'}, input_type=dict]"] history: 1
run_async_stream() raised ValidationError

With this PR:

run(): Reply(chat_message='Hello there!')
run_stream(): Reply(chat_message='Hello there!') history: 2
run_async_stream(): history: 2 Reply(chat_message='Hello there!')

The fix validates the dumped data with model_validate(..., by_name=True), so field names are accepted alongside aliases. Schemas without aliases behave exactly as before. by_name is available from pydantic 2.11, which matches the current floor.

I added a regression test for each streaming method. Both fail on main and pass here. black --check, flake8 and pytest --cov=atomic_agents atomic-agents (623 passed) are green.

run_stream() rebuilt the final response with
output_schema(**last_response.model_dump()). model_dump() keys the data by
field name, so for an output schema with a field alias the call failed
with 'Field required' after the whole response had streamed, and the
reply was never added to history. Validate with by_name=True so field
names are accepted alongside aliases.
…onse

run_async_stream() had the same output_schema(**model_dump()) rebuild as
run_stream(), so an output schema with a field alias failed the same way
once the async stream ended.

@Eigenwise Eigenwise left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Reproduced the sync and async alias failures against current main. Both pass with this change, including history recording. Combined core suite, Black and Flake8 pass. Thanks.

@Eigenwise
Eigenwise merged commit 9000a13 into Eigenwise:main Oct 19, 2026
2 checks passed
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.

2 participants