@@ -12,9 +12,9 @@ The team at [Rocket Science](https://www.rocketscience.gg/), contributed the
12
12
protocol with PydanticAI agents.
13
13
14
14
This also includes an [ ` Agent.to_ag_ui ` ] [ pydantic_ai.Agent.to_ag_ui ] convenience
15
- method which simplifies the creation of [ ` Adapter ` ] [ pydantic_ai.ag_ui.Adapter ]
16
- for PydanticAI agents, which can then be used by as part of a
17
- [ fastapi ] ( https://fastapi.tiangolo.com/ ) app .
15
+ method which simplifies the creation of [ ` FastAGUI ` ] [ pydantic_ai.ag_ui.FastAGUI ]
16
+ for PydanticAI agents, which is built on top of [ Starlette ] ( https://www.starlette.io/ ) ,
17
+ meaning it's fully compatible with any ASGI server .
18
18
19
19
## AG-UI Adapter
20
20
@@ -27,8 +27,6 @@ for all aspects of spec including:
27
27
- [ State Management] ( https://docs.ag-ui.com/concepts/state )
28
28
- [ Tools] ( https://docs.ag-ui.com/concepts/tools )
29
29
30
- Let's have a quick look at how to use it:
31
-
32
30
### Installation
33
31
34
32
The only dependencies are:
@@ -40,14 +38,14 @@ The only dependencies are:
40
38
41
39
To run the examples you'll also need:
42
40
43
- - [ fastapi ] ( https://fastapi.tiangolo.com/ ) : to provide ASGI compatible server
41
+ - [ uvicorn ] ( https://www.uvicorn.org/ ) or another ASGI compatible server
44
42
45
43
``` bash
46
- pip/uv-add ' fastapi '
44
+ pip/uv-add ' uvicorn '
47
45
```
48
46
49
- You can install PydanticAI with the ` ag-ui ` extra to include
50
- [ Adapter ] [ pydantic_ai.ag_ui.Adapter ] run :
47
+ You can install PydanticAI with the ` ag-ui ` extra to ensure you have all the
48
+ required AG-UI dependencies :
51
49
52
50
``` bash
53
51
pip/uv-add ' pydantic-ai-slim[ag-ui]'
@@ -60,30 +58,10 @@ pip/uv-add 'pydantic-ai-slim[ag-ui]'
60
58
61
59
from __future__ import annotations
62
60
63
- from typing import TYPE_CHECKING , Annotated
64
-
65
- from fastapi import FastAPI, Header
66
- from fastapi.responses import StreamingResponse
67
- from pydantic_ai.ag_ui import SSE_CONTENT_TYPE
68
-
69
61
from pydantic_ai import Agent
70
62
71
- if TYPE_CHECKING :
72
- from ag_ui.core import RunAgentInput
73
-
74
63
agent = Agent(' openai:gpt-4.1' , instructions = ' Be fun!' )
75
- adapter = agent.to_ag_ui()
76
- app = FastAPI(title = ' AG-UI Endpoint' )
77
-
78
-
79
- @app.post (' /' )
80
- async def root (
81
- input_data : RunAgentInput, accept : Annotated[str , Header()] = SSE_CONTENT_TYPE
82
- ) -> StreamingResponse:
83
- return StreamingResponse(
84
- adapter.run(input_data, accept),
85
- media_type = SSE_CONTENT_TYPE ,
86
- )
64
+ app = agent.to_ag_ui()
87
65
```
88
66
89
67
You can run the example with:
@@ -109,13 +87,16 @@ streamed back to the caller as Server-Sent Events (SSE).
109
87
A user request may require multiple round trips between client UI and PydanticAI
110
88
server, depending on the tools and events needed.
111
89
112
- [ Adapter] [ pydantic_ai.ag_ui.Adapter ] can be used with any ASGI server.
90
+ In addition to the [ Adapter] [ pydantic_ai.ag_ui.Adapter ] there is also
91
+ [ FastAGUI] [ pydantic_ai.ag_ui.FastAGUI ] which is slim wrapper around
92
+ [ Starlette] ( https://www.starlette.io/ ) providing easy access to run a PydanticAI
93
+ server with AG-UI support with any ASGI server.
113
94
114
95
### Features
115
96
116
97
To expose a PydanticAI agent as an AG-UI server including state support, you can
117
- use the [ ` to_ag_ui ` ] [ pydantic_ai.agent.Agent.to_ag_ui ] method in combination
118
- with [ fastapi ] ( https://fastapi.tiangolo.com/ ) .
98
+ use the [ ` to_ag_ui ` ] [ pydantic_ai.agent.Agent.to_ag_ui ] method create an ASGI
99
+ compatible server .
119
100
120
101
In the example below we have document state which is shared between the UI and
121
102
server using the [ ` StateDeps ` ] [ pydantic_ai.ag_ui.StateDeps ] which implements the
@@ -134,17 +115,10 @@ real-time synchronization between agents and frontend applications.
134
115
135
116
from __future__ import annotations
136
117
137
- from typing import TYPE_CHECKING , Annotated
138
-
139
- from fastapi import FastAPI, Header
140
- from fastapi.responses import StreamingResponse
141
118
from pydantic import BaseModel
142
- from pydantic_ai.ag_ui import SSE_CONTENT_TYPE , StateDeps
143
119
144
120
from pydantic_ai import Agent
145
-
146
- if TYPE_CHECKING :
147
- from ag_ui.core import RunAgentInput
121
+ from pydantic_ai.ag_ui import StateDeps
148
122
149
123
150
124
class DocumentState (BaseModel ):
@@ -158,29 +132,27 @@ agent = Agent(
158
132
instructions = ' Be fun!' ,
159
133
deps_type = StateDeps[DocumentState],
160
134
)
161
- adapter = agent.to_ag_ui()
162
- app = FastAPI(title = ' AG-UI Endpoint' )
163
-
164
-
165
- @app.post (' /' )
166
- async def root (
167
- input_data : RunAgentInput, accept : Annotated[str , Header()] = SSE_CONTENT_TYPE
168
- ) -> StreamingResponse:
169
- return StreamingResponse(
170
- adapter.run(input_data, accept, deps = StateDeps(state_type = DocumentState)),
171
- media_type = SSE_CONTENT_TYPE ,
172
- )
135
+ app = agent.to_ag_ui(deps = StateDeps(state_type = DocumentState))
173
136
```
174
137
175
- Since ` app ` is an ASGI application, it can be used with any ASGI server.
138
+ Since ` app ` is an ASGI application, it can be used with any ASGI server e.g .
176
139
177
140
``` bash
178
141
uvicorn agent_to_ag_ui:app --host 0.0.0.0 --port 8000
179
142
```
180
143
181
144
Since the goal of [ ` to_ag_ui ` ] [ pydantic_ai.agent.Agent.to_ag_ui ] is to be a
182
- convenience method, it accepts the same arguments as the
183
- [ ` Adapter ` ] [ pydantic_ai.ag_ui.Adapter ] constructor.
145
+ convenience method, it accepts the same a combination of the arguments require
146
+ for:
147
+
148
+ - [ ` Adapter ` ] [ pydantic_ai.ag_ui.Adapter ] constructor
149
+ - [ ` Agent.iter ` ] [ pydantic_ai.agent.Agent.iter ] method
150
+
151
+ If you want more control you can either use
152
+ [ ` agent_to_ag_ui ` ] [ pydantic_ai.ag_ui.agent_to_ag_ui ] helper method or create
153
+ and [ ` Agent ` ] [ pydantic_ai.ag_ui.Agent ] directly which also provide
154
+ the ability to customise [ ` Starlette ` ] ( https://www.starlette.io/applications/#starlette.applications.Starlette )
155
+ options.
184
156
185
157
#### Tools
186
158
@@ -200,18 +172,16 @@ for custom events and state updates.
200
172
201
173
from __future__ import annotations
202
174
203
- from typing import TYPE_CHECKING , Annotated
175
+ from typing import TYPE_CHECKING
204
176
205
177
from ag_ui.core import CustomEvent, EventType, StateSnapshotEvent
206
- from fastapi import FastAPI, Header
207
- from fastapi.responses import StreamingResponse
208
178
from pydantic import BaseModel
209
- from pydantic_ai.ag_ui import SSE_CONTENT_TYPE , StateDeps
210
179
211
180
from pydantic_ai import Agent, RunContext
181
+ from pydantic_ai.ag_ui import StateDeps
212
182
213
183
if TYPE_CHECKING :
214
- from ag_ui.core import RunAgentInput
184
+ pass
215
185
216
186
217
187
class DocumentState (BaseModel ):
@@ -225,8 +195,7 @@ agent = Agent(
225
195
instructions = ' Be fun!' ,
226
196
deps_type = StateDeps[DocumentState],
227
197
)
228
- adapter = agent.to_ag_ui()
229
- app = FastAPI(title = ' AG-UI Endpoint' )
198
+ app = agent.to_ag_ui(deps = StateDeps(state_type = DocumentState))
230
199
231
200
232
201
@agent.tool
@@ -251,16 +220,6 @@ def custom_events() -> list[CustomEvent]:
251
220
value = 2 ,
252
221
),
253
222
]
254
-
255
-
256
- @app.post (' /' )
257
- async def root (
258
- input_data : RunAgentInput, accept : Annotated[str , Header()] = SSE_CONTENT_TYPE
259
- ) -> StreamingResponse:
260
- return StreamingResponse(
261
- adapter.run(input_data, accept, deps = StateDeps(state_type = DocumentState)),
262
- media_type = SSE_CONTENT_TYPE ,
263
- )
264
223
```
265
224
266
225
### Examples
@@ -296,11 +255,11 @@ options:
296
255
Run with adapter debug logging:
297
256
298
257
``` shell
299
- python -m pydantic_ai.ag_ui_examples .dojo_server --log-level debug
258
+ python -m pydantic_ai_ag_ui_examples .dojo_server --log-level debug
300
259
```
301
260
302
261
Using uvicorn:
303
262
304
263
``` shell
305
- uvicorn pydantic_ai.ag_ui_examples .dojo_server:app --port 9000
264
+ uvicorn pydantic_ai_ag_ui_examples .dojo_server:app --port 9000
306
265
```
0 commit comments