|
2 | 2 |
|
3 | 3 | Pydantic AI includes a built-in web chat interface that you can use to interact with your agents through a browser. |
4 | 4 |
|
5 | | -https://github.com/user-attachments/assets/8a1c90dc-f62b-4e35-9d66-59459b45790d |
| 5 | +<video src="https://github.com/user-attachments/assets/8a1c90dc-f62b-4e35-9d66-59459b45790d" autoplay loop muted playsinline></video> |
6 | 6 |
|
7 | 7 | ## Installation |
8 | 8 |
|
9 | | -Install the `web` extra to get the required dependencies: |
| 9 | +Install the `web` extra (installs Starlette): |
10 | 10 |
|
11 | 11 | ```bash |
12 | 12 | pip/uv-add 'pydantic-ai-slim[web]' |
13 | 13 | ``` |
14 | 14 |
|
15 | | -## Usage |
16 | | - |
17 | | -There are two ways to launch the web chat UI: |
| 15 | +For CLI usage with `clai web`, see the [CLI documentation](../cli.md#web-chat-ui). |
18 | 16 |
|
19 | | -### 1. Using the CLI (`clai web`) |
| 17 | +## Usage |
20 | 18 |
|
21 | | -The simplest way to start the web UI is using the `clai web` command: |
| 19 | +Create a web app from an agent instance using [`Agent.to_web()`][pydantic_ai.agent.Agent.to_web]: |
22 | 20 |
|
23 | | -```bash |
24 | | -# With a custom agent |
25 | | -clai web --agent my_module:my_agent |
| 21 | +=== "Using Model Names" |
26 | 22 |
|
27 | | -# With specific models |
28 | | -clai web -m openai:gpt-5 -m anthropic:claude-sonnet-4-5 |
| 23 | + ```python |
| 24 | + from pydantic_ai import Agent |
| 25 | + from pydantic_ai.builtin_tools import WebSearchTool |
29 | 26 |
|
30 | | -# With builtin tools |
31 | | -clai web -m openai:gpt-5 -t web_search -t code_execution |
| 27 | + model = 'openai:gpt-5' |
| 28 | + agent = Agent(model) |
32 | 29 |
|
33 | | -# Generic agent with system instructions |
34 | | -clai web -m openai:gpt-5 -i 'You are a helpful coding assistant' |
35 | | -``` |
| 30 | + @agent.tool_plain |
| 31 | + def get_weather(city: str) -> str: |
| 32 | + return f'The weather in {city} is sunny' |
36 | 33 |
|
37 | | -#### CLI Options |
| 34 | + # Create app with model names (their display names are auto-generated) |
| 35 | + app = agent.to_web( |
| 36 | + models=['openai:gpt-5', 'anthropic:claude-sonnet-4-5'], |
| 37 | + builtin_tools=[WebSearchTool()], |
| 38 | + ) |
38 | 39 |
|
39 | | -| Option | Description | |
40 | | -|--------|-------------| |
41 | | -| `--agent`, `-a` | Agent to serve in `module:variable` format | |
42 | | -| `--model`, `-m` | Model to make available (repeatable) | |
43 | | -| `--tool`, `-t` | Builtin tool to enable (repeatable) | |
44 | | -| `--instructions`, `-i` | System instructions (when `--agent` not specified) | |
45 | | -| `--host` | Host to bind server (default: 127.0.0.1) | |
46 | | -| `--port` | Port to bind server (default: 7932) | |
47 | | -| `--mcp` | Path to MCP server config JSON file | |
| 40 | + # Or with custom display labels |
| 41 | + app = agent.to_web( |
| 42 | + models={'GPT 5': 'openai:gpt-5', 'Claude': 'anthropic:claude-sonnet-4-5'}, |
| 43 | + builtin_tools=[WebSearchTool()], |
| 44 | + ) |
| 45 | + ``` |
48 | 46 |
|
49 | | -Model names without a provider prefix are automatically inferred: |
| 47 | +=== "Using Model Instances" |
50 | 48 |
|
51 | | -- `gpt-*`, `o1`, `o3` → OpenAI |
52 | | -- `claude-*`, `sonnet`, `opus`, `haiku` → Anthropic |
53 | | -- `gemini-*` → Google |
| 49 | + ```python |
| 50 | + from pydantic_ai import Agent |
| 51 | + from pydantic_ai.builtin_tools import WebSearchTool |
| 52 | + from pydantic_ai.models.anthropic import AnthropicModel |
| 53 | + from pydantic_ai.models.openai import OpenAIModel |
54 | 54 |
|
55 | | -### 2. Using `Agent.to_web()` Programmatically |
| 55 | + # Create separate models with their own custom configuration |
| 56 | + anthropic_model = AnthropicModel('claude-sonnet-4-5') |
| 57 | + openai_model = OpenAIModel('gpt-5', api_key='custom-key') |
56 | 58 |
|
57 | | -For more control, you can create a web app from an agent instance: |
| 59 | + agent = Agent(openai_model) |
58 | 60 |
|
59 | | -```python |
60 | | -from pydantic_ai import Agent |
61 | | -from pydantic_ai.builtin_tools import WebSearchTool |
| 61 | + @agent.tool_plain |
| 62 | + def get_weather(city: str) -> str: |
| 63 | + return f'The weather in {city} is sunny' |
62 | 64 |
|
63 | | -agent = Agent('openai:gpt-5') |
| 65 | + # Use the instances directly |
| 66 | + app = agent.to_web( |
| 67 | + models=[openai_model, anthropic_model], |
| 68 | + builtin_tools=[WebSearchTool()], |
| 69 | + ) |
64 | 70 |
|
65 | | -@agent.tool_plain |
66 | | -def get_weather(city: str) -> str: |
67 | | - return f'The weather in {city} is sunny' |
| 71 | + # Or mix instances and strings with custom labels |
| 72 | + app = agent.to_web( |
| 73 | + models={'Custom GPT': openai_model, 'Claude': 'anthropic:claude-sonnet-4-5'}, |
| 74 | + builtin_tools=[WebSearchTool()], |
| 75 | + ) |
68 | 76 |
|
69 | | -# Create app with model names (their display names are auto-generated) |
70 | | -app = agent.to_web( |
71 | | - models=['openai:gpt-5', 'anthropic:claude-sonnet-4-5'], |
72 | | - builtin_tools=[WebSearchTool()], |
73 | | -) |
74 | | - |
75 | | -# Or with custom display labels |
76 | | -app = agent.to_web( |
77 | | - models={'GPT 5': 'openai:gpt-5', 'Claude': 'anthropic:claude-sonnet-4-5'}, |
78 | | - builtin_tools=[WebSearchTool()], |
79 | | -) |
80 | | -``` |
| 77 | + # With extra instructions passed to each run |
| 78 | + app = agent.to_web( |
| 79 | + models=[openai_model], |
| 80 | + instructions='Always respond in a friendly tone.', |
| 81 | + ) |
| 82 | + ``` |
81 | 83 |
|
82 | 84 | The returned Starlette app can be run with any ASGI server: |
83 | 85 |
|
84 | 86 | ```bash |
85 | 87 | uvicorn my_module:app --host 0.0.0.0 --port 8080 |
86 | 88 | ``` |
87 | 89 |
|
88 | | -!!! note "Reserved Routes" |
89 | | - The web UI app uses the following routes which should not be overwritten: |
90 | | - |
91 | | - - `/` and `/{id}` - Serves the chat UI |
92 | | - - `/api/chat` - Chat endpoint (POST, OPTIONS) |
93 | | - - `/api/configure` - Frontend configuration (GET) |
94 | | - - `/api/health` - Health check (GET) |
95 | | - |
96 | | - The app cannot currently be mounted at a subpath (e.g., `/chat`) because the UI expects these routes at the root. You can add additional routes to the app, but avoid conflicts with these reserved paths. |
97 | | - |
98 | | -## MCP Server Configuration |
99 | | - |
100 | | -You can enable [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) servers using a JSON configuration file: |
101 | | - |
102 | | -```bash |
103 | | -clai web --agent my_agent:my_agent --mcp mcp-servers.json |
104 | | -``` |
| 90 | +## Builtin Tool Support |
105 | 91 |
|
106 | | -Example JSON configuration: |
107 | | - |
108 | | -```json |
109 | | -{ |
110 | | - "mcpServers": { |
111 | | - "deepwiki": { |
112 | | - "url": "https://mcp.deepwiki.com/mcp" |
113 | | - }, |
114 | | - "github": { |
115 | | - "url": "https://api.githubcopilot.com/mcp", |
116 | | - "authorizationToken": "${GITHUB_TOKEN}" |
117 | | - } |
118 | | - } |
119 | | -} |
120 | | -``` |
| 92 | +Builtin tool support is automatically determined from each model's profile. The UI will only show tools that the selected model supports. |
121 | 93 |
|
122 | | -Environment variables can be referenced using `${VAR_NAME}` syntax, with optional defaults: `${VAR_NAME:-default_value}`. |
| 94 | +Available [builtin tools](../builtin-tools.md): |
123 | 95 |
|
124 | | -Each server entry supports: |
| 96 | +- `web_search` - Web search capability ([`WebSearchTool`][pydantic_ai.builtin_tools.WebSearchTool]) |
| 97 | +- `code_execution` - Code execution in a sandbox ([`CodeExecutionTool`][pydantic_ai.builtin_tools.CodeExecutionTool]) |
| 98 | +- `image_generation` - Image generation ([`ImageGenerationTool`][pydantic_ai.builtin_tools.ImageGenerationTool]) |
| 99 | +- `web_fetch` - Fetch content from URLs ([`WebFetchTool`][pydantic_ai.builtin_tools.WebFetchTool]) |
| 100 | +- `memory` - Persistent memory across conversations ([`MemoryTool`][pydantic_ai.builtin_tools.MemoryTool]) |
125 | 101 |
|
126 | | -| Field | Description | |
127 | | -|-------|-------------| |
128 | | -| `url` (required) | The MCP server URL | |
129 | | -| `authorizationToken` | Authorization token for the server | |
130 | | -| `description` | Description shown in the UI | |
131 | | -| `allowedTools` | List of allowed tool names | |
132 | | -| `headers` | Additional HTTP headers | |
| 102 | +!!! note "Memory Tool Requirements" |
| 103 | + The `memory` tool requires the agent to have memory configured via the |
| 104 | + `memory` parameter when creating the agent. |
133 | 105 |
|
134 | | -## Builtin Tool Support |
135 | 106 |
|
136 | | -When using the new models API, builtin tool support is automatically determined from each model's profile. The UI will only show tools that the selected model supports. |
| 107 | +## Reserved Routes |
137 | 108 |
|
138 | | -Available builtin tools: |
| 109 | +The web UI app uses the following routes which should not be overwritten: |
139 | 110 |
|
140 | | -- `web_search` - Web search capability |
141 | | -- `code_execution` - Code execution in a sandbox |
142 | | -- `image_generation` - Image generation |
143 | | -- `web_fetch` - Fetch content from URLs |
144 | | -- `memory` - Persistent memory across conversations |
| 111 | +- `/` and `/{id}` - Serves the chat UI |
| 112 | +- `/api/chat` - Chat endpoint (POST, OPTIONS) |
| 113 | +- `/api/configure` - Frontend configuration (GET) |
| 114 | +- `/api/health` - Health check (GET) |
145 | 115 |
|
146 | | -!!! note "Memory Tool Requirements" |
147 | | - The `memory` tool requires the agent to have memory configured via the |
148 | | - `memory` parameter when creating the agent. It cannot be enabled via |
149 | | - the CLI `-t memory` flag alone - an agent with memory must be provided |
150 | | - via `--agent`. |
| 116 | +The app cannot currently be mounted at a subpath (e.g., `/chat`) because the UI expects these routes at the root. You can add additional routes to the app, but avoid conflicts with these reserved paths. |
0 commit comments