pydantic-ai-slim 1.0.11__tar.gz → 1.0.13__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 (129) hide show
  1. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/PKG-INFO +3 -3
  2. pydantic_ai_slim-1.0.13/pydantic_ai/__init__.py +215 -0
  3. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_a2a.py +1 -1
  4. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_agent_graph.py +4 -0
  5. pydantic_ai_slim-1.0.13/pydantic_ai/_instrumentation.py +95 -0
  6. {pydantic_ai_slim-1.0.11/pydantic_ai/profiles → pydantic_ai_slim-1.0.13/pydantic_ai}/_json_schema.py +5 -3
  7. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_output.py +26 -12
  8. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_run_context.py +4 -0
  9. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_thinking_part.py +1 -1
  10. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_tool_manager.py +15 -7
  11. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_utils.py +24 -7
  12. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/agent/__init__.py +68 -36
  13. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/agent/abstract.py +12 -1
  14. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/agent/wrapper.py +11 -3
  15. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/builtin_tools.py +20 -1
  16. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/common_tools/duckduckgo.py +2 -2
  17. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/common_tools/tavily.py +2 -2
  18. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/direct.py +6 -6
  19. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/dbos/_agent.py +12 -3
  20. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/dbos/_mcp_server.py +1 -2
  21. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/dbos/_model.py +2 -2
  22. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/temporal/_agent.py +13 -4
  23. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/temporal/_function_toolset.py +1 -1
  24. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/temporal/_mcp_server.py +1 -1
  25. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/temporal/_model.py +3 -3
  26. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/temporal/_toolset.py +1 -3
  27. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/ext/aci.py +1 -1
  28. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/ext/langchain.py +1 -1
  29. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/mcp.py +32 -8
  30. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/messages.py +14 -11
  31. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/__init__.py +19 -2
  32. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/anthropic.py +29 -14
  33. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/bedrock.py +14 -5
  34. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/cohere.py +4 -0
  35. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/fallback.py +2 -9
  36. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/function.py +8 -0
  37. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/gemini.py +8 -0
  38. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/google.py +14 -2
  39. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/groq.py +8 -0
  40. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/huggingface.py +8 -2
  41. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/instrumented.py +16 -6
  42. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/mcp_sampling.py +2 -0
  43. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/mistral.py +8 -0
  44. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/openai.py +95 -29
  45. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/test.py +8 -0
  46. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/models/wrapper.py +7 -0
  47. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/output.py +11 -1
  48. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/__init__.py +1 -1
  49. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/google.py +1 -1
  50. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/openai.py +1 -1
  51. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/__init__.py +1 -1
  52. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/anthropic.py +1 -1
  53. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/azure.py +1 -1
  54. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/bedrock.py +1 -1
  55. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/cerebras.py +1 -1
  56. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/cohere.py +1 -1
  57. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/deepseek.py +1 -1
  58. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/fireworks.py +1 -1
  59. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/github.py +1 -1
  60. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/google.py +1 -1
  61. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/google_gla.py +1 -1
  62. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/google_vertex.py +1 -1
  63. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/grok.py +1 -1
  64. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/groq.py +1 -1
  65. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/heroku.py +1 -1
  66. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/huggingface.py +1 -1
  67. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/litellm.py +1 -1
  68. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/mistral.py +1 -1
  69. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/moonshotai.py +1 -1
  70. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/ollama.py +1 -1
  71. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/openai.py +1 -1
  72. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/openrouter.py +1 -1
  73. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/together.py +1 -1
  74. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/vercel.py +1 -1
  75. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/function.py +1 -2
  76. pydantic_ai_slim-1.0.11/pydantic_ai/__init__.py +0 -85
  77. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/.gitignore +0 -0
  78. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/LICENSE +0 -0
  79. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/README.md +0 -0
  80. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/__main__.py +0 -0
  81. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_cli.py +0 -0
  82. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_function_schema.py +0 -0
  83. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_griffe.py +0 -0
  84. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_mcp.py +0 -0
  85. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_otel_messages.py +0 -0
  86. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_parts_manager.py +0 -0
  87. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/_system_prompt.py +0 -0
  88. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/ag_ui.py +0 -0
  89. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/common_tools/__init__.py +0 -0
  90. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/__init__.py +0 -0
  91. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/dbos/__init__.py +0 -0
  92. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/dbos/_utils.py +0 -0
  93. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/temporal/__init__.py +0 -0
  94. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/temporal/_logfire.py +0 -0
  95. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
  96. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/exceptions.py +0 -0
  97. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/ext/__init__.py +0 -0
  98. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/format_prompt.py +0 -0
  99. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/amazon.py +0 -0
  100. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/anthropic.py +0 -0
  101. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/cohere.py +0 -0
  102. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/deepseek.py +0 -0
  103. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/grok.py +0 -0
  104. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/groq.py +0 -0
  105. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/harmony.py +0 -0
  106. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/meta.py +0 -0
  107. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/mistral.py +0 -0
  108. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/moonshotai.py +0 -0
  109. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/profiles/qwen.py +0 -0
  110. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/providers/gateway.py +0 -0
  111. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/py.typed +0 -0
  112. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/result.py +0 -0
  113. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/retries.py +0 -0
  114. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/run.py +0 -0
  115. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/settings.py +0 -0
  116. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/tools.py +0 -0
  117. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/__init__.py +0 -0
  118. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/_dynamic.py +0 -0
  119. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/abstract.py +0 -0
  120. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/approval_required.py +0 -0
  121. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/combined.py +0 -0
  122. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/external.py +0 -0
  123. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/filtered.py +0 -0
  124. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/prefixed.py +0 -0
  125. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/prepared.py +0 -0
  126. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/renamed.py +0 -0
  127. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/toolsets/wrapper.py +0 -0
  128. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pydantic_ai/usage.py +0 -0
  129. {pydantic_ai_slim-1.0.11 → pydantic_ai_slim-1.0.13}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydantic-ai-slim
3
- Version: 1.0.11
3
+ Version: 1.0.13
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.28
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.0.11
36
+ Requires-Dist: pydantic-graph==1.0.13
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.0.11; extra == 'evals'
60
+ Requires-Dist: pydantic-evals==1.0.13; extra == 'evals'
61
61
  Provides-Extra: google
62
62
  Requires-Dist: google-genai>=1.31.0; extra == 'google'
63
63
  Provides-Extra: groq
@@ -0,0 +1,215 @@
1
+ from importlib.metadata import version as _metadata_version
2
+
3
+ from .agent import (
4
+ Agent,
5
+ CallToolsNode,
6
+ EndStrategy,
7
+ InstrumentationSettings,
8
+ ModelRequestNode,
9
+ UserPromptNode,
10
+ capture_run_messages,
11
+ )
12
+ from .builtin_tools import CodeExecutionTool, UrlContextTool, WebSearchTool, WebSearchUserLocation
13
+ from .exceptions import (
14
+ AgentRunError,
15
+ ApprovalRequired,
16
+ CallDeferred,
17
+ FallbackExceptionGroup,
18
+ ModelHTTPError,
19
+ ModelRetry,
20
+ UnexpectedModelBehavior,
21
+ UsageLimitExceeded,
22
+ UserError,
23
+ )
24
+ from .format_prompt import format_as_xml
25
+ from .messages import (
26
+ AgentStreamEvent,
27
+ AudioFormat,
28
+ AudioMediaType,
29
+ AudioUrl,
30
+ BaseToolCallPart,
31
+ BaseToolReturnPart,
32
+ BinaryContent,
33
+ BuiltinToolCallPart,
34
+ BuiltinToolReturnPart,
35
+ DocumentFormat,
36
+ DocumentMediaType,
37
+ DocumentUrl,
38
+ FileUrl,
39
+ FinalResultEvent,
40
+ FinishReason,
41
+ FunctionToolCallEvent,
42
+ FunctionToolResultEvent,
43
+ HandleResponseEvent,
44
+ ImageFormat,
45
+ ImageMediaType,
46
+ ImageUrl,
47
+ ModelMessage,
48
+ ModelMessagesTypeAdapter,
49
+ ModelRequest,
50
+ ModelRequestPart,
51
+ ModelResponse,
52
+ ModelResponsePart,
53
+ ModelResponsePartDelta,
54
+ ModelResponseStreamEvent,
55
+ MultiModalContent,
56
+ PartDeltaEvent,
57
+ PartStartEvent,
58
+ RetryPromptPart,
59
+ SystemPromptPart,
60
+ TextPart,
61
+ TextPartDelta,
62
+ ThinkingPart,
63
+ ThinkingPartDelta,
64
+ ToolCallPart,
65
+ ToolCallPartDelta,
66
+ ToolReturn,
67
+ ToolReturnPart,
68
+ UserContent,
69
+ UserPromptPart,
70
+ VideoFormat,
71
+ VideoMediaType,
72
+ VideoUrl,
73
+ )
74
+ from .output import NativeOutput, PromptedOutput, StructuredDict, TextOutput, ToolOutput
75
+ from .profiles import (
76
+ DEFAULT_PROFILE,
77
+ InlineDefsJsonSchemaTransformer,
78
+ JsonSchemaTransformer,
79
+ ModelProfile,
80
+ ModelProfileSpec,
81
+ )
82
+ from .settings import ModelSettings
83
+ from .tools import DeferredToolRequests, DeferredToolResults, RunContext, Tool, ToolApproved, ToolDefinition, ToolDenied
84
+ from .toolsets import (
85
+ AbstractToolset,
86
+ ApprovalRequiredToolset,
87
+ CombinedToolset,
88
+ ExternalToolset,
89
+ FilteredToolset,
90
+ FunctionToolset,
91
+ PrefixedToolset,
92
+ PreparedToolset,
93
+ RenamedToolset,
94
+ ToolsetFunc,
95
+ ToolsetTool,
96
+ WrapperToolset,
97
+ )
98
+ from .usage import RequestUsage, RunUsage, UsageLimits
99
+
100
+ __all__ = (
101
+ '__version__',
102
+ # agent
103
+ 'Agent',
104
+ 'EndStrategy',
105
+ 'CallToolsNode',
106
+ 'ModelRequestNode',
107
+ 'UserPromptNode',
108
+ 'capture_run_messages',
109
+ 'InstrumentationSettings',
110
+ # exceptions
111
+ 'AgentRunError',
112
+ 'CallDeferred',
113
+ 'ApprovalRequired',
114
+ 'ModelRetry',
115
+ 'ModelHTTPError',
116
+ 'FallbackExceptionGroup',
117
+ 'UnexpectedModelBehavior',
118
+ 'UsageLimitExceeded',
119
+ 'UserError',
120
+ # messages
121
+ 'AgentStreamEvent',
122
+ 'AudioFormat',
123
+ 'AudioMediaType',
124
+ 'AudioUrl',
125
+ 'BaseToolCallPart',
126
+ 'BaseToolReturnPart',
127
+ 'BinaryContent',
128
+ 'BuiltinToolCallPart',
129
+ 'BuiltinToolReturnPart',
130
+ 'DocumentFormat',
131
+ 'DocumentMediaType',
132
+ 'DocumentUrl',
133
+ 'FileUrl',
134
+ 'FinalResultEvent',
135
+ 'FinishReason',
136
+ 'FunctionToolCallEvent',
137
+ 'FunctionToolResultEvent',
138
+ 'HandleResponseEvent',
139
+ 'ImageFormat',
140
+ 'ImageMediaType',
141
+ 'ImageUrl',
142
+ 'ModelMessage',
143
+ 'ModelMessagesTypeAdapter',
144
+ 'ModelRequest',
145
+ 'ModelRequestPart',
146
+ 'ModelResponse',
147
+ 'ModelResponsePart',
148
+ 'ModelResponsePartDelta',
149
+ 'ModelResponseStreamEvent',
150
+ 'MultiModalContent',
151
+ 'PartDeltaEvent',
152
+ 'PartStartEvent',
153
+ 'RetryPromptPart',
154
+ 'SystemPromptPart',
155
+ 'TextPart',
156
+ 'TextPartDelta',
157
+ 'ThinkingPart',
158
+ 'ThinkingPartDelta',
159
+ 'ToolCallPart',
160
+ 'ToolCallPartDelta',
161
+ 'ToolReturn',
162
+ 'ToolReturnPart',
163
+ 'UserContent',
164
+ 'UserPromptPart',
165
+ 'VideoFormat',
166
+ 'VideoMediaType',
167
+ 'VideoUrl',
168
+ # profiles
169
+ 'ModelProfile',
170
+ 'ModelProfileSpec',
171
+ 'DEFAULT_PROFILE',
172
+ 'InlineDefsJsonSchemaTransformer',
173
+ 'JsonSchemaTransformer',
174
+ # tools
175
+ 'Tool',
176
+ 'ToolDefinition',
177
+ 'RunContext',
178
+ 'DeferredToolRequests',
179
+ 'DeferredToolResults',
180
+ 'ToolApproved',
181
+ 'ToolDenied',
182
+ # toolsets
183
+ 'AbstractToolset',
184
+ 'ApprovalRequiredToolset',
185
+ 'CombinedToolset',
186
+ 'ExternalToolset',
187
+ 'FilteredToolset',
188
+ 'FunctionToolset',
189
+ 'PrefixedToolset',
190
+ 'PreparedToolset',
191
+ 'RenamedToolset',
192
+ 'ToolsetFunc',
193
+ 'ToolsetTool',
194
+ 'WrapperToolset',
195
+ # builtin_tools
196
+ 'WebSearchTool',
197
+ 'WebSearchUserLocation',
198
+ 'UrlContextTool',
199
+ 'CodeExecutionTool',
200
+ # output
201
+ 'ToolOutput',
202
+ 'NativeOutput',
203
+ 'PromptedOutput',
204
+ 'TextOutput',
205
+ 'StructuredDict',
206
+ # format_prompt
207
+ 'format_as_xml',
208
+ # settings
209
+ 'ModelSettings',
210
+ # usage
211
+ 'RunUsage',
212
+ 'RequestUsage',
213
+ 'UsageLimits',
214
+ )
215
+ __version__ = _metadata_version('pydantic_ai_slim')
@@ -10,7 +10,7 @@ from typing import Any, Generic, TypeVar
10
10
  from pydantic import TypeAdapter
11
11
  from typing_extensions import assert_never
12
12
 
13
- from pydantic_ai.messages import (
13
+ from pydantic_ai import (
14
14
  AudioUrl,
15
15
  BinaryContent,
16
16
  DocumentUrl,
@@ -16,6 +16,7 @@ from opentelemetry.trace import Tracer
16
16
  from typing_extensions import TypeVar, assert_never
17
17
 
18
18
  from pydantic_ai._function_schema import _takes_ctx as is_takes_ctx # type: ignore
19
+ from pydantic_ai._instrumentation import DEFAULT_INSTRUMENTATION_VERSION
19
20
  from pydantic_ai._tool_manager import ToolManager
20
21
  from pydantic_ai._utils import dataclasses_no_defaults_repr, get_union_args, is_async_callable, run_in_executor
21
22
  from pydantic_ai.builtin_tools import AbstractBuiltinTool
@@ -704,6 +705,9 @@ def build_run_context(ctx: GraphRunContext[GraphAgentState, GraphAgentDeps[DepsT
704
705
  tracer=ctx.deps.tracer,
705
706
  trace_include_content=ctx.deps.instrumentation_settings is not None
706
707
  and ctx.deps.instrumentation_settings.include_content,
708
+ instrumentation_version=ctx.deps.instrumentation_settings.version
709
+ if ctx.deps.instrumentation_settings
710
+ else DEFAULT_INSTRUMENTATION_VERSION,
707
711
  run_step=ctx.state.run_step,
708
712
  tool_call_approved=ctx.state.run_step == 0,
709
713
  )
@@ -0,0 +1,95 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from typing_extensions import Self
8
+
9
+ DEFAULT_INSTRUMENTATION_VERSION = 2
10
+ """Default instrumentation version for `InstrumentationSettings`."""
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class InstrumentationNames:
15
+ """Configuration for instrumentation span names and attributes based on version."""
16
+
17
+ # Agent run span configuration
18
+ agent_run_span_name: str
19
+ agent_name_attr: str
20
+
21
+ # Tool execution span configuration
22
+ tool_span_name: str
23
+ tool_arguments_attr: str
24
+ tool_result_attr: str
25
+
26
+ # Output Tool execution span configuration
27
+ output_tool_span_name: str
28
+
29
+ @classmethod
30
+ def for_version(cls, version: int) -> Self:
31
+ """Create instrumentation configuration for a specific version.
32
+
33
+ Args:
34
+ version: The instrumentation version (1, 2, or 3+)
35
+
36
+ Returns:
37
+ InstrumentationConfig instance with version-appropriate settings
38
+ """
39
+ if version <= 2:
40
+ return cls(
41
+ agent_run_span_name='agent run',
42
+ agent_name_attr='agent_name',
43
+ tool_span_name='running tool',
44
+ tool_arguments_attr='tool_arguments',
45
+ tool_result_attr='tool_response',
46
+ output_tool_span_name='running output function',
47
+ )
48
+ else:
49
+ return cls(
50
+ agent_run_span_name='invoke_agent',
51
+ agent_name_attr='gen_ai.agent.name',
52
+ tool_span_name='execute_tool', # Will be formatted with tool name
53
+ tool_arguments_attr='gen_ai.tool.call.arguments',
54
+ tool_result_attr='gen_ai.tool.call.result',
55
+ output_tool_span_name='execute_tool',
56
+ )
57
+
58
+ def get_agent_run_span_name(self, agent_name: str) -> str:
59
+ """Get the formatted agent span name.
60
+
61
+ Args:
62
+ agent_name: Name of the agent being executed
63
+
64
+ Returns:
65
+ Formatted span name
66
+ """
67
+ if self.agent_run_span_name == 'invoke_agent':
68
+ return f'invoke_agent {agent_name}'
69
+ return self.agent_run_span_name
70
+
71
+ def get_tool_span_name(self, tool_name: str) -> str:
72
+ """Get the formatted tool span name.
73
+
74
+ Args:
75
+ tool_name: Name of the tool being executed
76
+
77
+ Returns:
78
+ Formatted span name
79
+ """
80
+ if self.tool_span_name == 'execute_tool':
81
+ return f'execute_tool {tool_name}'
82
+ return self.tool_span_name
83
+
84
+ def get_output_tool_span_name(self, tool_name: str) -> str:
85
+ """Get the formatted output tool span name.
86
+
87
+ Args:
88
+ tool_name: Name of the tool being executed
89
+
90
+ Returns:
91
+ Formatted span name
92
+ """
93
+ if self.output_tool_span_name == 'execute_tool':
94
+ return f'execute_tool {tool_name}'
95
+ return self.output_tool_span_name
@@ -6,7 +6,7 @@ from copy import deepcopy
6
6
  from dataclasses import dataclass
7
7
  from typing import Any, Literal
8
8
 
9
- from pydantic_ai.exceptions import UserError
9
+ from .exceptions import UserError
10
10
 
11
11
  JsonSchema = dict[str, Any]
12
12
 
@@ -54,14 +54,14 @@ class JsonSchemaTransformer(ABC):
54
54
  if not self.prefer_inlined_defs and self.defs:
55
55
  handled['$defs'] = {k: self._handle(v) for k, v in self.defs.items()}
56
56
 
57
- elif self.recursive_refs: # pragma: no cover
57
+ elif self.recursive_refs:
58
58
  # If we are preferring inlined defs and there are recursive refs, we _have_ to use a $defs+$ref structure
59
59
  # We try to use whatever the original root key was, but if it is already in use,
60
60
  # we modify it to avoid collisions.
61
61
  defs = {key: self.defs[key] for key in self.recursive_refs}
62
62
  root_ref = self.schema.get('$ref')
63
63
  root_key = None if root_ref is None else re.sub(r'^#/\$defs/', '', root_ref)
64
- if root_key is None:
64
+ if root_key is None: # pragma: no cover
65
65
  root_key = self.schema.get('title', 'root')
66
66
  while root_key in defs:
67
67
  # Modify the root key until it is not already in use
@@ -77,6 +77,8 @@ class JsonSchemaTransformer(ABC):
77
77
  if self.prefer_inlined_defs:
78
78
  while ref := schema.get('$ref'):
79
79
  key = re.sub(r'^#/\$defs/', '', ref)
80
+ if key in self.recursive_refs:
81
+ break
80
82
  if key in self.refs_stack:
81
83
  self.recursive_refs.add(key)
82
84
  break # recursive ref can't be unpacked
@@ -11,6 +11,8 @@ from pydantic import Json, TypeAdapter, ValidationError
11
11
  from pydantic_core import SchemaValidator, to_json
12
12
  from typing_extensions import Self, TypedDict, TypeVar, assert_never
13
13
 
14
+ from pydantic_ai._instrumentation import InstrumentationNames
15
+
14
16
  from . import _function_schema, _utils, messages as _messages
15
17
  from ._run_context import AgentDepsT, RunContext
16
18
  from .exceptions import ModelRetry, ToolRetryError, UserError
@@ -95,6 +97,7 @@ async def execute_traced_output_function(
95
97
  ToolRetryError: When wrap_validation_errors is True and a ModelRetry is caught
96
98
  ModelRetry: When wrap_validation_errors is False and a ModelRetry occurs
97
99
  """
100
+ instrumentation_names = InstrumentationNames.for_version(run_context.instrumentation_version)
98
101
  # Set up span attributes
99
102
  tool_name = run_context.tool_name or getattr(function_schema.function, '__name__', 'output_function')
100
103
  attributes = {
@@ -104,18 +107,29 @@ async def execute_traced_output_function(
104
107
  if run_context.tool_call_id:
105
108
  attributes['gen_ai.tool.call.id'] = run_context.tool_call_id
106
109
  if run_context.trace_include_content:
107
- attributes['tool_arguments'] = to_json(args).decode()
108
- attributes['logfire.json_schema'] = json.dumps(
109
- {
110
- 'type': 'object',
111
- 'properties': {
112
- 'tool_arguments': {'type': 'object'},
113
- 'tool_response': {'type': 'object'},
114
- },
115
- }
116
- )
110
+ attributes[instrumentation_names.tool_arguments_attr] = to_json(args).decode()
111
+
112
+ attributes['logfire.json_schema'] = json.dumps(
113
+ {
114
+ 'type': 'object',
115
+ 'properties': {
116
+ **(
117
+ {
118
+ instrumentation_names.tool_arguments_attr: {'type': 'object'},
119
+ instrumentation_names.tool_result_attr: {'type': 'object'},
120
+ }
121
+ if run_context.trace_include_content
122
+ else {}
123
+ ),
124
+ 'gen_ai.tool.name': {},
125
+ **({'gen_ai.tool.call.id': {}} if run_context.tool_call_id else {}),
126
+ },
127
+ }
128
+ )
117
129
 
118
- with run_context.tracer.start_as_current_span('running output function', attributes=attributes) as span:
130
+ with run_context.tracer.start_as_current_span(
131
+ instrumentation_names.get_output_tool_span_name(tool_name), attributes=attributes
132
+ ) as span:
119
133
  try:
120
134
  output = await function_schema.call(args, run_context)
121
135
  except ModelRetry as r:
@@ -135,7 +149,7 @@ async def execute_traced_output_function(
135
149
  from .models.instrumented import InstrumentedModel
136
150
 
137
151
  span.set_attribute(
138
- 'tool_response',
152
+ instrumentation_names.tool_result_attr,
139
153
  output if isinstance(output, str) else json.dumps(InstrumentedModel.serialize_any(output)),
140
154
  )
141
155
 
@@ -8,6 +8,8 @@ from typing import TYPE_CHECKING, Generic
8
8
  from opentelemetry.trace import NoOpTracer, Tracer
9
9
  from typing_extensions import TypeVar
10
10
 
11
+ from pydantic_ai._instrumentation import DEFAULT_INSTRUMENTATION_VERSION
12
+
11
13
  from . import _utils, messages as _messages
12
14
 
13
15
  if TYPE_CHECKING:
@@ -36,6 +38,8 @@ class RunContext(Generic[AgentDepsT]):
36
38
  """The tracer to use for tracing the run."""
37
39
  trace_include_content: bool = False
38
40
  """Whether to include the content of the messages in the trace."""
41
+ instrumentation_version: int = DEFAULT_INSTRUMENTATION_VERSION
42
+ """Instrumentation settings version, if instrumentation is enabled."""
39
43
  retries: dict[str, int] = field(default_factory=dict)
40
44
  """Number of retries for each tool so far."""
41
45
  tool_call_id: str | None = None
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations as _annotations
2
2
 
3
- from pydantic_ai.messages import TextPart, ThinkingPart
3
+ from pydantic_ai import TextPart, ThinkingPart
4
4
 
5
5
 
6
6
  def split_content_into_text_and_thinking(content: str, thinking_tags: tuple[str, str]) -> list[ThinkingPart | TextPart]:
@@ -12,6 +12,7 @@ from pydantic import ValidationError
12
12
  from typing_extensions import assert_never
13
13
 
14
14
  from . import messages as _messages
15
+ from ._instrumentation import InstrumentationNames
15
16
  from ._run_context import AgentDepsT, RunContext
16
17
  from .exceptions import ModelRetry, ToolRetryError, UnexpectedModelBehavior
17
18
  from .messages import ToolCallPart
@@ -115,6 +116,7 @@ class ToolManager(Generic[AgentDepsT]):
115
116
  wrap_validation_errors,
116
117
  self.ctx.tracer,
117
118
  self.ctx.trace_include_content,
119
+ self.ctx.instrumentation_version,
118
120
  usage_limits,
119
121
  )
120
122
 
@@ -203,15 +205,18 @@ class ToolManager(Generic[AgentDepsT]):
203
205
  allow_partial: bool,
204
206
  wrap_validation_errors: bool,
205
207
  tracer: Tracer,
206
- include_content: bool = False,
208
+ include_content: bool,
209
+ instrumentation_version: int,
207
210
  usage_limits: UsageLimits | None = None,
208
211
  ) -> Any:
209
212
  """See <https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/#execute-tool-span>."""
213
+ instrumentation_names = InstrumentationNames.for_version(instrumentation_version)
214
+
210
215
  span_attributes = {
211
216
  'gen_ai.tool.name': call.tool_name,
212
217
  # NOTE: this means `gen_ai.tool.call.id` will be included even if it was generated by pydantic-ai
213
218
  'gen_ai.tool.call.id': call.tool_call_id,
214
- **({'tool_arguments': call.args_as_json_str()} if include_content else {}),
219
+ **({instrumentation_names.tool_arguments_attr: call.args_as_json_str()} if include_content else {}),
215
220
  'logfire.msg': f'running tool: {call.tool_name}',
216
221
  # add the JSON schema so these attributes are formatted nicely in Logfire
217
222
  'logfire.json_schema': json.dumps(
@@ -220,8 +225,8 @@ class ToolManager(Generic[AgentDepsT]):
220
225
  'properties': {
221
226
  **(
222
227
  {
223
- 'tool_arguments': {'type': 'object'},
224
- 'tool_response': {'type': 'object'},
228
+ instrumentation_names.tool_arguments_attr: {'type': 'object'},
229
+ instrumentation_names.tool_result_attr: {'type': 'object'},
225
230
  }
226
231
  if include_content
227
232
  else {}
@@ -232,18 +237,21 @@ class ToolManager(Generic[AgentDepsT]):
232
237
  }
233
238
  ),
234
239
  }
235
- with tracer.start_as_current_span('running tool', attributes=span_attributes) as span:
240
+ with tracer.start_as_current_span(
241
+ instrumentation_names.get_tool_span_name(call.tool_name),
242
+ attributes=span_attributes,
243
+ ) as span:
236
244
  try:
237
245
  tool_result = await self._call_tool(call, allow_partial, wrap_validation_errors, usage_limits)
238
246
  except ToolRetryError as e:
239
247
  part = e.tool_retry
240
248
  if include_content and span.is_recording():
241
- span.set_attribute('tool_response', part.model_response())
249
+ span.set_attribute(instrumentation_names.tool_result_attr, part.model_response())
242
250
  raise e
243
251
 
244
252
  if include_content and span.is_recording():
245
253
  span.set_attribute(
246
- 'tool_response',
254
+ instrumentation_names.tool_result_attr,
247
255
  tool_result
248
256
  if isinstance(tool_result, str)
249
257
  else _messages.tool_return_ta.dump_json(tool_result).decode(),
@@ -6,7 +6,7 @@ import inspect
6
6
  import re
7
7
  import time
8
8
  import uuid
9
- from collections.abc import AsyncIterable, AsyncIterator, Awaitable, Callable, Iterator
9
+ from collections.abc import AsyncIterable, AsyncIterator, Awaitable, Callable, Iterable, Iterator
10
10
  from contextlib import asynccontextmanager, suppress
11
11
  from dataclasses import dataclass, fields, is_dataclass
12
12
  from datetime import datetime, timezone
@@ -70,16 +70,33 @@ def check_object_json_schema(schema: JsonSchemaValue) -> ObjectJsonSchema:
70
70
 
71
71
  if schema.get('type') == 'object':
72
72
  return schema
73
- elif schema.get('$ref') is not None:
74
- maybe_result = schema.get('$defs', {}).get(schema['$ref'][8:]) # This removes the initial "#/$defs/".
75
-
76
- if "'$ref': '#/$defs/" in str(maybe_result):
77
- return schema # We can't remove the $defs because the schema contains other references
78
- return maybe_result
73
+ elif ref := schema.get('$ref'):
74
+ prefix = '#/$defs/'
75
+ # Return the referenced schema unless it contains additional nested references.
76
+ if (
77
+ ref.startswith(prefix)
78
+ and (resolved := schema.get('$defs', {}).get(ref[len(prefix) :]))
79
+ and resolved.get('type') == 'object'
80
+ and not _contains_ref(resolved)
81
+ ):
82
+ return resolved
83
+ return schema
79
84
  else:
80
85
  raise UserError('Schema must be an object')
81
86
 
82
87
 
88
+ def _contains_ref(obj: JsonSchemaValue | list[JsonSchemaValue]) -> bool:
89
+ """Recursively check if an object contains any $ref keys."""
90
+ items: Iterable[JsonSchemaValue]
91
+ if isinstance(obj, dict):
92
+ if '$ref' in obj:
93
+ return True
94
+ items = obj.values()
95
+ else:
96
+ items = obj
97
+ return any(isinstance(item, dict | list) and _contains_ref(item) for item in items) # pyright: ignore[reportUnknownArgumentType]
98
+
99
+
83
100
  T = TypeVar('T')
84
101
 
85
102