pydantic-ai-slim 1.3.0__tar.gz → 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pydantic-ai-slim might be problematic. Click here for more details.

Files changed (138) hide show
  1. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/PKG-INFO +3 -3
  2. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/__init__.py +2 -0
  3. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_agent_graph.py +33 -14
  4. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_utils.py +8 -8
  5. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/agent/__init__.py +6 -18
  6. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/builtin_tools.py +71 -0
  7. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/temporal/__init__.py +11 -0
  8. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/temporal/_function_toolset.py +2 -1
  9. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/exceptions.py +1 -1
  10. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/messages.py +1 -1
  11. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/__init__.py +11 -3
  12. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/anthropic.py +130 -9
  13. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/google.py +26 -14
  14. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/openai.py +190 -13
  15. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/google.py +31 -2
  16. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/run.py +40 -24
  17. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/.gitignore +0 -0
  18. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/LICENSE +0 -0
  19. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/README.md +0 -0
  20. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/__main__.py +0 -0
  21. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_a2a.py +0 -0
  22. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_cli.py +0 -0
  23. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_function_schema.py +0 -0
  24. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_griffe.py +0 -0
  25. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_instrumentation.py +0 -0
  26. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_json_schema.py +0 -0
  27. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_mcp.py +0 -0
  28. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_otel_messages.py +0 -0
  29. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_output.py +0 -0
  30. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_parts_manager.py +0 -0
  31. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_run_context.py +0 -0
  32. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_system_prompt.py +0 -0
  33. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_thinking_part.py +0 -0
  34. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/_tool_manager.py +0 -0
  35. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/ag_ui.py +0 -0
  36. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/agent/abstract.py +0 -0
  37. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/agent/wrapper.py +0 -0
  38. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/common_tools/__init__.py +0 -0
  39. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/common_tools/duckduckgo.py +0 -0
  40. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/common_tools/tavily.py +0 -0
  41. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/direct.py +0 -0
  42. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/__init__.py +0 -0
  43. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/dbos/__init__.py +0 -0
  44. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/dbos/_agent.py +0 -0
  45. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/dbos/_mcp_server.py +0 -0
  46. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/dbos/_model.py +0 -0
  47. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/dbos/_utils.py +0 -0
  48. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/prefect/__init__.py +0 -0
  49. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/prefect/_agent.py +0 -0
  50. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/prefect/_cache_policies.py +0 -0
  51. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/prefect/_function_toolset.py +0 -0
  52. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/prefect/_mcp_server.py +0 -0
  53. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/prefect/_model.py +0 -0
  54. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/prefect/_toolset.py +0 -0
  55. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/prefect/_types.py +0 -0
  56. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/temporal/_agent.py +0 -0
  57. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/temporal/_logfire.py +0 -0
  58. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/temporal/_mcp_server.py +0 -0
  59. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/temporal/_model.py +0 -0
  60. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
  61. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/durable_exec/temporal/_toolset.py +0 -0
  62. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/ext/__init__.py +0 -0
  63. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/ext/aci.py +0 -0
  64. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/ext/langchain.py +0 -0
  65. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/format_prompt.py +0 -0
  66. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/mcp.py +0 -0
  67. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/bedrock.py +0 -0
  68. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/cohere.py +0 -0
  69. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/fallback.py +0 -0
  70. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/function.py +0 -0
  71. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/gemini.py +0 -0
  72. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/groq.py +0 -0
  73. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/huggingface.py +0 -0
  74. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/instrumented.py +0 -0
  75. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/mcp_sampling.py +0 -0
  76. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/mistral.py +0 -0
  77. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/test.py +0 -0
  78. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/models/wrapper.py +0 -0
  79. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/output.py +0 -0
  80. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/__init__.py +0 -0
  81. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/amazon.py +0 -0
  82. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/anthropic.py +0 -0
  83. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/cohere.py +0 -0
  84. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/deepseek.py +0 -0
  85. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/google.py +0 -0
  86. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/grok.py +0 -0
  87. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/groq.py +0 -0
  88. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/harmony.py +0 -0
  89. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/meta.py +0 -0
  90. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/mistral.py +0 -0
  91. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/moonshotai.py +0 -0
  92. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/openai.py +0 -0
  93. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/profiles/qwen.py +0 -0
  94. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/__init__.py +0 -0
  95. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/anthropic.py +0 -0
  96. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/azure.py +0 -0
  97. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/bedrock.py +0 -0
  98. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/cerebras.py +0 -0
  99. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/cohere.py +0 -0
  100. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/deepseek.py +0 -0
  101. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/fireworks.py +0 -0
  102. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/gateway.py +0 -0
  103. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/github.py +0 -0
  104. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/google_gla.py +0 -0
  105. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/google_vertex.py +0 -0
  106. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/grok.py +0 -0
  107. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/groq.py +0 -0
  108. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/heroku.py +0 -0
  109. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/huggingface.py +0 -0
  110. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/litellm.py +0 -0
  111. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/mistral.py +0 -0
  112. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/moonshotai.py +0 -0
  113. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/nebius.py +0 -0
  114. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/ollama.py +0 -0
  115. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/openai.py +0 -0
  116. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/openrouter.py +0 -0
  117. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/ovhcloud.py +0 -0
  118. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/together.py +0 -0
  119. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/providers/vercel.py +0 -0
  120. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/py.typed +0 -0
  121. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/result.py +0 -0
  122. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/retries.py +0 -0
  123. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/settings.py +0 -0
  124. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/tools.py +0 -0
  125. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/__init__.py +0 -0
  126. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/_dynamic.py +0 -0
  127. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/abstract.py +0 -0
  128. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/approval_required.py +0 -0
  129. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/combined.py +0 -0
  130. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/external.py +0 -0
  131. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/filtered.py +0 -0
  132. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/function.py +0 -0
  133. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/prefixed.py +0 -0
  134. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/prepared.py +0 -0
  135. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/renamed.py +0 -0
  136. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/toolsets/wrapper.py +0 -0
  137. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pydantic_ai/usage.py +0 -0
  138. {pydantic_ai_slim-1.3.0 → pydantic_ai_slim-1.5.0}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydantic-ai-slim
3
- Version: 1.3.0
3
+ Version: 1.5.0
4
4
  Summary: Agent Framework / shim to use Pydantic with LLMs, slim package
5
5
  Project-URL: Homepage, https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim
6
6
  Project-URL: Source, https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim
@@ -33,7 +33,7 @@ Requires-Dist: genai-prices>=0.0.35
33
33
  Requires-Dist: griffe>=1.3.2
34
34
  Requires-Dist: httpx>=0.27
35
35
  Requires-Dist: opentelemetry-api>=1.28.0
36
- Requires-Dist: pydantic-graph==1.3.0
36
+ Requires-Dist: pydantic-graph==1.5.0
37
37
  Requires-Dist: pydantic>=2.10
38
38
  Requires-Dist: typing-inspection>=0.4.0
39
39
  Provides-Extra: a2a
@@ -57,7 +57,7 @@ Requires-Dist: dbos>=1.14.0; extra == 'dbos'
57
57
  Provides-Extra: duckduckgo
58
58
  Requires-Dist: ddgs>=9.0.0; extra == 'duckduckgo'
59
59
  Provides-Extra: evals
60
- Requires-Dist: pydantic-evals==1.3.0; extra == 'evals'
60
+ Requires-Dist: pydantic-evals==1.5.0; extra == 'evals'
61
61
  Provides-Extra: google
62
62
  Requires-Dist: google-genai>=1.46.0; extra == 'google'
63
63
  Provides-Extra: groq
@@ -12,6 +12,7 @@ from .agent import (
12
12
  from .builtin_tools import (
13
13
  CodeExecutionTool,
14
14
  ImageGenerationTool,
15
+ MCPServerTool,
15
16
  MemoryTool,
16
17
  UrlContextTool,
17
18
  WebSearchTool,
@@ -213,6 +214,7 @@ __all__ = (
213
214
  'CodeExecutionTool',
214
215
  'ImageGenerationTool',
215
216
  'MemoryTool',
217
+ 'MCPServerTool',
216
218
  # output
217
219
  'ToolOutput',
218
220
  'NativeOutput',
@@ -20,7 +20,8 @@ from pydantic_ai._instrumentation import DEFAULT_INSTRUMENTATION_VERSION
20
20
  from pydantic_ai._tool_manager import ToolManager
21
21
  from pydantic_ai._utils import dataclasses_no_defaults_repr, get_union_args, is_async_callable, run_in_executor
22
22
  from pydantic_ai.builtin_tools import AbstractBuiltinTool
23
- from pydantic_graph import BaseNode, Graph, GraphRunContext
23
+ from pydantic_graph import BaseNode, GraphRunContext
24
+ from pydantic_graph.beta import Graph, GraphBuilder
24
25
  from pydantic_graph.nodes import End, NodeRunEndT
25
26
 
26
27
  from . import _output, _system_prompt, exceptions, messages as _messages, models, result, usage as _usage
@@ -588,7 +589,11 @@ class CallToolsNode(AgentNode[DepsT, NodeRunEndT]):
588
589
  # as the empty response and request will not create any items in the API payload,
589
590
  # in the hope the model will return a non-empty response this time.
590
591
  ctx.state.increment_retries(ctx.deps.max_result_retries, model_settings=ctx.deps.model_settings)
591
- self._next_node = ModelRequestNode[DepsT, NodeRunEndT](_messages.ModelRequest(parts=[]))
592
+ run_context = build_run_context(ctx)
593
+ instructions = await ctx.deps.get_instructions(run_context)
594
+ self._next_node = ModelRequestNode[DepsT, NodeRunEndT](
595
+ _messages.ModelRequest(parts=[], instructions=instructions)
596
+ )
592
597
  return
593
598
 
594
599
  text = ''
@@ -652,7 +657,11 @@ class CallToolsNode(AgentNode[DepsT, NodeRunEndT]):
652
657
  ctx.state.increment_retries(
653
658
  ctx.deps.max_result_retries, error=e, model_settings=ctx.deps.model_settings
654
659
  )
655
- self._next_node = ModelRequestNode[DepsT, NodeRunEndT](_messages.ModelRequest(parts=[e.tool_retry]))
660
+ run_context = build_run_context(ctx)
661
+ instructions = await ctx.deps.get_instructions(run_context)
662
+ self._next_node = ModelRequestNode[DepsT, NodeRunEndT](
663
+ _messages.ModelRequest(parts=[e.tool_retry], instructions=instructions)
664
+ )
656
665
 
657
666
  self._events_iterator = _run_stream()
658
667
 
@@ -1154,22 +1163,32 @@ def build_agent_graph(
1154
1163
  name: str | None,
1155
1164
  deps_type: type[DepsT],
1156
1165
  output_type: OutputSpec[OutputT],
1157
- ) -> Graph[GraphAgentState, GraphAgentDeps[DepsT, result.FinalResult[OutputT]], result.FinalResult[OutputT]]:
1166
+ ) -> Graph[
1167
+ GraphAgentState,
1168
+ GraphAgentDeps[DepsT, OutputT],
1169
+ UserPromptNode[DepsT, OutputT],
1170
+ result.FinalResult[OutputT],
1171
+ ]:
1158
1172
  """Build the execution [Graph][pydantic_graph.Graph] for a given agent."""
1159
- nodes = (
1160
- UserPromptNode[DepsT],
1161
- ModelRequestNode[DepsT],
1162
- CallToolsNode[DepsT],
1163
- SetFinalResult[DepsT],
1164
- )
1165
- graph = Graph[GraphAgentState, GraphAgentDeps[DepsT, Any], result.FinalResult[OutputT]](
1166
- nodes=nodes,
1173
+ g = GraphBuilder(
1167
1174
  name=name or 'Agent',
1168
1175
  state_type=GraphAgentState,
1169
- run_end_type=result.FinalResult[OutputT],
1176
+ deps_type=GraphAgentDeps[DepsT, OutputT],
1177
+ input_type=UserPromptNode[DepsT, OutputT],
1178
+ output_type=result.FinalResult[OutputT],
1170
1179
  auto_instrument=False,
1171
1180
  )
1172
- return graph
1181
+
1182
+ g.add(
1183
+ g.edge_from(g.start_node).to(UserPromptNode[DepsT, OutputT]),
1184
+ g.node(UserPromptNode[DepsT, OutputT]),
1185
+ g.node(ModelRequestNode[DepsT, OutputT]),
1186
+ g.node(CallToolsNode[DepsT, OutputT]),
1187
+ g.node(
1188
+ SetFinalResult[DepsT, OutputT],
1189
+ ),
1190
+ )
1191
+ return g.build(validate_graph_structure=False)
1173
1192
 
1174
1193
 
1175
1194
  async def _process_message_history(
@@ -147,7 +147,7 @@ async def group_by_temporal(
147
147
  aiterable: The async iterable to group.
148
148
  soft_max_interval: Maximum interval over which to group items, this should avoid a trickle of items causing
149
149
  a group to never be yielded. It's a soft max in the sense that once we're over this time, we yield items
150
- as soon as `aiter.__anext__()` returns. If `None`, no grouping/debouncing is performed
150
+ as soon as `anext(aiter)` returns. If `None`, no grouping/debouncing is performed
151
151
 
152
152
  Returns:
153
153
  A context manager usable as an async iterable of lists of items produced by the input async iterable.
@@ -171,7 +171,7 @@ async def group_by_temporal(
171
171
  buffer: list[T] = []
172
172
  group_start_time = time.monotonic()
173
173
 
174
- aiterator = aiterable.__aiter__()
174
+ aiterator = aiter(aiterable)
175
175
  while True:
176
176
  if group_start_time is None:
177
177
  # group hasn't started, we just wait for the maximum interval
@@ -182,9 +182,9 @@ async def group_by_temporal(
182
182
 
183
183
  # if there's no current task, we get the next one
184
184
  if task is None:
185
- # aiter.__anext__() returns an Awaitable[T], not a Coroutine which asyncio.create_task expects
185
+ # anext(aiter) returns an Awaitable[T], not a Coroutine which asyncio.create_task expects
186
186
  # so far, this doesn't seem to be a problem
187
- task = asyncio.create_task(aiterator.__anext__()) # pyright: ignore[reportArgumentType]
187
+ task = asyncio.create_task(anext(aiterator)) # pyright: ignore[reportArgumentType]
188
188
 
189
189
  # we use asyncio.wait to avoid cancelling the coroutine if it's not done
190
190
  done, _ = await asyncio.wait((task,), timeout=wait_time)
@@ -284,10 +284,10 @@ class PeekableAsyncStream(Generic[T]):
284
284
 
285
285
  # Otherwise, we need to fetch the next item from the underlying iterator.
286
286
  if self._source_iter is None:
287
- self._source_iter = self._source.__aiter__()
287
+ self._source_iter = aiter(self._source)
288
288
 
289
289
  try:
290
- self._buffer = await self._source_iter.__anext__()
290
+ self._buffer = await anext(self._source_iter)
291
291
  except StopAsyncIteration:
292
292
  self._exhausted = True
293
293
  return UNSET
@@ -318,10 +318,10 @@ class PeekableAsyncStream(Generic[T]):
318
318
 
319
319
  # Otherwise, fetch the next item from the source.
320
320
  if self._source_iter is None:
321
- self._source_iter = self._source.__aiter__()
321
+ self._source_iter = aiter(self._source)
322
322
 
323
323
  try:
324
- return await self._source_iter.__anext__()
324
+ return await anext(self._source_iter)
325
325
  except StopAsyncIteration:
326
326
  self._exhausted = True
327
327
  raise
@@ -15,7 +15,6 @@ from pydantic.json_schema import GenerateJsonSchema
15
15
  from typing_extensions import Self, TypeVar, deprecated
16
16
 
17
17
  from pydantic_ai._instrumentation import DEFAULT_INSTRUMENTATION_VERSION, InstrumentationNames
18
- from pydantic_graph import Graph
19
18
 
20
19
  from .. import (
21
20
  _agent_graph,
@@ -41,7 +40,6 @@ from ..builtin_tools import AbstractBuiltinTool
41
40
  from ..models.instrumented import InstrumentationSettings, InstrumentedModel, instrument_model
42
41
  from ..output import OutputDataT, OutputSpec
43
42
  from ..profiles import ModelProfile
44
- from ..result import FinalResult
45
43
  from ..run import AgentRun, AgentRunResult
46
44
  from ..settings import ModelSettings, merge_model_settings
47
45
  from ..tools import (
@@ -542,6 +540,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
542
540
  """
543
541
  if infer_name and self.name is None:
544
542
  self._infer_name(inspect.currentframe())
543
+
545
544
  model_used = self._get_model(model)
546
545
  del model
547
546
 
@@ -565,9 +564,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
565
564
  tool_manager = ToolManager[AgentDepsT](toolset)
566
565
 
567
566
  # Build the graph
568
- graph: Graph[_agent_graph.GraphAgentState, _agent_graph.GraphAgentDeps[AgentDepsT, Any], FinalResult[Any]] = (
569
- _agent_graph.build_agent_graph(self.name, self._deps_type, output_type_)
570
- )
567
+ graph = _agent_graph.build_agent_graph(self.name, self._deps_type, output_type_)
571
568
 
572
569
  # Build the initial state
573
570
  usage = usage or _usage.RunUsage()
@@ -607,16 +604,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
607
604
  else:
608
605
  instrumentation_settings = None
609
606
  tracer = NoOpTracer()
610
- if builtin_tools:
611
- # Deduplicate builtin tools passed to the agent and the run based on type
612
- builtin_tools = list(
613
- {
614
- **({type(tool): tool for tool in self._builtin_tools or []}),
615
- **({type(tool): tool for tool in builtin_tools}),
616
- }.values()
617
- )
618
- else:
619
- builtin_tools = list(self._builtin_tools)
607
+
620
608
  graph_deps = _agent_graph.GraphAgentDeps[AgentDepsT, RunOutputDataT](
621
609
  user_deps=deps,
622
610
  prompt=user_prompt,
@@ -629,14 +617,14 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
629
617
  output_schema=output_schema,
630
618
  output_validators=output_validators,
631
619
  history_processors=self.history_processors,
632
- builtin_tools=builtin_tools,
620
+ builtin_tools=[*self._builtin_tools, *(builtin_tools or [])],
633
621
  tool_manager=tool_manager,
634
622
  tracer=tracer,
635
623
  get_instructions=get_instructions,
636
624
  instrumentation_settings=instrumentation_settings,
637
625
  )
638
626
 
639
- start_node = _agent_graph.UserPromptNode[AgentDepsT](
627
+ user_prompt_node = _agent_graph.UserPromptNode[AgentDepsT](
640
628
  user_prompt=user_prompt,
641
629
  deferred_tool_results=deferred_tool_results,
642
630
  instructions=instructions_literal,
@@ -663,7 +651,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
663
651
 
664
652
  try:
665
653
  async with graph.iter(
666
- start_node,
654
+ inputs=user_prompt_node,
667
655
  state=state,
668
656
  deps=graph_deps,
669
657
  span=use_span(run_span) if run_span.is_recording() else None,
@@ -16,6 +16,7 @@ __all__ = (
16
16
  'UrlContextTool',
17
17
  'ImageGenerationTool',
18
18
  'MemoryTool',
19
+ 'MCPServerTool',
19
20
  )
20
21
 
21
22
  _BUILTIN_TOOL_TYPES: dict[str, type[AbstractBuiltinTool]] = {}
@@ -33,6 +34,14 @@ class AbstractBuiltinTool(ABC):
33
34
  kind: str = 'unknown_builtin_tool'
34
35
  """Built-in tool identifier, this should be available on all built-in tools as a discriminator."""
35
36
 
37
+ @property
38
+ def unique_id(self) -> str:
39
+ """A unique identifier for the builtin tool.
40
+
41
+ If multiple instances of the same builtin tool can be passed to the model, subclasses should override this property to allow them to be distinguished.
42
+ """
43
+ return self.kind
44
+
36
45
  def __init_subclass__(cls, **kwargs: Any) -> None:
37
46
  super().__init_subclass__(**kwargs)
38
47
  _BUILTIN_TOOL_TYPES[cls.kind] = cls
@@ -263,6 +272,68 @@ class MemoryTool(AbstractBuiltinTool):
263
272
  """The kind of tool."""
264
273
 
265
274
 
275
+ @dataclass(kw_only=True)
276
+ class MCPServerTool(AbstractBuiltinTool):
277
+ """A builtin tool that allows your agent to use MCP servers.
278
+
279
+ Supported by:
280
+
281
+ * OpenAI Responses
282
+ * Anthropic
283
+ """
284
+
285
+ id: str
286
+ """A unique identifier for the MCP server."""
287
+
288
+ url: str
289
+ """The URL of the MCP server to use.
290
+
291
+ For OpenAI Responses, it is possible to use `connector_id` by providing it as `x-openai-connector:<connector_id>`.
292
+ """
293
+
294
+ authorization_token: str | None = None
295
+ """Authorization header to use when making requests to the MCP server.
296
+
297
+ Supported by:
298
+
299
+ * OpenAI Responses
300
+ * Anthropic
301
+ """
302
+
303
+ description: str | None = None
304
+ """A description of the MCP server.
305
+
306
+ Supported by:
307
+
308
+ * OpenAI Responses
309
+ """
310
+
311
+ allowed_tools: list[str] | None = None
312
+ """A list of tools that the MCP server can use.
313
+
314
+ Supported by:
315
+
316
+ * OpenAI Responses
317
+ * Anthropic
318
+ """
319
+
320
+ headers: dict[str, str] | None = None
321
+ """Optional HTTP headers to send to the MCP server.
322
+
323
+ Use for authentication or other purposes.
324
+
325
+ Supported by:
326
+
327
+ * OpenAI Responses
328
+ """
329
+
330
+ kind: str = 'mcp_server'
331
+
332
+ @property
333
+ def unique_id(self) -> str:
334
+ return ':'.join([self.kind, self.id])
335
+
336
+
266
337
  def _tool_discriminator(tool_data: dict[str, Any] | AbstractBuiltinTool) -> str:
267
338
  if isinstance(tool_data, dict):
268
339
  return tool_data.get('kind', AbstractBuiltinTool.kind)
@@ -36,6 +36,17 @@ __all__ = [
36
36
  'TemporalWrapperToolset',
37
37
  ]
38
38
 
39
+ # We need eagerly import the anyio backends or it will happens inside workflow code and temporal has issues
40
+ # Note: It's difficult to add a test that covers this because pytest presumably does these imports itself
41
+ # when you have a @pytest.mark.anyio somewhere.
42
+ # I suppose we could add a test that runs a python script in a separate process, but I have not done that...
43
+ import anyio._backends._asyncio # pyright: ignore[reportUnusedImport]
44
+
45
+ try:
46
+ import anyio._backends._trio # noqa F401 # pyright: ignore[reportUnusedImport]
47
+ except ImportError:
48
+ pass
49
+
39
50
 
40
51
  class PydanticAIPlugin(ClientPlugin, WorkerPlugin):
41
52
  """Temporal client and worker plugin for Pydantic AI."""
@@ -2,11 +2,12 @@ from __future__ import annotations
2
2
 
3
3
  from collections.abc import Callable
4
4
  from dataclasses import dataclass
5
- from typing import Annotated, Any, Literal, assert_never
5
+ from typing import Annotated, Any, Literal
6
6
 
7
7
  from pydantic import ConfigDict, Discriminator, with_config
8
8
  from temporalio import activity, workflow
9
9
  from temporalio.workflow import ActivityConfig
10
+ from typing_extensions import assert_never
10
11
 
11
12
  from pydantic_ai import FunctionToolset, ToolsetTool
12
13
  from pydantic_ai.exceptions import ApprovalRequired, CallDeferred, ModelRetry, UserError
@@ -159,7 +159,7 @@ class ModelHTTPError(AgentRunError):
159
159
  super().__init__(message)
160
160
 
161
161
 
162
- class FallbackExceptionGroup(ExceptionGroup):
162
+ class FallbackExceptionGroup(ExceptionGroup[Any]):
163
163
  """A group of exceptions that can be raised when all fallback models fail."""
164
164
 
165
165
 
@@ -480,7 +480,7 @@ class BinaryContent:
480
480
  """
481
481
 
482
482
  _identifier: Annotated[str | None, pydantic.Field(alias='identifier', default=None, exclude=True)] = field(
483
- compare=False, default=None
483
+ compare=False, default=None, repr=False
484
484
  )
485
485
 
486
486
  kind: Literal['binary'] = 'binary'
@@ -410,9 +410,17 @@ class Model(ABC):
410
410
  they need to customize the preparation flow further, but most implementations should simply call
411
411
  ``self.prepare_request(...)`` at the start of their ``request`` (and related) methods.
412
412
  """
413
- merged_settings = merge_model_settings(self.settings, model_settings)
414
- customized_parameters = self.customize_request_parameters(model_request_parameters)
415
- return merged_settings, customized_parameters
413
+ model_settings = merge_model_settings(self.settings, model_settings)
414
+
415
+ if builtin_tools := model_request_parameters.builtin_tools:
416
+ # Deduplicate builtin tools
417
+ model_request_parameters = replace(
418
+ model_request_parameters,
419
+ builtin_tools=list({tool.unique_id: tool for tool in builtin_tools}.values()),
420
+ )
421
+
422
+ model_request_parameters = self.customize_request_parameters(model_request_parameters)
423
+ return model_settings, model_request_parameters
416
424
 
417
425
  @property
418
426
  @abstractmethod