Skip to content

Filter out empty thinking parts from Gemini 3 when sending data to the frontend on integrations like Vercel #3479

@psg2

Description

@psg2

Initial Checks

Description

Slack thread: https://pydanticlogfire.slack.com/archives/C083V7PMHHA/p1763583745967179

When running Gemini 3 Pro even if we don't include thoughts the model will send back signatures with empty thinking parts, and if we stream those to the frontend it will break existing messages in two parts that might break content display.

Example Code

google_thinking_config = ThinkingConfigDict(
        include_thoughts=False,
        thinking_budget=-1,
    )
    settings = GoogleModelSettings(
        google_thinking_config=google_thinking_config,
    )
    model = GoogleModel("gemini-3-pro-preview", provider=provider, settings=settings)
    agent = Agent(model)

    response = agent.run_stream_events(user_prompt="Hello, how are you?")
    async for event in response:
        print(event)


---

PartStartEvent(index=0, part=ThinkingPart(content='', signature='CikB4/H/XloIwu2SHqsD59im9FS41+wD+BmuoQPqraVodZXw0rGITwNrgQpWAePx/175k6XlrErvNhtC8xJ4ZOnaPHuj41rbCd4cR/43ZTb/ERxlSekNlaw7C3d8OreSIFyh3hdmYs5wYUNxOwoUMwVdqi3mIqAv06VaSWpKZ2AtxoMKaAHj8f9eMhW5305uqeJg+YOJO+P/+pZ1umPZJtftF4HudIjjqDQ5aJDDf+6JDbG6lhtwWObZgatWeFZGryospiYErLLBj3vWBsu3dF53VNrIcNTUXBv3XNs82MLov9wwqpEKrWieaOnrCp4BAePx/15zM3xvUsXsIP/OWgMESOaPksOk20dg49uvaxTkGTHkCUfr0I3B59Y44xZkMVLaMJe060zhxsk/7JtTlZK5BoIcNG26WOoti5KfzKwxnVXnsXHeVzXOMoMMe6+Mfsj6uk7XrprWUEmGXE4a+7FGDZP/H1skJA51xqqtAgUZxesdz37AmZhbmRWVLywfoBQf7iv9NN1yggS71yIKgAEB4/H/XtzSZP+tQDQK66S0IJjh4b0g+PqU+SZedOB8V68o0kUhDg3hqRXDs+wt3n7fBfpmxXYdS0TJTWxP2QWMByzM84e9aSeQeusXVd0XJDWR0flivyjH9WJVjKxL1oQKnIzIrxCVPSpKvvwGYQ9ETVSY70sl//rNGmPjD+VruwrNAQHj8f9e2PcnRaXJxC9z2nrjXe448pr5kaXuYrlpm004zyik1h7U2dgA6SgViBohxQg0DCVSseWCjANErPNADJ611TJyOTymYhn2cQvSCn7aHC4VGw3iH0kA3jv+EZDzIgvo2AfQeBMTN9a5pleMweMt9JyxDMknLWHwehCoynOdvezwmbiGwV5P8XXsc4sgybRDjPH6XaDSnaMt8NUnYI2Muwq93xxIKgyrSFvNjY3qrmWGL0u3IUCZv7FGiPzB+zUbYsTGHTBhkdX3kLIKrwEB4/H/XqEruT3vubOmMW4zMIVxvz2Vj/Oha0vaCYgpvMTQIdOok/7OfspqX5eheFqmcSmckd+uNzcQpX4/iLjZr+CgCRCsEyrF12H7osVWSxMQiThJS8rIQkrORhNX/t6CFYemHpl+Rn13/Ij2rj2O5G27xuct/DYFiBAZBMGimLb+MvXP30TTkls+IWBtZXkomI8HZxD6tx5g7oxgcZuts5etNtK/TA5EQiLjaihhCo8CAePx/15GE/QlRqfZnzI3oQPlwkkoctTSppzZ8wJ/l/DP3zGfDnbj7TqHWozhbug8/xSFIYaI+6bnqsNn7rgaU709Eg2tk6tDi89jOmBxWq/ZhYEjtz7ldP/XtUP1vzXODSz6d08VSpJUFbvkTJ4JmH23DGdc1VFoddbdfcEo4yWZjwRvPGgOWrGAukNM5zJyIUjvN0oAiwJ1jWOFSOS3ChefTM1ShjCo1vSTfPKHvVmnu+vZhHNgZqgzRi5uxWUsT6u2fb1RCdgJbNrvSpftoyNbsLZ/NjxRj1VCQ3MsXMODjl30mlIUnWY7HUe05cfrA/mn9aui8emUAmCk5dfpCErkhUQu8V2hixE+KAmDowp2AePx/17NcUBarxsNVEfBacEgE2MaNYoFsWIFL8l2KQecIj/iqT6ALVvQTV/Mmf1aKg5pin62xRvzffreKYC9KDrfRDk5ZN154YfkYB0URUwVAgY/2DNRCfR+HVCv9HAy6QW/yRqnRekG0DgL5JqJz4Px+h7rZQ==', provider_name='google-vertex'))
PartEndEvent(index=0, part=ThinkingPart(content='', signature='CikB4/H/XloIwu2SHqsD59im9FS41+wD+BmuoQPqraVodZXw0rGITwNrgQpWAePx/175k6XlrErvNhtC8xJ4ZOnaPHuj41rbCd4cR/43ZTb/ERxlSekNlaw7C3d8OreSIFyh3hdmYs5wYUNxOwoUMwVdqi3mIqAv06VaSWpKZ2AtxoMKaAHj8f9eMhW5305uqeJg+YOJO+P/+pZ1umPZJtftF4HudIjjqDQ5aJDDf+6JDbG6lhtwWObZgatWeFZGryospiYErLLBj3vWBsu3dF53VNrIcNTUXBv3XNs82MLov9wwqpEKrWieaOnrCp4BAePx/15zM3xvUsXsIP/OWgMESOaPksOk20dg49uvaxTkGTHkCUfr0I3B59Y44xZkMVLaMJe060zhxsk/7JtTlZK5BoIcNG26WOoti5KfzKwxnVXnsXHeVzXOMoMMe6+Mfsj6uk7XrprWUEmGXE4a+7FGDZP/H1skJA51xqqtAgUZxesdz37AmZhbmRWVLywfoBQf7iv9NN1yggS71yIKgAEB4/H/XtzSZP+tQDQK66S0IJjh4b0g+PqU+SZedOB8V68o0kUhDg3hqRXDs+wt3n7fBfpmxXYdS0TJTWxP2QWMByzM84e9aSeQeusXVd0XJDWR0flivyjH9WJVjKxL1oQKnIzIrxCVPSpKvvwGYQ9ETVSY70sl//rNGmPjD+VruwrNAQHj8f9e2PcnRaXJxC9z2nrjXe448pr5kaXuYrlpm004zyik1h7U2dgA6SgViBohxQg0DCVSseWCjANErPNADJ611TJyOTymYhn2cQvSCn7aHC4VGw3iH0kA3jv+EZDzIgvo2AfQeBMTN9a5pleMweMt9JyxDMknLWHwehCoynOdvezwmbiGwV5P8XXsc4sgybRDjPH6XaDSnaMt8NUnYI2Muwq93xxIKgyrSFvNjY3qrmWGL0u3IUCZv7FGiPzB+zUbYsTGHTBhkdX3kLIKrwEB4/H/XqEruT3vubOmMW4zMIVxvz2Vj/Oha0vaCYgpvMTQIdOok/7OfspqX5eheFqmcSmckd+uNzcQpX4/iLjZr+CgCRCsEyrF12H7osVWSxMQiThJS8rIQkrORhNX/t6CFYemHpl+Rn13/Ij2rj2O5G27xuct/DYFiBAZBMGimLb+MvXP30TTkls+IWBtZXkomI8HZxD6tx5g7oxgcZuts5etNtK/TA5EQiLjaihhCo8CAePx/15GE/QlRqfZnzI3oQPlwkkoctTSppzZ8wJ/l/DP3zGfDnbj7TqHWozhbug8/xSFIYaI+6bnqsNn7rgaU709Eg2tk6tDi89jOmBxWq/ZhYEjtz7ldP/XtUP1vzXODSz6d08VSpJUFbvkTJ4JmH23DGdc1VFoddbdfcEo4yWZjwRvPGgOWrGAukNM5zJyIUjvN0oAiwJ1jWOFSOS3ChefTM1ShjCo1vSTfPKHvVmnu+vZhHNgZqgzRi5uxWUsT6u2fb1RCdgJbNrvSpftoyNbsLZ/NjxRj1VCQ3MsXMODjl30mlIUnWY7HUe05cfrA/mn9aui8emUAmCk5dfpCErkhUQu8V2hixE+KAmDowp2AePx/17NcUBarxsNVEfBacEgE2MaNYoFsWIFL8l2KQecIj/iqT6ALVvQTV/Mmf1aKg5pin62xRvzffreKYC9KDrfRDk5ZN154YfkYB0URUwVAgY/2DNRCfR+HVCv9HAy6QW/yRqnRekG0DgL5JqJz4Px+h7rZQ==', provider_name='google-vertex'), next_part_kind='text')
PartStartEvent(index=1, part=TextPart(content="I'm doing well, thank you for asking! How can I help you today?"), previous_part_kind='thinking')
FinalResultEvent(tool_name=None, tool_call_id=None)
PartEndEvent(index=1, part=TextPart(content="I'm doing well, thank you for asking! How can I help you today?"))
AgentRunResultEvent(result=AgentRunResult(output="I'm doing well, thank you for asking! How can I help you today?"))

Python, Pydantic AI & LLM client version

Python 3.12
Pydantic 1.20
Gemini 3 Pro

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions