Skip to content

Commit

Permalink
Multi-agent application documentation (#541)
Browse files Browse the repository at this point in the history
Co-authored-by: Sydney Runkle <[email protected]>
Co-authored-by: David Montague <[email protected]>
  • Loading branch information
3 people authored Dec 31, 2024
1 parent 6ee9d15 commit 4537c07
Show file tree
Hide file tree
Showing 15 changed files with 945 additions and 192 deletions.
6 changes: 3 additions & 3 deletions docs/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ You can also pass messages from previous runs to continue a conversation or prov

#### Usage Limits

PydanticAI offers a [`settings.UsageLimits`][pydantic_ai.settings.UsageLimits] structure to help you limit your
PydanticAI offers a [`UsageLimits`][pydantic_ai.usage.UsageLimits] structure to help you limit your
usage (tokens and/or requests) on model runs.

You can apply these settings by passing the `usage_limits` argument to the `run{_sync,_stream}` functions.
Expand All @@ -118,7 +118,7 @@ Consider the following example, where we limit the number of response tokens:
```py
from pydantic_ai import Agent
from pydantic_ai.exceptions import UsageLimitExceeded
from pydantic_ai.settings import UsageLimits
from pydantic_ai.usage import UsageLimits

agent = Agent('claude-3-5-sonnet-latest')

Expand Down Expand Up @@ -150,7 +150,7 @@ from typing_extensions import TypedDict

from pydantic_ai import Agent, ModelRetry
from pydantic_ai.exceptions import UsageLimitExceeded
from pydantic_ai.settings import UsageLimits
from pydantic_ai.usage import UsageLimits


class NeverResultType(TypedDict):
Expand Down
3 changes: 3 additions & 0 deletions docs/api/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `pydantic_ai.usage`

::: pydantic_ai.usage
40 changes: 2 additions & 38 deletions docs/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ async def application_code(prompt: str) -> str: # (3)!
3. Application code that calls the agent, in a real application this might be an API endpoint.
4. Call the agent from within the application code, in a real application this call might be deep within a call stack. Note `app_deps` here will NOT be used when deps are overridden.

_(This example is complete, it can be run "as is")_

```python {title="test_joke_app.py" hl_lines="10-12" call_name="test_application_code"}
from joke_app import MyDeps, application_code, joke_agent

Expand All @@ -296,44 +298,6 @@ async def test_application_code():
3. Override the dependencies of the agent for the duration of the `with` block, `test_deps` will be used when the agent is run.
4. Now we can safely call our application code, the agent will use the overridden dependencies.

## Agents as dependencies of other Agents

Since dependencies can be any python type, and agents are just python objects, agents can be dependencies of other agents.

```python {title="agents_as_dependencies.py"}
from dataclasses import dataclass

from pydantic_ai import Agent, RunContext


@dataclass
class MyDeps:
factory_agent: Agent[None, list[str]]


joke_agent = Agent(
'openai:gpt-4o',
deps_type=MyDeps,
system_prompt=(
'Use the "joke_factory" to generate some jokes, then choose the best. '
'You must return just a single joke.'
),
)

factory_agent = Agent('gemini-1.5-pro', result_type=list[str])


@joke_agent.tool
async def joke_factory(ctx: RunContext[MyDeps], count: int) -> str:
r = await ctx.deps.factory_agent.run(f'Please generate {count} jokes.')
return '\n'.join(r.data)


result = joke_agent.run_sync('Tell me a joke.', deps=MyDeps(factory_agent))
print(result.data)
#> Did you hear about the toothpaste scandal? They called it Colgate.
```

## Examples

The following examples demonstrate how to use dependencies in PydanticAI:
Expand Down
41 changes: 41 additions & 0 deletions docs/examples/flight-booking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Example of a multi-agent flow where one agent delegates work to another, then hands off control to a third agent.

Demonstrates:

* [agent delegation](../multi-agent-applications.md#agent-delegation)
* [programmatic agent hand-off](../multi-agent-applications.md#programmatic-agent-hand-off)
* [usage limits](../agents.md#usage-limits)

In this scenario, a group of agents work together to find the best flight for a user.

The control flow for this example can be summarised as follows:

```mermaid
graph TD
START --> search_agent("search agent")
search_agent --> extraction_agent("extraction agent")
extraction_agent --> search_agent
search_agent --> human_confirm("human confirm")
human_confirm --> search_agent
search_agent --> FAILED
human_confirm --> find_seat_function("find seat function")
find_seat_function --> human_seat_choice("human seat choice")
human_seat_choice --> find_seat_agent("find seat agent")
find_seat_agent --> find_seat_function
find_seat_function --> buy_flights("buy flights")
buy_flights --> SUCCESS
```

## Running the Example

With [dependencies installed and environment variables set](./index.md#usage), run:

```bash
python/uv-run -m pydantic_ai_examples.flight_booking
```

## Example Code

```python {title="flight_booking.py"}
#! examples/pydantic_ai_examples/flight_booking.py
```
4 changes: 4 additions & 0 deletions docs/extra/tweaks.css
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,7 @@ img.index-header {
min-height: 120px;
margin-bottom: 10px;
}

.mermaid {
text-align: center;
}
Loading

0 comments on commit 4537c07

Please sign in to comment.