Skip to content

Fix Python frontend tools client sample - #452

Open
Ran Shemtov (ranst91) wants to merge 2 commits into
MicrosoftDocs:mainfrom
CopilotKit:docs/python-ag-ui-frontend-tools-client
Open

Fix Python frontend tools client sample#452
Ran Shemtov (ranst91) wants to merge 2 commits into
MicrosoftDocs:mainfrom
CopilotKit:docs/python-ag-ui-frontend-tools-client

Conversation

@ranst91

Copy link
Copy Markdown
Contributor

Problem

The client sample in the Python zone of AG-UI > Frontend Tool Rendering cannot produce the output the page documents. Run against the server from the Getting Started tutorial, any prompt that requires a frontend tool prints only the run boundaries:

User (:q or quit to exit): What's the temperature reading from my sensors?

[Run Started]

[Run Finished]

Prompts that need no tool answer normally, so the gap is specific to frontend tool execution.

Cause

Four things in the sample:

  1. Tool declarations carried no parameter schema. Only name and description were sent, so the model had no arguments it was allowed to fill and called the tool with {}.
  2. The event loop ignored every tool-call event. It handled RUN_STARTED, TEXT_MESSAGE_CONTENT, RUN_FINISHED and RUN_ERROR only, so TOOL_CALL_START, TOOL_CALL_ARGS and TOOL_CALL_END fell through unhandled.
  3. _handle_tool_call was never called, and read fields that do not exist on those events. The tool name arrives as toolCallName on TOOL_CALL_START, and the arguments arrive as JSON text fragments in TOOL_CALL_ARGS.delta, to be concatenated per tool call id and parsed at TOOL_CALL_END.
  4. Tool results were never sent back. A frontend tool call ends the server's run, so the client has to record the call and its result and issue a follow-up run to get the agent's answer.

Fix

Only the client code block changes. The tool declarations now ship the JSON schema derived from each function's signature, the tool-call events are read and their argument fragments accumulated per call id, _handle_tool_call receives the tool name and the completed arguments, and the client records the call and result in the conversation before issuing the follow-up run. Run boundaries are reported once per user turn rather than once per run, matching the documented output.

The surrounding prose, the tool definitions section, the protocol description and the expected output are unchanged.

Verification

The sample was extracted from the page and run verbatim against a live AG-UI server built from the Getting Started tutorial:

User (:q or quit to exit): What's the temperature and humidity from my sensors?

[Run Started]

[Client Tool Call: read_climate_sensors]
  Arguments: {'include_temperature': True, 'include_humidity': True}
[Client Tool Result: {'temperature': 22.5, 'humidity': 45.0, 'air_quality_index': 75}]

Your sensors show:
- Temperature: 22.5 °C
- Humidity: 45%

[Run Finished]

Both sample tools were exercised, including get_user_location, which takes no parameters, and conversation history was confirmed to carry across turns.

The client sample on the AG-UI frontend tools page could not produce the
output the page shows. Running it against the Getting Started server printed
only `[Run Started]` and `[Run Finished]` for any prompt that needed a tool.

Four things were missing:

- The tool declarations carried no parameter schema, so the model could only
  call a tool with an empty argument object. They now ship the JSON schema
  derived from each function's signature.
- The event loop ignored every tool-call event. `TOOL_CALL_START` and
  `TOOL_CALL_ARGS` are now read, with the argument fragments accumulated per
  tool call id and parsed once the call is complete.
- `_handle_tool_call` was never called, and expected a single event carrying a
  ready-made argument dictionary. It now receives the tool name and the
  accumulated arguments, and returns the result.
- The client never sent tool results back. A frontend tool call ends the
  server's run, so the client now records the call and its result in the
  conversation and issues a follow-up run to get the agent's answer. Run
  boundaries are reported once per user turn rather than once per run.

Verified against a live AG-UI server: the sample runs verbatim, calls both
frontend tools with real arguments, and keeps history across turns.
@learn-build-service-prod

Copy link
Copy Markdown
Contributor

Learn Build status updates of commit db0aab0:

✅ Validation status: passed

File Status Preview URL Details
agent-framework/integrations/by-component/ui/ag-ui/frontend-tools.md ✅Succeeded

For more details, please refer to the build report.

The method now drives both the initial run and the follow-up run that
delivers the agent's answer after a frontend tool executes, so name it
run_turn rather than send_message.
@learn-build-service-prod

Copy link
Copy Markdown
Contributor

Learn Build status updates of commit 0d21f2f:

✅ Validation status: passed

File Status Preview URL Details
agent-framework/integrations/by-component/ui/ag-ui/frontend-tools.md ✅Succeeded

For more details, please refer to the build report.

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