-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Add Agent.to_web() method and web chat UI #3456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 56 commits
1cfa48e
d83caa5
bfffd4b
055e120
6bc8b16
32f7e1d
cf0e177
e7f44eb
c4ffde3
0595c27
0d24941
e5b30c2
f2dd19a
8ca7a27
fa3bb5f
e45c93f
f90b570
da8032c
0ab07b6
191897f
1faae3f
8423e89
a32c15a
91f9533
441d6a0
558985f
85f63bc
cd91e81
a132f26
943c7a8
831bdf3
125c059
025f1b5
0701b22
40b5c78
0673277
974bac2
4b58307
74f09e9
897e4e4
10d32fe
1c93cf0
b60f2ff
ee21cfb
cf1da90
372db8b
32cc5c5
48094d2
cd1e683
c1ba780
6984dfd
cf54985
106c8b9
f491e57
16e36dc
48bd838
b45156c
3733a56
b57fb38
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,57 +25,103 @@ export OPENAI_API_KEY='your-api-key-here' | |
| Then with [`uvx`](https://docs.astral.sh/uv/guides/tools/), run: | ||
|
|
||
| ```bash | ||
| uvx clai | ||
| uvx clai chat | ||
| ``` | ||
|
|
||
| Or to install `clai` globally [with `uv`](https://docs.astral.sh/uv/guides/tools/#installing-tools), run: | ||
|
|
||
| ```bash | ||
| uv tool install clai | ||
| ... | ||
| clai | ||
| clai chat | ||
| ``` | ||
|
|
||
| Or with `pip`, run: | ||
|
|
||
| ```bash | ||
| pip install clai | ||
| ... | ||
| clai | ||
| clai chat | ||
| ``` | ||
|
|
||
| Either way, running `clai` will start an interactive session where you can chat with the AI model. Special commands available in interactive mode: | ||
| Either way, running `clai chat` will start an interactive session where you can chat with the AI model. Special commands available in interactive mode: | ||
|
|
||
| - `/exit`: Exit the session | ||
| - `/markdown`: Show the last response in markdown format | ||
| - `/multiline`: Toggle multiline input mode (use Ctrl+D to submit) | ||
| - `/cp`: Copy the last response to clipboard | ||
|
|
||
| ## Web Chat UI | ||
|
|
||
| Launch a web-based chat interface for your agent: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's first have an example without an agent, to show that it will work that way as well |
||
|
|
||
| ```bash | ||
| clai web --agent module:agent_variable | ||
| ``` | ||
|
|
||
|  | ||
|
|
||
| For example, if you have an agent defined in `my_agent.py`: | ||
|
|
||
| ```python | ||
| from pydantic_ai import Agent | ||
|
|
||
| my_agent = Agent('openai:gpt-5', system_prompt='You are a helpful assistant.') | ||
dsfaccini marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| Launch the web UI with: | ||
|
|
||
| ```bash | ||
| clai web --agent my_agent:my_agent | ||
| ``` | ||
|
|
||
| This will start a web server (default: http://127.0.0.1:7932) with a chat interface for your agent. | ||
|
|
||
| ### Web Command Options | ||
|
|
||
| - `--agent`, `-a`: Agent to serve in `module:variable` format | ||
| - `--model`, `-m`: Model to make available (repeatable, agent's model is default if present) | ||
dsfaccini marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - `--tool`, `-t`: [Builtin tool](https://ai.pydantic.dev/builtin-tools/) to enable (repeatable). See [available tools](https://ai.pydantic.dev/ui/web/#builtin-tool-support). | ||
dsfaccini marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - `--instructions`, `-i`: System instructions. In generic mode (no `--agent`), these are the agent instructions. With `--agent`, these are passed as extra instructions to each run. | ||
| - `--host`: Host to bind the server to (default: 127.0.0.1) | ||
| - `--port`: Port to bind the server to (default: 7932) | ||
|
|
||
| ### Using with Models and Tools | ||
|
|
||
| You can specify which models and builtin tools are available in the UI via CLI flags: | ||
|
|
||
| ```bash | ||
| # Generic agent with specific models and tools | ||
| clai web -m openai:gpt-5 -m anthropic:claude-sonnet-4-5 -t web_search -t code_execution | ||
|
|
||
| # Custom agent with additional models | ||
| clai web --agent my_agent:my_agent -m openai:gpt-5 -m google:gemini-2.5-pro | ||
|
|
||
| # Generic agent with system instructions | ||
| clai web -m openai:gpt-5 -i 'You are a helpful coding assistant' | ||
|
|
||
| # Custom agent with extra instructions for each run | ||
| clai web --agent my_agent:my_agent -i 'Always respond in Spanish' | ||
| ``` | ||
|
|
||
dsfaccini marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| When using `--agent`, the agent's configured model becomes the default. CLI models (`-m`) are additional options. Without `--agent`, the first `-m` model is the default. | ||
|
|
||
| For full documentation, see [Web Chat UI](https://ai.pydantic.dev/ui/web/). | ||
|
|
||
| ## Help | ||
|
|
||
| ``` | ||
| usage: clai [-h] [-m [MODEL]] [-a AGENT] [-l] [-t [CODE_THEME]] [--no-stream] [--version] [prompt] | ||
| usage: clai [-h] [-l] [--version] {chat,web} ... | ||
|
|
||
| Pydantic AI CLI v... | ||
|
|
||
| Special prompts: | ||
| * `/exit` - exit the interactive mode (ctrl-c and ctrl-d also work) | ||
| * `/markdown` - show the last markdown output of the last question | ||
| * `/multiline` - toggle multiline mode | ||
| * `/cp` - copy the last response to clipboard | ||
|
|
||
| positional arguments: | ||
| prompt AI Prompt, if omitted fall into interactive mode | ||
| {chat,web} Available commands | ||
| chat Interactive chat with an AI model | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to the above, can we make this the default somehow instead of requiring it? |
||
| web Launch web chat UI for an agent | ||
|
|
||
| options: | ||
| -h, --help show this help message and exit | ||
| -m [MODEL], --model [MODEL] | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing all of this makes this |
||
| Model to use, in format "<provider>:<model>" e.g. "openai:gpt-5" or "anthropic:claude-sonnet-4-5". Defaults to "openai:gpt-5". | ||
| -a AGENT, --agent AGENT | ||
| Custom Agent to use, in format "module:variable", e.g. "mymodule.submodule:my_agent" | ||
| -l, --list-models List all available models and exit | ||
| -t [CODE_THEME], --code-theme [CODE_THEME] | ||
| Which colors to use for code, can be "dark", "light" or any theme from pygments.org/styles/. Defaults to "dark" which works well on dark terminals. | ||
| --no-stream Disable streaming from the model | ||
| --version Show version and exit | ||
| -h, --help show this help message and exit | ||
| -l, --list-models List all available models and exit | ||
| --version Show version and exit | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -22,46 +22,105 @@ export OPENAI_API_KEY='your-api-key-here' | |||||
| Then with [`uvx`](https://docs.astral.sh/uv/guides/tools/), run: | ||||||
|
|
||||||
| ```bash | ||||||
| uvx clai | ||||||
| uvx clai chat | ||||||
dsfaccini marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| ``` | ||||||
|
|
||||||
| Or to install `clai` globally [with `uv`](https://docs.astral.sh/uv/guides/tools/#installing-tools), run: | ||||||
|
|
||||||
| ```bash | ||||||
| uv tool install clai | ||||||
| ... | ||||||
| clai | ||||||
| clai chat | ||||||
| ``` | ||||||
|
|
||||||
| Or with `pip`, run: | ||||||
|
|
||||||
| ```bash | ||||||
| pip install clai | ||||||
| ... | ||||||
| clai | ||||||
| clai chat | ||||||
| ``` | ||||||
|
|
||||||
| Either way, running `clai` will start an interactive session where you can chat with the AI model. Special commands available in interactive mode: | ||||||
| Either way, running `clai chat` will start an interactive session where you can chat with the AI model. Special commands available in interactive mode: | ||||||
|
|
||||||
| - `/exit`: Exit the session | ||||||
| - `/markdown`: Show the last response in markdown format | ||||||
| - `/multiline`: Toggle multiline input mode (use Ctrl+D to submit) | ||||||
| - `/cp`: Copy the last response to clipboard | ||||||
|
|
||||||
| ### Web Chat UI | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a lot of duplication here with
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I wasn't sure about it as well, I thought there maybe be people who look more at the repo than the docs, I know I sometimes do, so I left it in both places, but I can just link to the docs from the readme. |
||||||
|
|
||||||
| Launch a web-based chat interface for your agent: | ||||||
|
|
||||||
| ```bash | ||||||
| clai web --agent module:agent_variable | ||||||
| ``` | ||||||
|
|
||||||
| For example, if you have an agent defined in `my_agent.py`: | ||||||
|
|
||||||
| ```python | ||||||
| from pydantic_ai import Agent | ||||||
|
|
||||||
| my_agent = Agent('openai:gpt-5', instructions='You are a helpful assistant.') | ||||||
| ``` | ||||||
|
|
||||||
| Launch the web UI with: | ||||||
|
|
||||||
| ```bash | ||||||
| clai web --agent my_agent:my_agent | ||||||
| ``` | ||||||
|
|
||||||
| This will start a web server (default: http://127.0.0.1:7932) with a chat interface for your agent. | ||||||
|
|
||||||
| #### CLI Options | ||||||
|
|
||||||
| ```bash | ||||||
| # With a custom agent | ||||||
| clai web --agent my_module:my_agent | ||||||
|
|
||||||
| # With specific models (first is default when no --agent) | ||||||
| clai web -m openai:gpt-5 -m anthropic:claude-sonnet-4-5 | ||||||
|
|
||||||
| # With builtin tools | ||||||
| clai web -m openai:gpt-5 -t web_search -t code_execution | ||||||
|
|
||||||
| # Generic agent with system instructions | ||||||
| clai web -m openai:gpt-5 -i 'You are a helpful coding assistant' | ||||||
|
|
||||||
| # Custom agent with extra instructions for each run | ||||||
| clai web --agent my_module:my_agent -i 'Always respond in Spanish' | ||||||
| ``` | ||||||
|
|
||||||
| | Option | Description | | ||||||
| |--------|-------------| | ||||||
| | `--agent`, `-a` | Agent to serve in `module:variable` format | | ||||||
| | `--model`, `-m` | Model to make available (repeatable, agent's model is default if present) | | ||||||
| | `--tool`, `-t` | [Builtin tool](builtin-tools.md) to enable (repeatable). See [available tools](ui/web.md#builtin-tool-support). | | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some of the notes from above also apply here |
||||||
| | `--instructions`, `-i` | System instructions. In generic mode (no `--agent`), these are the agent instructions. With `--agent`, these are passed as extra instructions to each run. | | ||||||
| | `--host` | Host to bind server (default: 127.0.0.1) | | ||||||
| | `--port` | Port to bind server (default: 7932) | | ||||||
|
|
||||||
| !!! note "Memory Tool" | ||||||
| The `memory` tool requires the agent to have memory configured and cannot be enabled via `-t memory` alone. An agent with memory must be provided via `--agent`. | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's link to the docs that explain this |
||||||
|
|
||||||
| For programmatic usage with `Agent.to_web()`, see the [Web UI documentation](ui/web.md). | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| ### Help | ||||||
|
|
||||||
| To get help on the CLI, use the `--help` flag: | ||||||
|
|
||||||
| ```bash | ||||||
| uvx clai --help | ||||||
| uvx clai chat --help | ||||||
| uvx clai web --help | ||||||
| ``` | ||||||
|
|
||||||
| ### Choose a model | ||||||
|
|
||||||
| You can specify which model to use with the `--model` flag: | ||||||
|
|
||||||
| ```bash | ||||||
| uvx clai --model anthropic:claude-sonnet-4-0 | ||||||
| uvx clai chat --model anthropic:claude-sonnet-4-0 | ||||||
| ``` | ||||||
|
|
||||||
| (a full list of models available can be printed with `uvx clai --list-models`) | ||||||
|
|
@@ -79,7 +138,7 @@ agent = Agent('openai:gpt-5', instructions='You always respond in Italian.') | |||||
| Then run: | ||||||
|
|
||||||
| ```bash | ||||||
| uvx clai --agent custom_agent:agent "What's the weather today?" | ||||||
| uvx clai chat --agent custom_agent:agent "What's the weather today?" | ||||||
| ``` | ||||||
|
|
||||||
| The format must be `module:variable` where: | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| # Web Chat UI | ||
|
|
||
| Pydantic AI includes a built-in web chat interface that you can use to interact with your agents through a browser. | ||
|
|
||
| <video src="https://github.com/user-attachments/assets/8a1c90dc-f62b-4e35-9d66-59459b45790d" autoplay loop muted playsinline></video> | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's just have a screenshot; I like videos but this one takes too many seconds to get to point, shows an error first, and has a typo in the initial prompt 😄 |
||
|
|
||
| ## Installation | ||
|
|
||
| Install the `web` extra (installs Starlette): | ||
|
|
||
| ```bash | ||
| pip/uv-add 'pydantic-ai-slim[web]' | ||
| ``` | ||
|
|
||
| For CLI usage with `clai web`, see the [CLI documentation](../cli.md#web-chat-ui). | ||
|
|
||
| ## Usage | ||
|
|
||
| Create a web app from an agent instance using [`Agent.to_web()`][pydantic_ai.agent.Agent.to_web]: | ||
|
|
||
| === "Using Model Names" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We haven't explained yet what these model names do, so we should start with a simple example that just does |
||
|
|
||
| ```python | ||
| from pydantic_ai import Agent | ||
| from pydantic_ai.builtin_tools import WebSearchTool | ||
|
|
||
| model = 'openai:gpt-5' | ||
| agent = Agent(model) | ||
|
|
||
| @agent.tool_plain | ||
| def get_weather(city: str) -> str: | ||
| return f'The weather in {city} is sunny' | ||
|
|
||
| # Create app with model names (their display names are auto-generated) | ||
| app = agent.to_web( | ||
| models=['openai:gpt-5', 'anthropic:claude-sonnet-4-5'], | ||
| builtin_tools=[WebSearchTool()], | ||
| ) | ||
|
|
||
| # Or with custom display labels | ||
| app = agent.to_web( | ||
| models={'GPT 5': 'openai:gpt-5', 'Claude': 'anthropic:claude-sonnet-4-5'}, | ||
| builtin_tools=[WebSearchTool()], | ||
| ) | ||
| ``` | ||
|
|
||
| === "Using Model Instances" | ||
|
|
||
| ```python | ||
| from pydantic_ai import Agent | ||
| from pydantic_ai.builtin_tools import WebSearchTool | ||
| from pydantic_ai.models.anthropic import AnthropicModel | ||
| from pydantic_ai.models.openai import OpenAIChatModel | ||
|
|
||
| # Create separate models with their own custom configuration | ||
| anthropic_model = AnthropicModel('claude-sonnet-4-5') | ||
| openai_model = OpenAIChatModel('gpt-5', provider='openai') | ||
|
|
||
| agent = Agent(openai_model) | ||
|
|
||
| @agent.tool_plain | ||
| def get_weather(city: str) -> str: | ||
| return f'The weather in {city} is sunny' | ||
|
|
||
| # Use the instances directly | ||
| app = agent.to_web( | ||
| models=[openai_model, anthropic_model], | ||
| builtin_tools=[WebSearchTool()], | ||
| ) | ||
|
|
||
| # Or mix instances and strings with custom labels | ||
| app = agent.to_web( | ||
| models={'Custom GPT': openai_model, 'Claude': 'anthropic:claude-sonnet-4-5'}, | ||
| builtin_tools=[WebSearchTool()], | ||
| ) | ||
|
|
||
| # With extra instructions passed to each run | ||
| app = agent.to_web( | ||
| models=[openai_model], | ||
| instructions='Always respond in a friendly tone.', | ||
| ) | ||
| ``` | ||
|
|
||
| The returned Starlette app can be run with any ASGI server: | ||
|
|
||
| ```bash | ||
| uvicorn my_module:app --host 0.0.0.0 --port 8080 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use the same port the CLI uses |
||
| ``` | ||
|
|
||
| ## Builtin Tool Support | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to what I wrote above, a separate section makes sense, but we need to explain the feature first instead of diving straight into implementation details like "Builtin tool support is automatically determined from each model's profile". So something like, "you can can specify a list of built-in tools that will be shown as options to the user, if the selected model supports it" |
||
|
|
||
| Builtin tool support is automatically determined from each model's profile. The UI will only show tools that the selected model supports. | ||
|
|
||
| Available [builtin tools](../builtin-tools.md): | ||
|
|
||
| - `web_search` - Web search capability ([`WebSearchTool`][pydantic_ai.builtin_tools.WebSearchTool]) | ||
| - `code_execution` - Code execution in a sandbox ([`CodeExecutionTool`][pydantic_ai.builtin_tools.CodeExecutionTool]) | ||
| - `image_generation` - Image generation ([`ImageGenerationTool`][pydantic_ai.builtin_tools.ImageGenerationTool]) | ||
| - `web_fetch` - Fetch content from URLs ([`WebFetchTool`][pydantic_ai.builtin_tools.WebFetchTool]) | ||
| - `memory` - Persistent memory across conversations ([`MemoryTool`][pydantic_ai.builtin_tools.MemoryTool]) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will get outdated, so I'd much prefer to only link to the other docs and then only explicitly mention the tools that aren't supported, like Those other docs don't currently mention the string names of the tools, but we don't support strings on |
||
|
|
||
| !!! note "Memory Tool Requirements" | ||
| The `memory` tool requires the agent to have memory configured via the | ||
| `memory` parameter when creating the agent. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is confusing/incorrect: there's no The |
||
|
|
||
|
|
||
| ## Reserved Routes | ||
|
|
||
| The web UI app uses the following routes which should not be overwritten: | ||
|
|
||
| - `/` and `/{id}` - Serves the chat UI | ||
| - `/api/chat` - Chat endpoint (POST, OPTIONS) | ||
| - `/api/configure` - Frontend configuration (GET) | ||
| - `/api/health` - Health check (GET) | ||
|
|
||
| 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. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,10 +97,12 @@ nav: | |
| - Overview: ui/overview.md | ||
| - AG-UI: ui/ag-ui.md | ||
| - Vercel AI: ui/vercel-ai.md | ||
| - Web Chat UI: ui/web.md | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To the user, this is a Pydantic AI feature, not a UI event stream integration (even if it technically uses that functionality), so it shouldn't be under this section. Instead, let's make it its own dedicated page under |
||
| - Agent2Agent (A2A): a2a.md | ||
|
|
||
| - Related Packages: | ||
| - Clai: cli.md | ||
| - Clai: | ||
| - CLI: cli.md | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please revert this change, it can be its own item |
||
|
|
||
| - Examples: | ||
| - Setup: examples/setup.md | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm can we keep
claiworking as it did, and not require this new argument?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can, I though this would be cleaner/less confusing