Chat-Kit + AG-UI Demo
March 12, 2026 · View on GitHub
A minimal full-stack demo: Vue 3 frontend communicates with a PydanticAI agent over the AG-UI protocol, backed by the Stateful Responses API.
┌──────────────────────┐
│ Vue 3 Frontend │ localhost:5173
│ @ag-ui/client │
└──────────┬───────────┘
│ AG-UI (SSE)
▼
┌──────────────────────┐
│ PydanticAI Agent │ localhost:8000
│ AGUIAdapter │
│ OpenAIResponsesModel│
└──────────┬───────────┘
│ OpenAI Responses API
▼
┌──────────────────────┐
│ Stateful Responses │ (deployed)
│ → LLM (vLLM) │
└──────────────────────┘
Prerequisites
- Python 3.13+ with uv
- Node.js 18+
- An API token for the Stateful Responses endpoint
Quick Start
1. Agent backend
cd agent
cp .env.example .env # then edit .env with your token
uv sync
uv run uvicorn server:app --reload
Runs at http://localhost:8000/.
2. Frontend
cd frontend
cp .env.example .env # then edit .env with your token
npm install
npm run dev
Open http://localhost:5173.
Project Structure
├── agent/
│ ├── server.py # FastAPI app with AG-UI endpoint
│ ├── utils.py # Raw CoT thinking support + logging HTTP client
│ ├── pyproject.toml
│ └── .env.example
├── frontend/
│ ├── src/
│ │ ├── App.vue # Chat UI
│ │ ├── composables/useAgentChat.ts # AG-UI ↔ chat-kit bridge
│ │ ├── types.ts
│ │ └── main.ts
│ ├── .env.example
│ ├── package.json
│ └── vite.config.ts
└── README.md
How It Works
- User types a message in the Vue 3 chat UI
@ag-ui/clientHttpAgentPOSTs an AG-UIRunAgentInputto the backendAGUIAdapterconverts AG-UI messages to PydanticAI format and runs the agent- The agent calls
OpenAIResponsesModelwhich hits the Stateful Responses API - Stateful Responses reconstructs history, forwards to the LLM, and streams tokens back
AGUIAdaptertranslates PydanticAI output into AG-UI events (TextMessageStart/TextMessageContent/TextMessageEnd)- The frontend's
useAgentChatcomposable maps AG-UI events toBaseMessageobjects - Vue reactively renders each token as it arrives
Chat-Kit type compatibility
The frontend defines its own BaseMessage, MessageRole, and MessageStatus types in frontend/src/types.ts that mirror the exact same interfaces from @aleph-alpha/chat-kit. This means the useAgentChat composable produces messages that are directly compatible with chat-kit's components (ChatConversation, ChatInput, etc.) — in a production app you'd import the types from @aleph-alpha/chat-kit instead of duplicating them.
Key files
agent/utils.py— ExtendsAGUIAdapterandAGUIEventStreamto surface raw Chain-of-Thought thinking from models that store it inprovider_detailsrather thanThinkingPart.content(context).frontend/src/types.ts— Local copies of chat-kit'sBaseMessage,MessageRole, andMessageStatustypes.frontend/src/composables/useAgentChat.ts— The bridge between AG-UI events and chat-kit'sBaseMessagemodel. MapsTextMessageStart/TextMessageContent/TextMessageEndevents toBaseMessageobjects with the same lifecycle statuses (started→sending→completed). In production, this composable would live inside@aleph-alpha/chat-kitas anAGUIChatService.