Skip to content

Python: AG-UI, Tool calls suppress shared state message injection #3010

@thomgrand

Description

@thomgrand

Hi,

currently, sharing the state between an agent and an AG-UI frontend (e.g. CopilotKit) breaks after the first time a tool is called. The agent no longer receives the shared state in the message history after the tool call. This problem also shows on the AG-UI dojo: https://dojo.ag-ui.com/microsoft-agent-framework-python/feature/shared_state. Let the bot write a simple recipe and afterwards, try to edit the shared state and ask the bot about the current state. Note that the bot still has the tool call in the message history, so its conversation history remains in the state it has set in the tool call. Example screenshot attached below.
Image

If you do the same conversation with another backend (e.g. Langgraph Python), editing in the frontend still works after the tool call:
Image

After a lot of debugging on both the frontend and backend side, I found that the state message is injected into the message history by the AF python AG-UI backend. However, the conversation history is also checked for ANY tool calls, and if any call is found, no state message is injected. Here are the responsible lines.
_state_manager.py
_orchestrators.py

I can only guess that the original code is intended to not print multiple instances of the current state in the message history in case it was updated by the backend, but for that purpose it is overly simplified:

  1. You can only use the content of the last agent/backend update if the state is the same as it was during the agent update. Otherwise frontend changes are ignored between tool calls.
  2. If my assumption about the original intent is correct, why is the tool call not limited to state updates? Currently, any tool call would eliminate the state.

The state variable in the backend (self.current_state) seems to reflect what I see on the frontend, so if I remove the check for conversation_has_tool_calls in state_manager, the state gets injected again as the first message in the history and the above example works.

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions