-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Add new capabilities abstraction + make agents serializable #4640
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 all commits
fbdfd8d
68b4036
c847585
00be4ca
33604e6
01a94c3
a735b73
9001b1a
c66ea20
9460ea5
a7c70d6
282819c
b635b48
9e28bc1
94d0329
2b30c3a
3d8b3a6
d8d3aba
598a8cf
37e4d1f
b91be81
8392293
a539b4e
e567e98
df4fe1a
4e01113
99ae9c9
32a0ce7
561eeda
2ac4084
84cfac2
425c3e4
f8a8e9b
f56d4fb
819f73b
e2c7d72
00379df
b731b91
d2cbedd
4b48e77
058f3c7
4531455
c7ee11e
8587253
b2ffa12
0f1ec96
5af0a9c
e962092
b8b639d
e45c512
f7ef02e
b083d87
a3a92c9
e9542e2
dd4d870
eec5bf2
485ec13
c4ae7fe
c192ecc
1e2b243
ca6d0c4
4fb43b0
60f2bdb
999a1e0
b845907
a58d1c6
40ae5fe
8317926
f19618d
6fa2dd9
afdadd0
7ec47c2
2058046
371e57d
cd71167
2247334
19b93b8
6782caa
2fae249
804d001
b237c36
367d5ba
e89d1f1
ba58a0b
2ee74f1
b7192c1
4ed9df0
6e703ef
5c693a7
5e2128d
312fac2
eebc4e4
4d85cf0
5d772e7
37041dd
a052174
310c3ce
580a729
2c6dfcf
6daf13f
8c1c2a2
96123be
6088c22
761526f
aa61789
c04a93b
479cdd1
4fe4afe
d912f1d
abadc4d
0881700
973193a
a36c7f5
b745ef0
e2a48f8
8cf33c4
d7a9aa0
a97b5d9
023f3cd
9a727e7
0aecad0
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 |
|---|---|---|
|
|
@@ -309,13 +309,6 @@ async def main(): | |
| print(nodes) | ||
| """ | ||
| [ | ||
| UserPromptNode( | ||
| user_prompt='What is the capital of France?', | ||
| instructions_functions=[], | ||
| system_prompts=(), | ||
| system_prompt_functions=[], | ||
| system_prompt_dynamic_functions={}, | ||
| ), | ||
| ModelRequestNode( | ||
| request=ModelRequest( | ||
| parts=[ | ||
|
|
@@ -545,7 +538,6 @@ if __name__ == '__main__': | |
| print(output_messages) | ||
| """ | ||
| [ | ||
| '=== UserPromptNode: What will the weather be like in Paris on Tuesday? ===', | ||
| '=== ModelRequestNode: streaming partial request tokens ===', | ||
| "[Request] Starting part 0: ToolCallPart(tool_name='weather_forecast', tool_call_id='0001')", | ||
| '[Request] Part 0 args delta: {"location":"Pa', | ||
|
|
@@ -712,6 +704,33 @@ print(result_sync.output) | |
|
|
||
| The final request uses `temperature=0.0` (run-time), `max_tokens=500` (from model), demonstrating how settings merge with run-time taking precedence. | ||
|
|
||
| ##### Dynamic model settings | ||
|
|
||
| Both agent-level and run-level `model_settings` accept a callable that receives a | ||
| [`RunContext`][pydantic_ai.tools.RunContext] and returns [`ModelSettings`][pydantic_ai.settings.ModelSettings]. | ||
| The callable is invoked before each model request, so settings can vary per step. | ||
| The current resolved settings so far are available via `ctx.model_settings` inside the callable. | ||
|
Contributor
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. The statement "The current resolved settings so far are available via
The numbered list below (lines 724-727) is good, but the prose on line 720 should explicitly note this position-dependence, e.g. "Inside a callable at a given layer,
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. Updated prose to explicitly note position-dependence of |
||
|
|
||
| Settings are resolved in layers, each merged on top of the previous: | ||
|
|
||
| 1. **Model defaults** (`model.settings`) | ||
| 2. **Agent-level** (`Agent(model_settings=...)`) | ||
| 3. **Capability-level** (e.g. from `Thinking()`, `ModelSettings(...)` capabilities) | ||
|
Contributor
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. The capabilities abstraction is the headline feature of this PR, but Even for a draft PR, adding at least a basic "Capabilities" section in
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. Same — docs page coming with hooks/toolset-state merge.
Contributor
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. The capabilities abstraction is the headline feature of this PR, but it's only mentioned here in passing (in the model settings resolution list). There's no dedicated section explaining what capabilities are, how to use the Even for a draft PR, I'd recommend adding at least a stub "Capabilities" section (or a standalone
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. Dedicated capabilities docs page will come once hooks and toolset-state are merged. |
||
| 4. **Run-level** (`agent.run(model_settings=...)`) | ||
|
|
||
| Inside a callable, `ctx.model_settings` contains the merged result of all *previous* layers (position-dependent). For example, an agent-level callable sees only model defaults, while a run-level callable sees model defaults + agent-level + capability-level settings. To reset a field set by a previous layer, set it explicitly (e.g. `{'temperature': None}`). | ||
|
|
||
| ```python | ||
| from pydantic_ai import Agent, ModelSettings | ||
|
|
||
| agent = Agent( | ||
| 'test', | ||
| model_settings=lambda ctx: ModelSettings( | ||
| temperature=0.0 if ctx.run_step <= 1 else 0.7, | ||
| ), | ||
| ) | ||
| ``` | ||
|
|
||
| !!! note "Model Settings Support" | ||
| Model-level settings are supported by all concrete model implementations (OpenAI, Anthropic, Google, etc.). Wrapper models like [`FallbackModel`](models/overview.md#fallback-model), [`WrapperModel`][pydantic_ai.models.wrapper.WrapperModel], and [`InstrumentedModel`][pydantic_ai.models.instrumented.InstrumentedModel] don't have their own settings - they use the settings of their underlying models. | ||
|
|
||
|
|
||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| from importlib.metadata import version as _metadata_version | ||
|
|
||
| from ._template import TemplateStr | ||
| from .agent import ( | ||
| Agent, | ||
| CallToolsNode, | ||
|
|
@@ -42,6 +43,9 @@ | |
| ModelAPIError, | ||
| ModelHTTPError, | ||
| ModelRetry, | ||
| SkipModelRequest, | ||
| SkipToolExecution, | ||
| SkipToolValidation, | ||
| UnexpectedModelBehavior, | ||
| UsageLimitExceeded, | ||
| UserError, | ||
|
|
@@ -115,6 +119,7 @@ | |
| from .tools import DeferredToolRequests, DeferredToolResults, RunContext, Tool, ToolApproved, ToolDefinition, ToolDenied | ||
| from .toolsets import ( | ||
| AbstractToolset, | ||
| AgentToolset, | ||
| ApprovalRequiredToolset, | ||
| CombinedToolset, | ||
| ExternalToolset, | ||
|
|
@@ -161,6 +166,9 @@ | |
| 'ModelHTTPError', | ||
| 'FallbackExceptionGroup', | ||
| 'IncompleteToolCall', | ||
| 'SkipModelRequest', | ||
| 'SkipToolExecution', | ||
| 'SkipToolValidation', | ||
| 'UnexpectedModelBehavior', | ||
| 'UsageLimitExceeded', | ||
| 'UserError', | ||
|
|
@@ -233,6 +241,7 @@ | |
| 'ToolDenied', | ||
| # toolsets | ||
| 'AbstractToolset', | ||
| 'AgentToolset', | ||
| 'ApprovalRequiredToolset', | ||
| 'CombinedToolset', | ||
| 'ExternalToolset', | ||
|
|
@@ -260,6 +269,8 @@ | |
| 'PromptedOutput', | ||
| 'TextOutput', | ||
| 'StructuredDict', | ||
| # template | ||
| 'TemplateStr', | ||
|
Contributor
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.
Consider adding
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. Consistent with AgentMetadata — not exported from top-level. |
||
| # format_prompt | ||
| 'format_as_xml', | ||
| # settings | ||
|
|
||
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.
The docs say "The current resolved settings so far are available via
ctx.model_settingsinside the callable" — but the semantics ofctx.model_settingsdepend on where in the resolution chain the callable is. An agent-level callable sees only model defaults, while a run-level callable sees model defaults merged with agent settings. This should be documented more precisely, e.g.:"When called at the agent level,
ctx.model_settingscontains the model's default settings. When called at the run level, it contains the model defaults merged with the agent-level settings."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.
Updated docs to explain the full resolution order: model defaults → agent-level → capability-level → run-level, with what
ctx.model_settingscontains at each stage.