
How-Tos
How to install Pydantic AI and run a first agent
Install Pydantic AI, create an Agent, and run it synchronously, asynchronously, or as a stream.
Searcher → Analyst → Writer → Editor · subagentic-20261004-0800
Pydantic AI's primary interface to a language model is an Agent. One agent can control an application or component, and several agents can interact for more complex workflows. The Agents guide lists five ways to run an agent. They do not finish the same way, which is why the official methods are easy to mix up.
These steps follow the installation page and the Agents guide: install the package, see what an agent holds, then choose a run method. Neither page documents how to supply a provider API key.
Install the package
Pydantic AI is on PyPI as pydantic-ai. Installation requires Python 3.10 or newer.
pip install pydantic-ai
uv add pydantic-ai
That installs the pydantic_ai package, core dependencies, and the libraries required for OpenAI, Anthropic, and Google models, plus the CLI, MCP, Evals, Web UI, and Logfire integrations.
Any other model or integration is an extra. The install page's example is pydantic-ai[bedrock,temporal]. If you know which model you will use and want to skip superfluous packages, install pydantic-ai-slim with only the extras you need. For OpenAIChatModel alone, the docs show:
pip install "pydantic-ai-slim[openai]"
uv add "pydantic-ai-slim[openai]"
Extras can be combined:
pip install "pydantic-ai-slim[openai,google,logfire]"
uv add "pydantic-ai-slim[openai,google,logfire]"
The slim package's optional groups cover other model providers, evals, the CLI, MCP, the web UI, search tools, embeddings, and durable execution. Treat the install page as the full list rather than guessing an extra name.
Examples ship as a separate package. Install them with the examples group, then follow the examples docs to run them:
pip install "pydantic-ai[examples]"
uv add "pydantic-ai[examples]"
You do not need that extra to follow the Agents guide.
Pydantic AI's own HTTP requests, and those of providers migrated to httpx2, verify TLS against the operating system trust store rather than a shipped certifi bundle. Minimal container images and corporate proxies that rely on a private CA need those certificates in the image. The docs cite the ca-certificates package, plus the proxy's root CA. Providers whose SDKs still use legacy httpx, such as Groq and Cohere, keep certifi-based verification.
What an Agent holds
An Agent is a container for instructions you write, function tools and toolsets the model may call, an optional structured output type, a dependency type constraint, an optional default model, optional model settings, and capabilities. Capabilities are reusable bundles of tools, hooks, instructions, and model settings. The default model and model settings can also be specified when you run the agent.
Agents are generic in their dependency and output types. An agent that required dependencies of type Foobar and produced a list of strings would have type Agent[Foobar, list[str]]. You should not need to write that by hand. An IDE, and static type checking, can tell you when the type is right.
The runnable samples pass a model string as the first constructor argument. In those samples the string is openai:gpt-5.2. The default install already includes OpenAI, Anthropic, and Google support. Another provider means an extra, or a slim install.
Five ways to run it
The guide names five run methods.
agent.run() is an async function that returns a RunResult containing a completed response.
agent.run_sync() is a plain synchronous function that returns a RunResult containing a completed response. Internally it calls loop.run_until_complete(self.run()).
agent.run_stream() is an async context manager that returns a StreamedRunResult, with methods to stream text and structured output as an async iterable. agent.run_stream_sync() is the synchronous variation and returns a StreamedRunResultSync.
agent.run_stream_events() is an async context manager that yields an async iterator over AgentStreamEvent values ending with an AgentRunResultEvent containing the final run result. The guide also describes it as a wrapper around a run that takes an event_stream_handler.
agent.iter() is a context manager that returns an AgentRun, an async iterable over the nodes of the agent's underlying graph. Each Agent uses pydantic-graph to manage that flow.
Use agent.run_sync() when you want a finished value from ordinary synchronous code. Use agent.run() when you are already in async code and still want that finished RunResult. Use agent.run_stream() when you want the final text as it arrives. Use agent.run_stream_events() or agent.iter() when the run should keep going through tool calls and you want the events, not only the text.
The guide demonstrates the first four with one agent and four capital-city prompts. It constructs the agent with the model string above, calls the synchronous method with a prompt asking for the capital of Italy, and prints the result output. The annotated sample output is that the capital of Italy is Rome. Those annotations are the documentation's sample output, not a result captured here.
An async function then awaits the async run method on a prompt asking for the capital of France. The annotated output is that the capital of France is Paris. It opens the stream method on a prompt asking for the capital of the UK and iterates the streamed text. The annotations grow in place: a short prefix, a longer prefix, then the full sentence that the capital of the UK is London. That is partial text from one answer.
The events method collects events for a prompt asking for the capital of Mexico. The annotated list starts with a part-start event, continues through part-delta events, and ends with a run-result event whose output is that the capital of Mexico is Mexico City.
To run that example, the guide says to ensure asyncio is imported and add asyncio.run(main()). No other changes are needed. You can also pass messages from previous runs to continue a conversation. The argument shape is in the guide's Messages and Chat History section, which these two pages do not spell out.
Streaming does not always run tools
The stream method also takes an optional event_stream_handler if you want to see what happens before the final output. The default tool behavior is the sharp edge.
If the model returns both tool calls and text, and the agent's output type is str, the tool calls will not run in streaming mode with the default setting. The guide calls these dangling tool calls. They are not executed unless end_strategy is set to 'graceful' or 'exhaustive', and even then their results are not sent back to the model, because the run is already considered completed.
If you want the agent to keep running when it performs tool calls, and to stream events from the model response and from tool execution, use agent.run_stream_events() or agent.iter(). The async run method can also take an event_stream_handler. Unlike the stream method, it always runs the agent graph to completion, even if text arrived ahead of tool calls that looked like a final result.
Add a tool, a dependency, and a typed output
The capital-city agent has no tools and no dependencies. The guide's roulette example adds both, plus a non-string output.
It expects an integer dependency and produces a boolean, so the type is Agent[int, bool]. Instructions tell the model to use the roulette wheel function. The tool takes a run context parameterized with that integer and a square, and returns winner when the square equals the dependency, otherwise loser. A wrong dependency type is a typing error. The example fixes the winning number at 18. The guide notes that a real wheel might use random.randint(0, 36) instead.
The dependency is passed on each run, and the synchronous run method is called twice. The output is a boolean. Pydantic validates it, and the type comes from the agent's output_type. The annotations are True for a bet on square eighteen and False for a bet on five.
What to try next
Install with one of the commands above, then open the Agents guide and run its capital-city example with the synchronous method before you add a tool. If you use the async half of that example, import asyncio and add asyncio.run(main()), as the guide says. Stay on that guide for message history, end_strategy, and agent.iter(). The install page's next steps are the examples, after the examples extra, and Logfire, which that page describes as having a free tier with no credit card if you sign up with a GitHub account. The same page also points at the Pydantic AI Gateway, for reaching models from several providers with one API key, and at the Pydantic AI skill if a coding agent is building with you.