Back to Agno

AG-UI

cookbook/05_agent_os/16_agui/README.md

2.8.26.6 KB
Original Source

AG-UI

AG-UI is an event-stream protocol between an agent backend and an interactive frontend. AgentOS translates Agent and Team run events into AG-UI text, tool, reasoning, state, and lifecycle events, while keeping the model, tools, sessions, and approval state on the server.

Every example in this folder is a standalone server. A client sends a RunAgentInput to POST {prefix}/agui and receives text/event-stream. The same interface exposes GET {prefix}/status; with the default empty prefix those routes are POST /agui and GET /status.

Files

FileWhat it teaches
basic.pyMount one agent at the default /agui and /status routes.
agent_with_tools.pyContrast a Python backend tool with a frontend-supplied external-execution tool.
structured_output.pyStream a response constrained by a Pydantic output schema.
reasoning_agent.pyTranslate Agno reasoning lifecycle events into AG-UI reasoning events.
agent_with_media.pyPass AG-UI image, audio, video, and document parts to Gemini.
shared_state.pySend state snapshots and JSON Patch deltas as session state changes.
human_in_the_loop.pyPause and resume a real backend tool that uses requires_confirmation.
research_team.pyStream a coordinated Team and its member activity over AG-UI.
multiple_instances.pyMount two independent AG-UI interfaces on one AgentOS.

Prerequisites

Install the demo environment, then export the provider key used by the file:

bash
./scripts/demo_setup.sh
export OPENAI_API_KEY=...
export GOOGLE_API_KEY=...  # agent_with_media.py only

research_team.py also needs internet access for WebSearchTools.

Run

Start one example at a time; every standalone server uses port 7777:

bash
.venvs/demo/bin/python cookbook/05_agent_os/16_agui/basic.py
.venvs/demo/bin/python cookbook/05_agent_os/16_agui/agent_with_tools.py
.venvs/demo/bin/python cookbook/05_agent_os/16_agui/structured_output.py
.venvs/demo/bin/python cookbook/05_agent_os/16_agui/reasoning_agent.py
.venvs/demo/bin/python cookbook/05_agent_os/16_agui/agent_with_media.py
.venvs/demo/bin/python cookbook/05_agent_os/16_agui/shared_state.py
.venvs/demo/bin/python cookbook/05_agent_os/16_agui/human_in_the_loop.py
.venvs/demo/bin/python cookbook/05_agent_os/16_agui/research_team.py
.venvs/demo/bin/python cookbook/05_agent_os/16_agui/multiple_instances.py

Point an AG-UI client such as CopilotKit or the AG-UI Dojo at the matching endpoint:

Running filePOST event streamStatus
basic.pyhttp://localhost:7777/aguihttp://localhost:7777/status
agent_with_tools.pyhttp://localhost:7777/tools/aguihttp://localhost:7777/tools/status
structured_output.pyhttp://localhost:7777/structured-output/aguihttp://localhost:7777/structured-output/status
reasoning_agent.pyhttp://localhost:7777/reasoning/aguihttp://localhost:7777/reasoning/status
agent_with_media.pyhttp://localhost:7777/media/aguihttp://localhost:7777/media/status
shared_state.pyhttp://localhost:7777/shared-state/aguihttp://localhost:7777/shared-state/status
human_in_the_loop.pyhttp://localhost:7777/human-in-the-loop/aguihttp://localhost:7777/human-in-the-loop/status
research_team.pyhttp://localhost:7777/research-team/aguihttp://localhost:7777/research-team/status
multiple_instances.pyhttp://localhost:7777/chat/agui and http://localhost:7777/analyst/agui/chat/status and /analyst/status

The old all-in-one showcase is intentionally gone: starting the file you are learning makes its endpoint available directly, without import-only support modules.

The event stream

A minimal request against basic.py is:

bash
curl -N http://localhost:7777/agui \
  -H 'Content-Type: application/json' \
  -d '{
    "threadId": "agui-readme-thread",
    "runId": "agui-readme-run",
    "state": {},
    "messages": [
      {"id": "message-1", "role": "user", "content": "Say hello in five words."}
    ],
    "tools": [],
    "context": [],
    "forwardedProps": {}
  }'

The stream begins with RUN_STARTED, emits message or capability-specific events, and ends with RUN_FINISHED. Tool calls use TOOL_CALL_*; reasoning uses REASONING_*; shared state uses STATE_SNAPSHOT and STATE_DELTA. threadId becomes the Agno session ID, so later requests can continue the same conversation.

Frontend tools and backend HITL are different

These two pause patterns look similar in a UI but have different ownership:

PatternWhere the tool existsWho executes itExample
Frontend-defined toolThe client sends its schema in RunAgentInput.tools; there is no Python implementation on the backend.The browser executes it and sends a trailing AG-UI tool message with the result.agent_with_tools.py
Backend confirmationPython registers a real @tool(requires_confirmation=True) implementation.AgentOS persists the paused run; the frontend sends {"accepted": true} or a rejection, then AgentOS resumes and conditionally executes Python.human_in_the_loop.py

The backend pause/resume mechanics themselves (requires_confirmation, continue_run, @approval records) are taught in ../05_human_in_the_loop/; this folder covers only how AG-UI surfaces them.

For example, a CopilotKit frontend can provide change_background in the request:

json
{
  "name": "change_background",
  "description": "Change the page background to a CSS value.",
  "parameters": {
    "type": "object",
    "properties": {"background": {"type": "string"}},
    "required": ["background"]
  }
}

The AG-UI adapter converts that request-scoped definition into an external_execution function with no server entrypoint. The first stream returns its tool-call ID; after the browser performs the change, it sends a trailing tool message with that ID to resume the persisted run. By contrast, the email function in human_in_the_loop.py is present and executable on the server, but cannot run until its confirmation requirement is resolved.

State and media

AG-UI state is a dictionary sent with the request. shared_state.py snapshots that dictionary before the run, lets update_session_state mutate it, emits a JSON Patch delta after the tool call, and finishes with an authoritative snapshot.

Media belongs in the latest user message as an AG-UI image, audio, video, or document content part. The adapter converts URL or base64 data sources into Agno media objects before calling the Gemini agent in agent_with_media.py.