pydantic-ai-slim 0.7.6__tar.gz → 0.8.1__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 (119) hide show
  1. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/PKG-INFO +5 -5
  2. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_cli.py +2 -1
  3. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/ag_ui.py +2 -2
  4. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/agent/__init__.py +22 -16
  5. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/agent/abstract.py +31 -18
  6. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/direct.py +5 -3
  7. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/durable_exec/temporal/__init__.py +67 -16
  8. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/durable_exec/temporal/_function_toolset.py +9 -2
  9. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/durable_exec/temporal/_logfire.py +5 -2
  10. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/mcp.py +48 -71
  11. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/messages.py +54 -13
  12. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/__init__.py +18 -8
  13. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/anthropic.py +1 -1
  14. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/bedrock.py +6 -2
  15. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/gemini.py +1 -1
  16. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/google.py +1 -1
  17. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/groq.py +1 -1
  18. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/huggingface.py +1 -1
  19. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/instrumented.py +14 -5
  20. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/mistral.py +2 -2
  21. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/openai.py +14 -4
  22. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/result.py +36 -18
  23. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pyproject.toml +2 -2
  24. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/.gitignore +0 -0
  25. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/LICENSE +0 -0
  26. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/README.md +0 -0
  27. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/__init__.py +0 -0
  28. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/__main__.py +0 -0
  29. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_a2a.py +0 -0
  30. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_agent_graph.py +0 -0
  31. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_function_schema.py +0 -0
  32. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_griffe.py +0 -0
  33. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_mcp.py +0 -0
  34. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_otel_messages.py +0 -0
  35. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_output.py +0 -0
  36. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_parts_manager.py +0 -0
  37. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_run_context.py +0 -0
  38. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_system_prompt.py +0 -0
  39. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_thinking_part.py +0 -0
  40. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_tool_manager.py +0 -0
  41. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/_utils.py +0 -0
  42. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/agent/wrapper.py +0 -0
  43. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/builtin_tools.py +0 -0
  44. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/common_tools/__init__.py +0 -0
  45. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/common_tools/duckduckgo.py +0 -0
  46. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/common_tools/tavily.py +0 -0
  47. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/durable_exec/__init__.py +0 -0
  48. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/durable_exec/temporal/_agent.py +0 -0
  49. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/durable_exec/temporal/_mcp_server.py +0 -0
  50. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/durable_exec/temporal/_model.py +0 -0
  51. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
  52. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/durable_exec/temporal/_toolset.py +0 -0
  53. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/exceptions.py +0 -0
  54. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/ext/__init__.py +0 -0
  55. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/ext/aci.py +0 -0
  56. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/ext/langchain.py +0 -0
  57. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/format_prompt.py +0 -0
  58. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/cohere.py +0 -0
  59. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/fallback.py +0 -0
  60. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/function.py +0 -0
  61. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/mcp_sampling.py +0 -0
  62. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/test.py +0 -0
  63. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/models/wrapper.py +0 -0
  64. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/output.py +0 -0
  65. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/__init__.py +0 -0
  66. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/_json_schema.py +0 -0
  67. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/amazon.py +0 -0
  68. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/anthropic.py +0 -0
  69. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/cohere.py +0 -0
  70. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/deepseek.py +0 -0
  71. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/google.py +0 -0
  72. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/grok.py +0 -0
  73. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/groq.py +0 -0
  74. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/harmony.py +0 -0
  75. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/meta.py +0 -0
  76. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/mistral.py +0 -0
  77. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/moonshotai.py +0 -0
  78. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/openai.py +0 -0
  79. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/profiles/qwen.py +0 -0
  80. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/__init__.py +0 -0
  81. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/anthropic.py +0 -0
  82. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/azure.py +0 -0
  83. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/bedrock.py +0 -0
  84. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/cerebras.py +0 -0
  85. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/cohere.py +0 -0
  86. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/deepseek.py +0 -0
  87. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/fireworks.py +0 -0
  88. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/github.py +0 -0
  89. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/google.py +0 -0
  90. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/google_gla.py +0 -0
  91. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/google_vertex.py +0 -0
  92. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/grok.py +0 -0
  93. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/groq.py +0 -0
  94. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/heroku.py +0 -0
  95. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/huggingface.py +0 -0
  96. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/mistral.py +0 -0
  97. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/moonshotai.py +0 -0
  98. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/ollama.py +0 -0
  99. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/openai.py +0 -0
  100. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/openrouter.py +0 -0
  101. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/together.py +0 -0
  102. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/providers/vercel.py +0 -0
  103. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/py.typed +0 -0
  104. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/retries.py +0 -0
  105. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/run.py +0 -0
  106. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/settings.py +0 -0
  107. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/tools.py +0 -0
  108. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/__init__.py +0 -0
  109. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/_dynamic.py +0 -0
  110. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/abstract.py +0 -0
  111. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/combined.py +0 -0
  112. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/deferred.py +0 -0
  113. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/filtered.py +0 -0
  114. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/function.py +0 -0
  115. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/prefixed.py +0 -0
  116. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/prepared.py +0 -0
  117. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/renamed.py +0 -0
  118. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/toolsets/wrapper.py +0 -0
  119. {pydantic_ai_slim-0.7.6 → pydantic_ai_slim-0.8.1}/pydantic_ai/usage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydantic-ai-slim
3
- Version: 0.7.6
3
+ Version: 0.8.1
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
@@ -35,7 +35,7 @@ Requires-Dist: genai-prices>=0.0.22
35
35
  Requires-Dist: griffe>=1.3.2
36
36
  Requires-Dist: httpx>=0.27
37
37
  Requires-Dist: opentelemetry-api>=1.28.0
38
- Requires-Dist: pydantic-graph==0.7.6
38
+ Requires-Dist: pydantic-graph==0.8.1
39
39
  Requires-Dist: pydantic>=2.10
40
40
  Requires-Dist: typing-inspection>=0.4.0
41
41
  Provides-Extra: a2a
@@ -57,7 +57,7 @@ Requires-Dist: cohere>=5.16.0; (platform_system != 'Emscripten') and extra == 'c
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==0.7.6; extra == 'evals'
60
+ Requires-Dist: pydantic-evals==0.8.1; extra == 'evals'
61
61
  Provides-Extra: google
62
62
  Requires-Dist: google-genai>=1.31.0; extra == 'google'
63
63
  Provides-Extra: groq
@@ -67,7 +67,7 @@ Requires-Dist: huggingface-hub[inference]>=0.33.5; extra == 'huggingface'
67
67
  Provides-Extra: logfire
68
68
  Requires-Dist: logfire>=3.14.1; extra == 'logfire'
69
69
  Provides-Extra: mcp
70
- Requires-Dist: mcp>=1.10.0; (python_version >= '3.10') and extra == 'mcp'
70
+ Requires-Dist: mcp>=1.12.3; (python_version >= '3.10') and extra == 'mcp'
71
71
  Provides-Extra: mistral
72
72
  Requires-Dist: mistralai>=1.9.2; extra == 'mistral'
73
73
  Provides-Extra: openai
@@ -77,7 +77,7 @@ Requires-Dist: tenacity>=8.2.3; extra == 'retries'
77
77
  Provides-Extra: tavily
78
78
  Requires-Dist: tavily-python>=0.5.0; extra == 'tavily'
79
79
  Provides-Extra: temporal
80
- Requires-Dist: temporalio==1.15.0; extra == 'temporal'
80
+ Requires-Dist: temporalio==1.16.0; extra == 'temporal'
81
81
  Provides-Extra: vertexai
82
82
  Requires-Dist: google-auth>=2.36.0; extra == 'vertexai'
83
83
  Requires-Dist: requests>=2.32.2; extra == 'vertexai'
@@ -228,6 +228,7 @@ async def run_chat(
228
228
  prog_name: str,
229
229
  config_dir: Path | None = None,
230
230
  deps: AgentDepsT = None,
231
+ message_history: list[ModelMessage] | None = None,
231
232
  ) -> int:
232
233
  prompt_history_path = (config_dir or PYDANTIC_AI_HOME) / PROMPT_HISTORY_FILENAME
233
234
  prompt_history_path.parent.mkdir(parents=True, exist_ok=True)
@@ -235,7 +236,7 @@ async def run_chat(
235
236
  session: PromptSession[Any] = PromptSession(history=FileHistory(str(prompt_history_path)))
236
237
 
237
238
  multiline = False
238
- messages: list[ModelMessage] = []
239
+ messages: list[ModelMessage] = message_history[:] if message_history else []
239
240
 
240
241
  while True:
241
242
  try:
@@ -28,11 +28,11 @@ from ._agent_graph import CallToolsNode, ModelRequestNode
28
28
  from .agent import AbstractAgent, AgentRun
29
29
  from .exceptions import UserError
30
30
  from .messages import (
31
- AgentStreamEvent,
32
31
  FunctionToolResultEvent,
33
32
  ModelMessage,
34
33
  ModelRequest,
35
34
  ModelResponse,
35
+ ModelResponseStreamEvent,
36
36
  PartDeltaEvent,
37
37
  PartStartEvent,
38
38
  SystemPromptPart,
@@ -403,7 +403,7 @@ async def _agent_stream(run: AgentRun[AgentDepsT, Any]) -> AsyncIterator[BaseEve
403
403
 
404
404
  async def _handle_model_request_event(
405
405
  stream_ctx: _RequestStreamContext,
406
- agent_event: AgentStreamEvent,
406
+ agent_event: ModelResponseStreamEvent,
407
407
  ) -> AsyncIterator[BaseEvent]:
408
408
  """Handle an agent event and yield AG-UI protocol events.
409
409
 
@@ -26,7 +26,14 @@ from .. import (
26
26
  models,
27
27
  usage as _usage,
28
28
  )
29
- from .._agent_graph import HistoryProcessor
29
+ from .._agent_graph import (
30
+ CallToolsNode,
31
+ EndStrategy,
32
+ HistoryProcessor,
33
+ ModelRequestNode,
34
+ UserPromptNode,
35
+ capture_run_messages,
36
+ )
30
37
  from .._output import OutputToolset
31
38
  from .._tool_manager import ToolManager
32
39
  from ..builtin_tools import AbstractBuiltinTool
@@ -60,13 +67,6 @@ from ..toolsets.prepared import PreparedToolset
60
67
  from .abstract import AbstractAgent, EventStreamHandler, RunOutputDataT
61
68
  from .wrapper import WrapperAgent
62
69
 
63
- # Re-exporting like this improves auto-import behavior in PyCharm
64
- capture_run_messages = _agent_graph.capture_run_messages
65
- EndStrategy = _agent_graph.EndStrategy
66
- CallToolsNode = _agent_graph.CallToolsNode
67
- ModelRequestNode = _agent_graph.ModelRequestNode
68
- UserPromptNode = _agent_graph.UserPromptNode
69
-
70
70
  if TYPE_CHECKING:
71
71
  from ..mcp import MCPServer
72
72
 
@@ -678,22 +678,28 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
678
678
  self, state: _agent_graph.GraphAgentState, usage: _usage.RunUsage, settings: InstrumentationSettings
679
679
  ):
680
680
  if settings.version == 1:
681
- attr_name = 'all_messages_events'
682
- value = [
683
- InstrumentedModel.event_to_dict(e) for e in settings.messages_to_otel_events(state.message_history)
684
- ]
681
+ attrs = {
682
+ 'all_messages_events': json.dumps(
683
+ [
684
+ InstrumentedModel.event_to_dict(e)
685
+ for e in settings.messages_to_otel_events(state.message_history)
686
+ ]
687
+ )
688
+ }
685
689
  else:
686
- attr_name = 'pydantic_ai.all_messages'
687
- value = settings.messages_to_otel_messages(state.message_history)
690
+ attrs = {
691
+ 'pydantic_ai.all_messages': json.dumps(settings.messages_to_otel_messages(state.message_history)),
692
+ **settings.system_instructions_attributes(self._instructions),
693
+ }
688
694
 
689
695
  return {
690
696
  **usage.opentelemetry_attributes(),
691
- attr_name: json.dumps(value),
697
+ **attrs,
692
698
  'logfire.json_schema': json.dumps(
693
699
  {
694
700
  'type': 'object',
695
701
  'properties': {
696
- attr_name: {'type': 'array'},
702
+ **{attr: {'type': 'array'} for attr in attrs.keys()},
697
703
  'final_result': {'type': 'object'},
698
704
  },
699
705
  }
@@ -5,7 +5,7 @@ from abc import ABC, abstractmethod
5
5
  from collections.abc import AsyncIterable, AsyncIterator, Awaitable, Iterator, Mapping, Sequence
6
6
  from contextlib import AbstractAsyncContextManager, asynccontextmanager, contextmanager
7
7
  from types import FrameType
8
- from typing import TYPE_CHECKING, Any, Callable, Generic, Union, cast, overload
8
+ from typing import TYPE_CHECKING, Any, Callable, Generic, cast, overload
9
9
 
10
10
  from typing_extensions import Self, TypeAlias, TypeIs, TypeVar
11
11
 
@@ -34,13 +34,6 @@ from ..tools import (
34
34
  from ..toolsets import AbstractToolset
35
35
  from ..usage import RunUsage, UsageLimits
36
36
 
37
- # Re-exporting like this improves auto-import behavior in PyCharm
38
- capture_run_messages = _agent_graph.capture_run_messages
39
- EndStrategy = _agent_graph.EndStrategy
40
- CallToolsNode = _agent_graph.CallToolsNode
41
- ModelRequestNode = _agent_graph.ModelRequestNode
42
- UserPromptNode = _agent_graph.UserPromptNode
43
-
44
37
  if TYPE_CHECKING:
45
38
  from fasta2a.applications import FastA2A
46
39
  from fasta2a.broker import Broker
@@ -60,11 +53,7 @@ RunOutputDataT = TypeVar('RunOutputDataT')
60
53
  """Type variable for the result data of a run where `output_type` was customized on the run call."""
61
54
 
62
55
  EventStreamHandler: TypeAlias = Callable[
63
- [
64
- RunContext[AgentDepsT],
65
- AsyncIterable[Union[_messages.AgentStreamEvent, _messages.HandleResponseEvent]],
66
- ],
67
- Awaitable[None],
56
+ [RunContext[AgentDepsT], AsyncIterable[_messages.AgentStreamEvent]], Awaitable[None]
68
57
  ]
69
58
  """A function that receives agent [`RunContext`][pydantic_ai.tools.RunContext] and an async iterable of events from the model's streaming response and the agent's execution of tools."""
70
59
 
@@ -452,7 +441,9 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
452
441
  async with node.stream(graph_ctx) as stream:
453
442
  final_result_event = None
454
443
 
455
- async def stream_to_final(stream: AgentStream) -> AsyncIterator[_messages.AgentStreamEvent]:
444
+ async def stream_to_final(
445
+ stream: AgentStream,
446
+ ) -> AsyncIterator[_messages.ModelResponseStreamEvent]:
456
447
  nonlocal final_result_event
457
448
  async for event in stream:
458
449
  yield event
@@ -899,12 +890,18 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
899
890
  lifespan=lifespan,
900
891
  )
901
892
 
902
- async def to_cli(self: Self, deps: AgentDepsT = None, prog_name: str = 'pydantic-ai') -> None:
893
+ async def to_cli(
894
+ self: Self,
895
+ deps: AgentDepsT = None,
896
+ prog_name: str = 'pydantic-ai',
897
+ message_history: list[_messages.ModelMessage] | None = None,
898
+ ) -> None:
903
899
  """Run the agent in a CLI chat interface.
904
900
 
905
901
  Args:
906
902
  deps: The dependencies to pass to the agent.
907
903
  prog_name: The name of the program to use for the CLI. Defaults to 'pydantic-ai'.
904
+ message_history: History of the conversation so far.
908
905
 
909
906
  Example:
910
907
  ```python {title="agent_to_cli.py" test="skip"}
@@ -920,14 +917,28 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
920
917
 
921
918
  from pydantic_ai._cli import run_chat
922
919
 
923
- await run_chat(stream=True, agent=self, deps=deps, console=Console(), code_theme='monokai', prog_name=prog_name)
920
+ await run_chat(
921
+ stream=True,
922
+ agent=self,
923
+ deps=deps,
924
+ console=Console(),
925
+ code_theme='monokai',
926
+ prog_name=prog_name,
927
+ message_history=message_history,
928
+ )
924
929
 
925
- def to_cli_sync(self: Self, deps: AgentDepsT = None, prog_name: str = 'pydantic-ai') -> None:
930
+ def to_cli_sync(
931
+ self: Self,
932
+ deps: AgentDepsT = None,
933
+ prog_name: str = 'pydantic-ai',
934
+ message_history: list[_messages.ModelMessage] | None = None,
935
+ ) -> None:
926
936
  """Run the agent in a CLI chat interface with the non-async interface.
927
937
 
928
938
  Args:
929
939
  deps: The dependencies to pass to the agent.
930
940
  prog_name: The name of the program to use for the CLI. Defaults to 'pydantic-ai'.
941
+ message_history: History of the conversation so far.
931
942
 
932
943
  ```python {title="agent_to_cli_sync.py" test="skip"}
933
944
  from pydantic_ai import Agent
@@ -937,4 +948,6 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
937
948
  agent.to_cli_sync(prog_name='assistant')
938
949
  ```
939
950
  """
940
- return get_event_loop().run_until_complete(self.to_cli(deps=deps, prog_name=prog_name))
951
+ return get_event_loop().run_until_complete(
952
+ self.to_cli(deps=deps, prog_name=prog_name, message_history=message_history)
953
+ )
@@ -275,7 +275,9 @@ class StreamedResponseSync:
275
275
  """
276
276
 
277
277
  _async_stream_cm: AbstractAsyncContextManager[StreamedResponse]
278
- _queue: queue.Queue[messages.AgentStreamEvent | Exception | None] = field(default_factory=queue.Queue, init=False)
278
+ _queue: queue.Queue[messages.ModelResponseStreamEvent | Exception | None] = field(
279
+ default_factory=queue.Queue, init=False
280
+ )
279
281
  _thread: threading.Thread | None = field(default=None, init=False)
280
282
  _stream_response: StreamedResponse | None = field(default=None, init=False)
281
283
  _exception: Exception | None = field(default=None, init=False)
@@ -295,8 +297,8 @@ class StreamedResponseSync:
295
297
  ) -> None:
296
298
  self._cleanup()
297
299
 
298
- def __iter__(self) -> Iterator[messages.AgentStreamEvent]:
299
- """Stream the response as an iterable of [`AgentStreamEvent`][pydantic_ai.messages.AgentStreamEvent]s."""
300
+ def __iter__(self) -> Iterator[messages.ModelResponseStreamEvent]:
301
+ """Stream the response as an iterable of [`ModelResponseStreamEvent`][pydantic_ai.messages.ModelResponseStreamEvent]s."""
300
302
  self._check_context_manager_usage()
301
303
 
302
304
  while True:
@@ -1,15 +1,24 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import warnings
4
- from collections.abc import Sequence
4
+ from collections.abc import AsyncIterator, Sequence
5
+ from contextlib import AbstractAsyncContextManager
5
6
  from dataclasses import replace
6
7
  from typing import Any, Callable
7
8
 
8
9
  from pydantic.errors import PydanticUserError
9
- from temporalio.client import ClientConfig, Plugin as ClientPlugin
10
+ from temporalio.client import ClientConfig, Plugin as ClientPlugin, WorkflowHistory
10
11
  from temporalio.contrib.pydantic import PydanticPayloadConverter, pydantic_data_converter
11
- from temporalio.converter import DefaultPayloadConverter
12
- from temporalio.worker import Plugin as WorkerPlugin, WorkerConfig
12
+ from temporalio.converter import DataConverter, DefaultPayloadConverter
13
+ from temporalio.service import ConnectConfig, ServiceClient
14
+ from temporalio.worker import (
15
+ Plugin as WorkerPlugin,
16
+ Replayer,
17
+ ReplayerConfig,
18
+ Worker,
19
+ WorkerConfig,
20
+ WorkflowReplayResult,
21
+ )
13
22
  from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner
14
23
 
15
24
  from ...exceptions import UserError
@@ -31,17 +40,15 @@ __all__ = [
31
40
  class PydanticAIPlugin(ClientPlugin, WorkerPlugin):
32
41
  """Temporal client and worker plugin for Pydantic AI."""
33
42
 
34
- def configure_client(self, config: ClientConfig) -> ClientConfig:
35
- if (data_converter := config.get('data_converter')) and data_converter.payload_converter_class not in (
36
- DefaultPayloadConverter,
37
- PydanticPayloadConverter,
38
- ):
39
- warnings.warn( # pragma: no cover
40
- 'A non-default Temporal data converter was used which has been replaced with the Pydantic data converter.'
41
- )
43
+ def init_client_plugin(self, next: ClientPlugin) -> None:
44
+ self.next_client_plugin = next
42
45
 
43
- config['data_converter'] = pydantic_data_converter
44
- return super().configure_client(config)
46
+ def init_worker_plugin(self, next: WorkerPlugin) -> None:
47
+ self.next_worker_plugin = next
48
+
49
+ def configure_client(self, config: ClientConfig) -> ClientConfig:
50
+ config['data_converter'] = self._get_new_data_converter(config.get('data_converter'))
51
+ return self.next_client_plugin.configure_client(config)
45
52
 
46
53
  def configure_worker(self, config: WorkerConfig) -> WorkerConfig:
47
54
  runner = config.get('workflow_runner') # pyright: ignore[reportUnknownMemberType]
@@ -67,7 +74,35 @@ class PydanticAIPlugin(ClientPlugin, WorkerPlugin):
67
74
  PydanticUserError,
68
75
  ]
69
76
 
70
- return super().configure_worker(config)
77
+ return self.next_worker_plugin.configure_worker(config)
78
+
79
+ async def connect_service_client(self, config: ConnectConfig) -> ServiceClient:
80
+ return await self.next_client_plugin.connect_service_client(config)
81
+
82
+ async def run_worker(self, worker: Worker) -> None:
83
+ await self.next_worker_plugin.run_worker(worker)
84
+
85
+ def configure_replayer(self, config: ReplayerConfig) -> ReplayerConfig: # pragma: no cover
86
+ config['data_converter'] = self._get_new_data_converter(config.get('data_converter')) # pyright: ignore[reportUnknownMemberType]
87
+ return self.next_worker_plugin.configure_replayer(config)
88
+
89
+ def run_replayer(
90
+ self,
91
+ replayer: Replayer,
92
+ histories: AsyncIterator[WorkflowHistory],
93
+ ) -> AbstractAsyncContextManager[AsyncIterator[WorkflowReplayResult]]: # pragma: no cover
94
+ return self.next_worker_plugin.run_replayer(replayer, histories)
95
+
96
+ def _get_new_data_converter(self, converter: DataConverter | None) -> DataConverter:
97
+ if converter and converter.payload_converter_class not in (
98
+ DefaultPayloadConverter,
99
+ PydanticPayloadConverter,
100
+ ):
101
+ warnings.warn( # pragma: no cover
102
+ 'A non-default Temporal data converter was used which has been replaced with the Pydantic data converter.'
103
+ )
104
+
105
+ return pydantic_data_converter
71
106
 
72
107
 
73
108
  class AgentPlugin(WorkerPlugin):
@@ -76,8 +111,24 @@ class AgentPlugin(WorkerPlugin):
76
111
  def __init__(self, agent: TemporalAgent[Any, Any]):
77
112
  self.agent = agent
78
113
 
114
+ def init_worker_plugin(self, next: WorkerPlugin) -> None:
115
+ self.next_worker_plugin = next
116
+
79
117
  def configure_worker(self, config: WorkerConfig) -> WorkerConfig:
80
118
  activities: Sequence[Callable[..., Any]] = config.get('activities', []) # pyright: ignore[reportUnknownMemberType]
81
119
  # Activities are checked for name conflicts by Temporal.
82
120
  config['activities'] = [*activities, *self.agent.temporal_activities]
83
- return super().configure_worker(config)
121
+ return self.next_worker_plugin.configure_worker(config)
122
+
123
+ async def run_worker(self, worker: Worker) -> None:
124
+ await self.next_worker_plugin.run_worker(worker)
125
+
126
+ def configure_replayer(self, config: ReplayerConfig) -> ReplayerConfig: # pragma: no cover
127
+ return self.next_worker_plugin.configure_replayer(config)
128
+
129
+ def run_replayer(
130
+ self,
131
+ replayer: Replayer,
132
+ histories: AsyncIterator[WorkflowHistory],
133
+ ) -> AbstractAsyncContextManager[AsyncIterator[WorkflowReplayResult]]: # pragma: no cover
134
+ return self.next_worker_plugin.run_replayer(replayer, histories)
@@ -51,7 +51,10 @@ class TemporalFunctionToolset(TemporalWrapperToolset[AgentDepsT]):
51
51
  'Removing or renaming tools during an agent run is not supported with Temporal.'
52
52
  ) from e
53
53
 
54
- return await self.wrapped.call_tool(name, params.tool_args, ctx, tool)
54
+ # The tool args will already have been validated into their proper types in the `ToolManager`,
55
+ # but `execute_activity` would have turned them into simple Python types again, so we need to re-validate them.
56
+ args_dict = tool.args_validator.validate_python(params.tool_args)
57
+ return await self.wrapped.call_tool(name, args_dict, ctx, tool)
55
58
 
56
59
  # Set type hint explicitly so that Temporal can take care of serialization and deserialization
57
60
  call_tool_activity.__annotations__['deps'] = deps_type
@@ -85,7 +88,11 @@ class TemporalFunctionToolset(TemporalWrapperToolset[AgentDepsT]):
85
88
  return await workflow.execute_activity( # pyright: ignore[reportUnknownMemberType]
86
89
  activity=self.call_tool_activity,
87
90
  args=[
88
- _CallToolParams(name=name, tool_args=tool_args, serialized_run_context=serialized_run_context),
91
+ _CallToolParams(
92
+ name=name,
93
+ tool_args=tool_args,
94
+ serialized_run_context=serialized_run_context,
95
+ ),
89
96
  ctx.deps,
90
97
  ],
91
98
  **tool_activity_config,
@@ -25,10 +25,13 @@ class LogfirePlugin(ClientPlugin):
25
25
  self.setup_logfire = setup_logfire
26
26
  self.metrics = metrics
27
27
 
28
+ def init_client_plugin(self, next: ClientPlugin) -> None:
29
+ self.next_client_plugin = next
30
+
28
31
  def configure_client(self, config: ClientConfig) -> ClientConfig:
29
32
  interceptors = config.get('interceptors', [])
30
33
  config['interceptors'] = [*interceptors, TracingInterceptor(get_tracer('temporalio'))]
31
- return super().configure_client(config)
34
+ return self.next_client_plugin.configure_client(config)
32
35
 
33
36
  async def connect_service_client(self, config: ConnectConfig) -> ServiceClient:
34
37
  logfire = self.setup_logfire()
@@ -45,4 +48,4 @@ class LogfirePlugin(ClientPlugin):
45
48
  telemetry=TelemetryConfig(metrics=OpenTelemetryConfig(url=metrics_url, headers=headers))
46
49
  )
47
50
 
48
- return await super().connect_service_client(config)
51
+ return await self.next_client_plugin.connect_service_client(config)