agentex-sdk 0.1.0a6__py3-none-any.whl

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.
Files changed (289) hide show
  1. agentex/__init__.py +103 -0
  2. agentex/_base_client.py +1992 -0
  3. agentex/_client.py +506 -0
  4. agentex/_compat.py +219 -0
  5. agentex/_constants.py +14 -0
  6. agentex/_exceptions.py +108 -0
  7. agentex/_files.py +123 -0
  8. agentex/_models.py +829 -0
  9. agentex/_qs.py +150 -0
  10. agentex/_resource.py +43 -0
  11. agentex/_response.py +830 -0
  12. agentex/_streaming.py +333 -0
  13. agentex/_types.py +219 -0
  14. agentex/_utils/__init__.py +57 -0
  15. agentex/_utils/_logs.py +25 -0
  16. agentex/_utils/_proxy.py +65 -0
  17. agentex/_utils/_reflection.py +42 -0
  18. agentex/_utils/_resources_proxy.py +24 -0
  19. agentex/_utils/_streams.py +12 -0
  20. agentex/_utils/_sync.py +86 -0
  21. agentex/_utils/_transform.py +447 -0
  22. agentex/_utils/_typing.py +151 -0
  23. agentex/_utils/_utils.py +422 -0
  24. agentex/_version.py +4 -0
  25. agentex/lib/.keep +4 -0
  26. agentex/lib/__init__.py +0 -0
  27. agentex/lib/adk/__init__.py +41 -0
  28. agentex/lib/adk/_modules/__init__.py +0 -0
  29. agentex/lib/adk/_modules/acp.py +247 -0
  30. agentex/lib/adk/_modules/agent_task_tracker.py +176 -0
  31. agentex/lib/adk/_modules/agents.py +77 -0
  32. agentex/lib/adk/_modules/events.py +141 -0
  33. agentex/lib/adk/_modules/messages.py +285 -0
  34. agentex/lib/adk/_modules/state.py +291 -0
  35. agentex/lib/adk/_modules/streaming.py +75 -0
  36. agentex/lib/adk/_modules/tasks.py +124 -0
  37. agentex/lib/adk/_modules/tracing.py +194 -0
  38. agentex/lib/adk/providers/__init__.py +9 -0
  39. agentex/lib/adk/providers/_modules/__init__.py +0 -0
  40. agentex/lib/adk/providers/_modules/litellm.py +232 -0
  41. agentex/lib/adk/providers/_modules/openai.py +416 -0
  42. agentex/lib/adk/providers/_modules/sgp.py +85 -0
  43. agentex/lib/adk/utils/__init__.py +5 -0
  44. agentex/lib/adk/utils/_modules/__init__.py +0 -0
  45. agentex/lib/adk/utils/_modules/templating.py +94 -0
  46. agentex/lib/cli/__init__.py +0 -0
  47. agentex/lib/cli/commands/__init__.py +0 -0
  48. agentex/lib/cli/commands/agents.py +328 -0
  49. agentex/lib/cli/commands/init.py +227 -0
  50. agentex/lib/cli/commands/main.py +33 -0
  51. agentex/lib/cli/commands/secrets.py +169 -0
  52. agentex/lib/cli/commands/tasks.py +118 -0
  53. agentex/lib/cli/commands/uv.py +133 -0
  54. agentex/lib/cli/handlers/__init__.py +0 -0
  55. agentex/lib/cli/handlers/agent_handlers.py +160 -0
  56. agentex/lib/cli/handlers/cleanup_handlers.py +186 -0
  57. agentex/lib/cli/handlers/deploy_handlers.py +351 -0
  58. agentex/lib/cli/handlers/run_handlers.py +452 -0
  59. agentex/lib/cli/handlers/secret_handlers.py +670 -0
  60. agentex/lib/cli/templates/default/.dockerignore.j2 +43 -0
  61. agentex/lib/cli/templates/default/Dockerfile-uv.j2 +42 -0
  62. agentex/lib/cli/templates/default/Dockerfile.j2 +42 -0
  63. agentex/lib/cli/templates/default/README.md.j2 +193 -0
  64. agentex/lib/cli/templates/default/deploy/example.yaml.j2 +55 -0
  65. agentex/lib/cli/templates/default/manifest.yaml.j2 +116 -0
  66. agentex/lib/cli/templates/default/project/acp.py.j2 +29 -0
  67. agentex/lib/cli/templates/default/pyproject.toml.j2 +33 -0
  68. agentex/lib/cli/templates/default/requirements.txt.j2 +5 -0
  69. agentex/lib/cli/templates/deploy/Screenshot 2025-03-19 at 10.36.57/342/200/257AM.png +0 -0
  70. agentex/lib/cli/templates/deploy/example.yaml.j2 +55 -0
  71. agentex/lib/cli/templates/sync/.dockerignore.j2 +43 -0
  72. agentex/lib/cli/templates/sync/Dockerfile-uv.j2 +42 -0
  73. agentex/lib/cli/templates/sync/Dockerfile.j2 +42 -0
  74. agentex/lib/cli/templates/sync/README.md.j2 +293 -0
  75. agentex/lib/cli/templates/sync/deploy/example.yaml.j2 +55 -0
  76. agentex/lib/cli/templates/sync/manifest.yaml.j2 +116 -0
  77. agentex/lib/cli/templates/sync/project/acp.py.j2 +26 -0
  78. agentex/lib/cli/templates/sync/pyproject.toml.j2 +33 -0
  79. agentex/lib/cli/templates/sync/requirements.txt.j2 +5 -0
  80. agentex/lib/cli/templates/temporal/.dockerignore.j2 +43 -0
  81. agentex/lib/cli/templates/temporal/Dockerfile-uv.j2 +48 -0
  82. agentex/lib/cli/templates/temporal/Dockerfile.j2 +48 -0
  83. agentex/lib/cli/templates/temporal/README.md.j2 +316 -0
  84. agentex/lib/cli/templates/temporal/deploy/example.yaml.j2 +55 -0
  85. agentex/lib/cli/templates/temporal/manifest.yaml.j2 +137 -0
  86. agentex/lib/cli/templates/temporal/project/acp.py.j2 +30 -0
  87. agentex/lib/cli/templates/temporal/project/run_worker.py.j2 +33 -0
  88. agentex/lib/cli/templates/temporal/project/workflow.py.j2 +66 -0
  89. agentex/lib/cli/templates/temporal/pyproject.toml.j2 +34 -0
  90. agentex/lib/cli/templates/temporal/requirements.txt.j2 +5 -0
  91. agentex/lib/cli/utils/cli_utils.py +14 -0
  92. agentex/lib/cli/utils/credential_utils.py +103 -0
  93. agentex/lib/cli/utils/exceptions.py +6 -0
  94. agentex/lib/cli/utils/kubectl_utils.py +135 -0
  95. agentex/lib/cli/utils/kubernetes_secrets_utils.py +185 -0
  96. agentex/lib/core/__init__.py +0 -0
  97. agentex/lib/core/adapters/__init__.py +0 -0
  98. agentex/lib/core/adapters/llm/__init__.py +1 -0
  99. agentex/lib/core/adapters/llm/adapter_litellm.py +46 -0
  100. agentex/lib/core/adapters/llm/adapter_sgp.py +55 -0
  101. agentex/lib/core/adapters/llm/port.py +24 -0
  102. agentex/lib/core/adapters/streams/adapter_redis.py +128 -0
  103. agentex/lib/core/adapters/streams/port.py +50 -0
  104. agentex/lib/core/clients/__init__.py +1 -0
  105. agentex/lib/core/clients/temporal/__init__.py +0 -0
  106. agentex/lib/core/clients/temporal/temporal_client.py +181 -0
  107. agentex/lib/core/clients/temporal/types.py +47 -0
  108. agentex/lib/core/clients/temporal/utils.py +56 -0
  109. agentex/lib/core/services/__init__.py +0 -0
  110. agentex/lib/core/services/adk/__init__.py +0 -0
  111. agentex/lib/core/services/adk/acp/__init__.py +0 -0
  112. agentex/lib/core/services/adk/acp/acp.py +210 -0
  113. agentex/lib/core/services/adk/agent_task_tracker.py +85 -0
  114. agentex/lib/core/services/adk/agents.py +43 -0
  115. agentex/lib/core/services/adk/events.py +61 -0
  116. agentex/lib/core/services/adk/messages.py +164 -0
  117. agentex/lib/core/services/adk/providers/__init__.py +0 -0
  118. agentex/lib/core/services/adk/providers/litellm.py +256 -0
  119. agentex/lib/core/services/adk/providers/openai.py +723 -0
  120. agentex/lib/core/services/adk/providers/sgp.py +99 -0
  121. agentex/lib/core/services/adk/state.py +120 -0
  122. agentex/lib/core/services/adk/streaming.py +262 -0
  123. agentex/lib/core/services/adk/tasks.py +69 -0
  124. agentex/lib/core/services/adk/tracing.py +36 -0
  125. agentex/lib/core/services/adk/utils/__init__.py +0 -0
  126. agentex/lib/core/services/adk/utils/templating.py +58 -0
  127. agentex/lib/core/temporal/__init__.py +0 -0
  128. agentex/lib/core/temporal/activities/__init__.py +207 -0
  129. agentex/lib/core/temporal/activities/activity_helpers.py +37 -0
  130. agentex/lib/core/temporal/activities/adk/__init__.py +0 -0
  131. agentex/lib/core/temporal/activities/adk/acp/__init__.py +0 -0
  132. agentex/lib/core/temporal/activities/adk/acp/acp_activities.py +86 -0
  133. agentex/lib/core/temporal/activities/adk/agent_task_tracker_activities.py +76 -0
  134. agentex/lib/core/temporal/activities/adk/agents_activities.py +35 -0
  135. agentex/lib/core/temporal/activities/adk/events_activities.py +50 -0
  136. agentex/lib/core/temporal/activities/adk/messages_activities.py +94 -0
  137. agentex/lib/core/temporal/activities/adk/providers/__init__.py +0 -0
  138. agentex/lib/core/temporal/activities/adk/providers/litellm_activities.py +71 -0
  139. agentex/lib/core/temporal/activities/adk/providers/openai_activities.py +210 -0
  140. agentex/lib/core/temporal/activities/adk/providers/sgp_activities.py +42 -0
  141. agentex/lib/core/temporal/activities/adk/state_activities.py +85 -0
  142. agentex/lib/core/temporal/activities/adk/streaming_activities.py +33 -0
  143. agentex/lib/core/temporal/activities/adk/tasks_activities.py +48 -0
  144. agentex/lib/core/temporal/activities/adk/tracing_activities.py +55 -0
  145. agentex/lib/core/temporal/activities/adk/utils/__init__.py +0 -0
  146. agentex/lib/core/temporal/activities/adk/utils/templating_activities.py +41 -0
  147. agentex/lib/core/temporal/services/__init__.py +0 -0
  148. agentex/lib/core/temporal/services/temporal_task_service.py +69 -0
  149. agentex/lib/core/temporal/types/__init__.py +0 -0
  150. agentex/lib/core/temporal/types/workflow.py +5 -0
  151. agentex/lib/core/temporal/workers/__init__.py +0 -0
  152. agentex/lib/core/temporal/workers/worker.py +162 -0
  153. agentex/lib/core/temporal/workflows/workflow.py +26 -0
  154. agentex/lib/core/tracing/__init__.py +5 -0
  155. agentex/lib/core/tracing/processors/agentex_tracing_processor.py +117 -0
  156. agentex/lib/core/tracing/processors/sgp_tracing_processor.py +119 -0
  157. agentex/lib/core/tracing/processors/tracing_processor_interface.py +40 -0
  158. agentex/lib/core/tracing/trace.py +311 -0
  159. agentex/lib/core/tracing/tracer.py +70 -0
  160. agentex/lib/core/tracing/tracing_processor_manager.py +62 -0
  161. agentex/lib/environment_variables.py +87 -0
  162. agentex/lib/py.typed +0 -0
  163. agentex/lib/sdk/__init__.py +0 -0
  164. agentex/lib/sdk/config/__init__.py +0 -0
  165. agentex/lib/sdk/config/agent_config.py +61 -0
  166. agentex/lib/sdk/config/agent_manifest.py +219 -0
  167. agentex/lib/sdk/config/build_config.py +35 -0
  168. agentex/lib/sdk/config/deployment_config.py +117 -0
  169. agentex/lib/sdk/config/local_development_config.py +56 -0
  170. agentex/lib/sdk/config/project_config.py +103 -0
  171. agentex/lib/sdk/fastacp/__init__.py +3 -0
  172. agentex/lib/sdk/fastacp/base/base_acp_server.py +406 -0
  173. agentex/lib/sdk/fastacp/fastacp.py +74 -0
  174. agentex/lib/sdk/fastacp/impl/agentic_base_acp.py +72 -0
  175. agentex/lib/sdk/fastacp/impl/sync_acp.py +109 -0
  176. agentex/lib/sdk/fastacp/impl/temporal_acp.py +97 -0
  177. agentex/lib/sdk/fastacp/tests/README.md +297 -0
  178. agentex/lib/sdk/fastacp/tests/conftest.py +307 -0
  179. agentex/lib/sdk/fastacp/tests/pytest.ini +10 -0
  180. agentex/lib/sdk/fastacp/tests/run_tests.py +227 -0
  181. agentex/lib/sdk/fastacp/tests/test_base_acp_server.py +450 -0
  182. agentex/lib/sdk/fastacp/tests/test_fastacp_factory.py +344 -0
  183. agentex/lib/sdk/fastacp/tests/test_integration.py +477 -0
  184. agentex/lib/sdk/state_machine/__init__.py +6 -0
  185. agentex/lib/sdk/state_machine/noop_workflow.py +21 -0
  186. agentex/lib/sdk/state_machine/state.py +10 -0
  187. agentex/lib/sdk/state_machine/state_machine.py +189 -0
  188. agentex/lib/sdk/state_machine/state_workflow.py +16 -0
  189. agentex/lib/sdk/utils/__init__.py +0 -0
  190. agentex/lib/sdk/utils/messages.py +223 -0
  191. agentex/lib/types/__init__.py +0 -0
  192. agentex/lib/types/acp.py +94 -0
  193. agentex/lib/types/agent_configs.py +79 -0
  194. agentex/lib/types/agent_results.py +29 -0
  195. agentex/lib/types/credentials.py +34 -0
  196. agentex/lib/types/fastacp.py +61 -0
  197. agentex/lib/types/files.py +13 -0
  198. agentex/lib/types/json_rpc.py +49 -0
  199. agentex/lib/types/llm_messages.py +354 -0
  200. agentex/lib/types/task_message_updates.py +171 -0
  201. agentex/lib/types/tracing.py +34 -0
  202. agentex/lib/utils/__init__.py +0 -0
  203. agentex/lib/utils/completions.py +131 -0
  204. agentex/lib/utils/console.py +14 -0
  205. agentex/lib/utils/io.py +29 -0
  206. agentex/lib/utils/iterables.py +14 -0
  207. agentex/lib/utils/json_schema.py +23 -0
  208. agentex/lib/utils/logging.py +31 -0
  209. agentex/lib/utils/mcp.py +17 -0
  210. agentex/lib/utils/model_utils.py +46 -0
  211. agentex/lib/utils/parsing.py +15 -0
  212. agentex/lib/utils/regex.py +6 -0
  213. agentex/lib/utils/temporal.py +13 -0
  214. agentex/py.typed +0 -0
  215. agentex/resources/__init__.py +103 -0
  216. agentex/resources/agents.py +707 -0
  217. agentex/resources/events.py +294 -0
  218. agentex/resources/messages/__init__.py +33 -0
  219. agentex/resources/messages/batch.py +271 -0
  220. agentex/resources/messages/messages.py +492 -0
  221. agentex/resources/spans.py +557 -0
  222. agentex/resources/states.py +544 -0
  223. agentex/resources/tasks.py +615 -0
  224. agentex/resources/tracker.py +384 -0
  225. agentex/types/__init__.py +56 -0
  226. agentex/types/acp_type.py +7 -0
  227. agentex/types/agent.py +29 -0
  228. agentex/types/agent_list_params.py +13 -0
  229. agentex/types/agent_list_response.py +10 -0
  230. agentex/types/agent_rpc_by_name_params.py +21 -0
  231. agentex/types/agent_rpc_params.py +51 -0
  232. agentex/types/agent_rpc_params1.py +21 -0
  233. agentex/types/agent_rpc_response.py +20 -0
  234. agentex/types/agent_rpc_result.py +90 -0
  235. agentex/types/agent_task_tracker.py +34 -0
  236. agentex/types/data_content.py +30 -0
  237. agentex/types/data_content_param.py +31 -0
  238. agentex/types/data_delta.py +14 -0
  239. agentex/types/event.py +29 -0
  240. agentex/types/event_list_params.py +22 -0
  241. agentex/types/event_list_response.py +10 -0
  242. agentex/types/message_author.py +7 -0
  243. agentex/types/message_create_params.py +18 -0
  244. agentex/types/message_list_params.py +14 -0
  245. agentex/types/message_list_response.py +10 -0
  246. agentex/types/message_style.py +7 -0
  247. agentex/types/message_update_params.py +18 -0
  248. agentex/types/messages/__init__.py +8 -0
  249. agentex/types/messages/batch_create_params.py +16 -0
  250. agentex/types/messages/batch_create_response.py +10 -0
  251. agentex/types/messages/batch_update_params.py +16 -0
  252. agentex/types/messages/batch_update_response.py +10 -0
  253. agentex/types/shared/__init__.py +3 -0
  254. agentex/types/shared/task_message_update.py +83 -0
  255. agentex/types/span.py +36 -0
  256. agentex/types/span_create_params.py +40 -0
  257. agentex/types/span_list_params.py +12 -0
  258. agentex/types/span_list_response.py +10 -0
  259. agentex/types/span_update_params.py +37 -0
  260. agentex/types/state.py +25 -0
  261. agentex/types/state_create_params.py +16 -0
  262. agentex/types/state_list_params.py +16 -0
  263. agentex/types/state_list_response.py +10 -0
  264. agentex/types/state_update_params.py +16 -0
  265. agentex/types/task.py +23 -0
  266. agentex/types/task_delete_by_name_response.py +8 -0
  267. agentex/types/task_delete_response.py +8 -0
  268. agentex/types/task_list_response.py +10 -0
  269. agentex/types/task_message.py +33 -0
  270. agentex/types/task_message_content.py +16 -0
  271. agentex/types/task_message_content_param.py +17 -0
  272. agentex/types/task_message_delta.py +16 -0
  273. agentex/types/text_content.py +53 -0
  274. agentex/types/text_content_param.py +54 -0
  275. agentex/types/text_delta.py +14 -0
  276. agentex/types/tool_request_content.py +36 -0
  277. agentex/types/tool_request_content_param.py +37 -0
  278. agentex/types/tool_request_delta.py +18 -0
  279. agentex/types/tool_response_content.py +36 -0
  280. agentex/types/tool_response_content_param.py +36 -0
  281. agentex/types/tool_response_delta.py +18 -0
  282. agentex/types/tracker_list_params.py +16 -0
  283. agentex/types/tracker_list_response.py +10 -0
  284. agentex/types/tracker_update_params.py +19 -0
  285. agentex_sdk-0.1.0a6.dist-info/METADATA +426 -0
  286. agentex_sdk-0.1.0a6.dist-info/RECORD +289 -0
  287. agentex_sdk-0.1.0a6.dist-info/WHEEL +4 -0
  288. agentex_sdk-0.1.0a6.dist-info/entry_points.txt +2 -0
  289. agentex_sdk-0.1.0a6.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,723 @@
1
+ # Standard library imports
2
+ import json
3
+ from contextlib import AsyncExitStack, asynccontextmanager
4
+ from typing import Any, Literal
5
+
6
+ from agents import Agent, Runner, RunResult, RunResultStreaming
7
+ from agents.agent import StopAtTools, ToolsToFinalOutputFunction
8
+ from agents.mcp import MCPServerStdio
9
+ from mcp import StdioServerParameters
10
+ from openai.types.responses import (
11
+ ResponseCompletedEvent,
12
+ ResponseFunctionToolCall,
13
+ ResponseOutputItemDoneEvent,
14
+ ResponseTextDeltaEvent,
15
+ )
16
+ from pydantic import BaseModel
17
+
18
+ # Local imports
19
+ from agentex import AsyncAgentex
20
+ from agentex.lib.core.services.adk.streaming import (
21
+ StreamingService,
22
+ StreamingTaskMessageContext,
23
+ )
24
+ from agentex.lib.core.tracing.tracer import AsyncTracer
25
+ from agentex.lib.types.task_message_updates import (
26
+ StreamTaskMessageDelta,
27
+ StreamTaskMessageFull,
28
+ TextDelta,
29
+ )
30
+ from agentex.types.task_message_content import (
31
+ TextContent,
32
+ ToolRequestContent,
33
+ ToolResponseContent,
34
+ )
35
+ from agentex.lib.utils import logging
36
+ from agentex.lib.utils.mcp import redact_mcp_server_params
37
+ from agentex.lib.utils.temporal import heartbeat_if_in_workflow
38
+
39
+ logger = logging.make_logger(__name__)
40
+
41
+
42
+ @asynccontextmanager
43
+ async def mcp_server_context(
44
+ mcp_server_params: list[StdioServerParameters],
45
+ mcp_timeout_seconds: int | None = None,
46
+ ):
47
+ """Context manager for MCP servers."""
48
+ servers = []
49
+ for params in mcp_server_params:
50
+ server = MCPServerStdio(
51
+ name=f"Server: {params.command}",
52
+ params=params.model_dump(),
53
+ cache_tools_list=True,
54
+ client_session_timeout_seconds=mcp_timeout_seconds,
55
+ )
56
+ servers.append(server)
57
+
58
+ async with AsyncExitStack() as stack:
59
+ for server in servers:
60
+ await stack.enter_async_context(server)
61
+ yield servers
62
+
63
+
64
+ class OpenAIService:
65
+ """Service for OpenAI agent operations using the agents library."""
66
+
67
+ def __init__(
68
+ self,
69
+ agentex_client: AsyncAgentex | None = None,
70
+ streaming_service: StreamingService | None = None,
71
+ tracer: AsyncTracer | None = None,
72
+ ):
73
+ self.agentex_client = agentex_client
74
+ self.streaming_service = streaming_service
75
+ self.tracer = tracer
76
+
77
+ async def run_agent(
78
+ self,
79
+ input_list: list[dict[str, Any]],
80
+ mcp_server_params: list[StdioServerParameters],
81
+ agent_name: str,
82
+ agent_instructions: str,
83
+ trace_id: str | None = None,
84
+ parent_span_id: str | None = None,
85
+ handoff_description: str | None = None,
86
+ handoffs: list[BaseModel] | None = None,
87
+ model: str | None = None,
88
+ model_settings: BaseModel | None = None,
89
+ tools: list[BaseModel] | None = None,
90
+ output_type: type[Any] | None = None,
91
+ tool_use_behavior: (
92
+ Literal["run_llm_again", "stop_on_first_tool"]
93
+ | StopAtTools
94
+ | ToolsToFinalOutputFunction
95
+ ) = "run_llm_again",
96
+ mcp_timeout_seconds: int | None = None,
97
+ ) -> RunResult:
98
+ """
99
+ Run an agent without streaming or TaskMessage creation.
100
+
101
+ Args:
102
+ input_list: List of input data for the agent.
103
+ mcp_server_params: MCP server parameters for the agent.
104
+ agent_name: The name of the agent to run.
105
+ agent_instructions: Instructions for the agent.
106
+ trace_id: Optional trace ID for tracing.
107
+ parent_span_id: Optional parent span ID for tracing.
108
+ handoff_description: Optional description of the handoff.
109
+ handoffs: Optional list of handoffs.
110
+ model: Optional model to use.
111
+ model_settings: Optional model settings.
112
+ tools: Optional list of tools.
113
+ output_type: Optional output type.
114
+ tool_use_behavior: Optional tool use behavior.
115
+ mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
116
+
117
+ Returns:
118
+ SerializableRunResult: The result of the agent run.
119
+ """
120
+ redacted_params = redact_mcp_server_params(mcp_server_params)
121
+
122
+ trace = self.tracer.trace(trace_id)
123
+ async with trace.span(
124
+ parent_id=parent_span_id,
125
+ name="run_agent",
126
+ input={
127
+ "input_list": input_list,
128
+ "mcp_server_params": redacted_params,
129
+ "agent_name": agent_name,
130
+ "agent_instructions": agent_instructions,
131
+ "handoff_description": handoff_description,
132
+ "handoffs": handoffs,
133
+ "model": model,
134
+ "model_settings": model_settings,
135
+ "tools": tools,
136
+ "output_type": output_type,
137
+ "tool_use_behavior": tool_use_behavior,
138
+ },
139
+ ) as span:
140
+ heartbeat_if_in_workflow("run agent")
141
+
142
+ async with mcp_server_context(
143
+ mcp_server_params, mcp_timeout_seconds
144
+ ) as servers:
145
+ tools = [tool.to_oai_function_tool() for tool in tools] if tools else []
146
+ handoffs = (
147
+ [Agent(**handoff.model_dump()) for handoff in handoffs]
148
+ if handoffs
149
+ else []
150
+ )
151
+
152
+ agent_kwargs = {
153
+ "name": agent_name,
154
+ "instructions": agent_instructions,
155
+ "mcp_servers": servers,
156
+ "handoff_description": handoff_description,
157
+ "handoffs": handoffs,
158
+ "model": model,
159
+ "tools": tools,
160
+ "output_type": output_type,
161
+ "tool_use_behavior": tool_use_behavior,
162
+ }
163
+ if model_settings is not None:
164
+ agent_kwargs["model_settings"] = (
165
+ model_settings.to_oai_model_settings()
166
+ )
167
+
168
+ agent = Agent(**agent_kwargs)
169
+
170
+ # Run without streaming
171
+ result = await Runner.run(starting_agent=agent, input=input_list)
172
+
173
+ if span:
174
+ span.output = {
175
+ "new_items": [
176
+ item.raw_item.model_dump()
177
+ if isinstance(item.raw_item, BaseModel)
178
+ else item.raw_item
179
+ for item in result.new_items
180
+ ],
181
+ "final_output": result.final_output,
182
+ }
183
+
184
+ return result
185
+
186
+ async def run_agent_auto_send(
187
+ self,
188
+ task_id: str,
189
+ input_list: list[dict[str, Any]],
190
+ mcp_server_params: list[StdioServerParameters],
191
+ agent_name: str,
192
+ agent_instructions: str,
193
+ trace_id: str | None = None,
194
+ parent_span_id: str | None = None,
195
+ handoff_description: str | None = None,
196
+ handoffs: list[BaseModel] | None = None,
197
+ model: str | None = None,
198
+ model_settings: BaseModel | None = None,
199
+ tools: list[BaseModel] | None = None,
200
+ output_type: type[Any] | None = None,
201
+ tool_use_behavior: (
202
+ Literal["run_llm_again", "stop_on_first_tool"]
203
+ | StopAtTools
204
+ | ToolsToFinalOutputFunction
205
+ ) = "run_llm_again",
206
+ mcp_timeout_seconds: int | None = None,
207
+ ) -> RunResult:
208
+ """
209
+ Run an agent with automatic TaskMessage creation.
210
+
211
+ Args:
212
+ task_id: The ID of the task to run the agent for.
213
+ input_list: List of input data for the agent.
214
+ mcp_server_params: MCP server parameters for the agent.
215
+ agent_name: The name of the agent to run.
216
+ agent_instructions: Instructions for the agent.
217
+ trace_id: Optional trace ID for tracing.
218
+ parent_span_id: Optional parent span ID for tracing.
219
+ handoff_description: Optional description of the handoff.
220
+ handoffs: Optional list of handoffs.
221
+ model: Optional model to use.
222
+ model_settings: Optional model settings.
223
+ tools: Optional list of tools.
224
+ output_type: Optional output type.
225
+ tool_use_behavior: Optional tool use behavior.
226
+ mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
227
+
228
+ Returns:
229
+ SerializableRunResult: The result of the agent run.
230
+ """
231
+ if self.streaming_service is None:
232
+ raise ValueError("StreamingService must be available for auto_send methods")
233
+ if self.agentex_client is None:
234
+ raise ValueError("Agentex client must be provided for auto_send methods")
235
+
236
+ redacted_params = redact_mcp_server_params(mcp_server_params)
237
+
238
+ trace = self.tracer.trace(trace_id)
239
+ async with trace.span(
240
+ parent_id=parent_span_id,
241
+ name="run_agent_auto_send",
242
+ input={
243
+ "task_id": task_id,
244
+ "input_list": input_list,
245
+ "mcp_server_params": redacted_params,
246
+ "agent_name": agent_name,
247
+ "agent_instructions": agent_instructions,
248
+ "handoff_description": handoff_description,
249
+ "handoffs": handoffs,
250
+ "model": model,
251
+ "model_settings": model_settings,
252
+ "tools": tools,
253
+ "output_type": output_type,
254
+ "tool_use_behavior": tool_use_behavior,
255
+ },
256
+ ) as span:
257
+ heartbeat_if_in_workflow("run agent auto send")
258
+
259
+ async with mcp_server_context(
260
+ mcp_server_params, mcp_timeout_seconds
261
+ ) as servers:
262
+ tools = [tool.to_oai_function_tool() for tool in tools] if tools else []
263
+ handoffs = (
264
+ [Agent(**handoff.model_dump()) for handoff in handoffs]
265
+ if handoffs
266
+ else []
267
+ )
268
+ agent_kwargs = {
269
+ "name": agent_name,
270
+ "instructions": agent_instructions,
271
+ "mcp_servers": servers,
272
+ "handoff_description": handoff_description,
273
+ "handoffs": handoffs,
274
+ "model": model,
275
+ "tools": tools,
276
+ "output_type": output_type,
277
+ "tool_use_behavior": tool_use_behavior,
278
+ }
279
+ if model_settings is not None:
280
+ agent_kwargs["model_settings"] = (
281
+ model_settings.to_oai_model_settings()
282
+ )
283
+
284
+ agent = Agent(**agent_kwargs)
285
+
286
+ # Run without streaming
287
+ result = await Runner.run(starting_agent=agent, input=input_list)
288
+
289
+ if span:
290
+ span.output = {
291
+ "new_items": [
292
+ item.raw_item.model_dump()
293
+ if isinstance(item.raw_item, BaseModel)
294
+ else item.raw_item
295
+ for item in result.new_items
296
+ ],
297
+ "final_output": result.final_output,
298
+ }
299
+
300
+ tool_call_map: dict[str, ResponseFunctionToolCall] = {}
301
+
302
+ for item in result.new_items:
303
+ if item.type == "message_output_item":
304
+ text_content = TextContent(
305
+ author="agent",
306
+ content=item.raw_item.content[0].text,
307
+ )
308
+ # Create message for the final result using streaming context
309
+ async with (
310
+ self.streaming_service.streaming_task_message_context(
311
+ task_id=task_id,
312
+ initial_content=text_content,
313
+ ) as streaming_context
314
+ ):
315
+ await streaming_context.stream_update(
316
+ update=StreamTaskMessageFull(
317
+ parent_task_message=streaming_context.task_message,
318
+ content=text_content,
319
+ ),
320
+ )
321
+
322
+ elif item.type == "tool_call_item":
323
+ tool_call_map[item.raw_item.call_id] = item.raw_item
324
+
325
+ tool_request_content = ToolRequestContent(
326
+ author="agent",
327
+ tool_call_id=item.raw_item.call_id,
328
+ name=item.raw_item.name,
329
+ arguments=json.loads(item.raw_item.arguments),
330
+ )
331
+
332
+ # Create tool request using streaming context
333
+ async with (
334
+ self.streaming_service.streaming_task_message_context(
335
+ task_id=task_id,
336
+ initial_content=tool_request_content,
337
+ ) as streaming_context
338
+ ):
339
+ await streaming_context.stream_update(
340
+ update=StreamTaskMessageFull(
341
+ parent_task_message=streaming_context.task_message,
342
+ content=tool_request_content,
343
+ ),
344
+ )
345
+
346
+ elif item.type == "tool_call_output_item":
347
+ tool_output_item = item.raw_item
348
+
349
+ tool_response_content = ToolResponseContent(
350
+ author="agent",
351
+ tool_call_id=tool_output_item["call_id"],
352
+ name=tool_call_map[tool_output_item["call_id"]].name,
353
+ content=tool_output_item["output"],
354
+ )
355
+ # Create tool response using streaming context
356
+ async with (
357
+ self.streaming_service.streaming_task_message_context(
358
+ task_id=task_id,
359
+ initial_content=tool_response_content,
360
+ ) as streaming_context
361
+ ):
362
+ await streaming_context.stream_update(
363
+ update=StreamTaskMessageFull(
364
+ parent_task_message=streaming_context.task_message,
365
+ content=tool_response_content,
366
+ ),
367
+ )
368
+
369
+ # Convert to serializable result
370
+ return result
371
+
372
+ async def run_agent_streamed(
373
+ self,
374
+ input_list: list[dict[str, Any]],
375
+ mcp_server_params: list[StdioServerParameters],
376
+ agent_name: str,
377
+ agent_instructions: str,
378
+ trace_id: str | None = None,
379
+ parent_span_id: str | None = None,
380
+ handoff_description: str | None = None,
381
+ handoffs: list[BaseModel] | None = None,
382
+ model: str | None = None,
383
+ model_settings: BaseModel | None = None,
384
+ tools: list[BaseModel] | None = None,
385
+ output_type: type[Any] | None = None,
386
+ tool_use_behavior: (
387
+ Literal["run_llm_again", "stop_on_first_tool"]
388
+ | StopAtTools
389
+ | ToolsToFinalOutputFunction
390
+ ) = "run_llm_again",
391
+ mcp_timeout_seconds: int | None = None,
392
+ ) -> RunResultStreaming:
393
+ """
394
+ Run an agent with streaming enabled but no TaskMessage creation.
395
+
396
+ Args:
397
+ input_list: List of input data for the agent.
398
+ mcp_server_params: MCP server parameters for the agent.
399
+ agent_name: The name of the agent to run.
400
+ agent_instructions: Instructions for the agent.
401
+ trace_id: Optional trace ID for tracing.
402
+ parent_span_id: Optional parent span ID for tracing.
403
+ handoff_description: Optional description of the handoff.
404
+ handoffs: Optional list of handoffs.
405
+ model: Optional model to use.
406
+ model_settings: Optional model settings.
407
+ tools: Optional list of tools.
408
+ output_type: Optional output type.
409
+ tool_use_behavior: Optional tool use behavior.
410
+ mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
411
+
412
+ Returns:
413
+ RunResultStreaming: The result of the agent run with streaming.
414
+ """
415
+ trace = self.tracer.trace(trace_id)
416
+ redacted_params = redact_mcp_server_params(mcp_server_params)
417
+
418
+ async with trace.span(
419
+ parent_id=parent_span_id,
420
+ name="run_agent_streamed",
421
+ input={
422
+ "input_list": input_list,
423
+ "mcp_server_params": redacted_params,
424
+ "agent_name": agent_name,
425
+ "agent_instructions": agent_instructions,
426
+ "handoff_description": handoff_description,
427
+ "handoffs": handoffs,
428
+ "model": model,
429
+ "model_settings": model_settings,
430
+ "tools": tools,
431
+ "output_type": output_type,
432
+ "tool_use_behavior": tool_use_behavior,
433
+ },
434
+ ) as span:
435
+ heartbeat_if_in_workflow("run agent streamed")
436
+
437
+ async with mcp_server_context(
438
+ mcp_server_params, mcp_timeout_seconds
439
+ ) as servers:
440
+ tools = [tool.to_oai_function_tool() for tool in tools] if tools else []
441
+ handoffs = (
442
+ [Agent(**handoff.model_dump()) for handoff in handoffs]
443
+ if handoffs
444
+ else []
445
+ )
446
+ agent_kwargs = {
447
+ "name": agent_name,
448
+ "instructions": agent_instructions,
449
+ "mcp_servers": servers,
450
+ "handoff_description": handoff_description,
451
+ "handoffs": handoffs,
452
+ "model": model,
453
+ "tools": tools,
454
+ "output_type": output_type,
455
+ "tool_use_behavior": tool_use_behavior,
456
+ }
457
+ if model_settings is not None:
458
+ agent_kwargs["model_settings"] = (
459
+ model_settings.to_oai_model_settings()
460
+ )
461
+
462
+ agent = Agent(**agent_kwargs)
463
+
464
+ # Run with streaming (but no TaskMessage creation)
465
+ result = Runner.run_streamed(starting_agent=agent, input=input_list)
466
+
467
+ if span:
468
+ span.output = {
469
+ "new_items": [
470
+ item.raw_item.model_dump()
471
+ if isinstance(item.raw_item, BaseModel)
472
+ else item.raw_item
473
+ for item in result.new_items
474
+ ],
475
+ "final_output": result.final_output,
476
+ }
477
+
478
+ return result
479
+
480
+ async def run_agent_streamed_auto_send(
481
+ self,
482
+ task_id: str,
483
+ input_list: list[dict[str, Any]],
484
+ mcp_server_params: list[StdioServerParameters],
485
+ agent_name: str,
486
+ agent_instructions: str,
487
+ trace_id: str | None = None,
488
+ parent_span_id: str | None = None,
489
+ handoff_description: str | None = None,
490
+ handoffs: list[BaseModel] | None = None,
491
+ model: str | None = None,
492
+ model_settings: BaseModel | None = None,
493
+ tools: list[BaseModel] | None = None,
494
+ output_type: type[Any] | None = None,
495
+ tool_use_behavior: (
496
+ Literal["run_llm_again", "stop_on_first_tool"]
497
+ | StopAtTools
498
+ | ToolsToFinalOutputFunction
499
+ ) = "run_llm_again",
500
+ mcp_timeout_seconds: int | None = None,
501
+ ) -> RunResultStreaming:
502
+ """
503
+ Run an agent with streaming enabled and automatic TaskMessage creation.
504
+
505
+ Args:
506
+ task_id: The ID of the task to run the agent for.
507
+ input_list: List of input data for the agent.
508
+ mcp_server_params: MCP server parameters for the agent.
509
+ agent_name: The name of the agent to run.
510
+ agent_instructions: Instructions for the agent.
511
+ trace_id: Optional trace ID for tracing.
512
+ parent_span_id: Optional parent span ID for tracing.
513
+ handoff_description: Optional description of the handoff.
514
+ handoffs: Optional list of handoffs.
515
+ model: Optional model to use.
516
+ model_settings: Optional model settings.
517
+ tools: Optional list of tools.
518
+ output_type: Optional output type.
519
+ tool_use_behavior: Optional tool use behavior.
520
+ mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
521
+
522
+ Returns:
523
+ RunResultStreaming: The result of the agent run with streaming.
524
+ """
525
+ if self.streaming_service is None:
526
+ raise ValueError("StreamingService must be available for auto_send methods")
527
+ if self.agentex_client is None:
528
+ raise ValueError("Agentex client must be provided for auto_send methods")
529
+
530
+ tool_call_map: dict[str, ResponseFunctionToolCall] = {}
531
+
532
+ trace = self.tracer.trace(trace_id)
533
+ redacted_params = redact_mcp_server_params(mcp_server_params)
534
+
535
+ async with trace.span(
536
+ parent_id=parent_span_id,
537
+ name="run_agent_streamed_auto_send",
538
+ input={
539
+ "task_id": task_id,
540
+ "input_list": input_list,
541
+ "mcp_server_params": redacted_params,
542
+ "agent_name": agent_name,
543
+ "agent_instructions": agent_instructions,
544
+ "handoff_description": handoff_description,
545
+ "handoffs": handoffs,
546
+ "model": model,
547
+ "model_settings": model_settings,
548
+ "tools": tools,
549
+ "output_type": output_type,
550
+ "tool_use_behavior": tool_use_behavior,
551
+ },
552
+ ) as span:
553
+ heartbeat_if_in_workflow("run agent streamed auto send")
554
+
555
+ async with mcp_server_context(
556
+ mcp_server_params, mcp_timeout_seconds
557
+ ) as servers:
558
+ tools = [tool.to_oai_function_tool() for tool in tools] if tools else []
559
+ handoffs = (
560
+ [Agent(**handoff.model_dump()) for handoff in handoffs]
561
+ if handoffs
562
+ else []
563
+ )
564
+ agent_kwargs = {
565
+ "name": agent_name,
566
+ "instructions": agent_instructions,
567
+ "mcp_servers": servers,
568
+ "handoff_description": handoff_description,
569
+ "handoffs": handoffs,
570
+ "model": model,
571
+ "tools": tools,
572
+ "output_type": output_type,
573
+ "tool_use_behavior": tool_use_behavior,
574
+ }
575
+ if model_settings is not None:
576
+ agent_kwargs["model_settings"] = (
577
+ model_settings.to_oai_model_settings()
578
+ )
579
+
580
+ agent = Agent(**agent_kwargs)
581
+
582
+ # Run with streaming
583
+ result = Runner.run_streamed(starting_agent=agent, input=input_list)
584
+
585
+ item_id_to_streaming_context: dict[
586
+ str, StreamingTaskMessageContext
587
+ ] = {}
588
+ unclosed_item_ids: set[str] = set()
589
+
590
+ try:
591
+ # Process streaming events with TaskMessage creation
592
+ async for event in result.stream_events():
593
+ heartbeat_if_in_workflow(
594
+ "processing stream event with auto send"
595
+ )
596
+
597
+ if event.type == "run_item_stream_event":
598
+ if event.item.type == "tool_call_item":
599
+ tool_call_item = event.item.raw_item
600
+ tool_call_map[tool_call_item.call_id] = tool_call_item
601
+
602
+ tool_request_content = ToolRequestContent(
603
+ author="agent",
604
+ tool_call_id=tool_call_item.call_id,
605
+ name=tool_call_item.name,
606
+ arguments=json.loads(tool_call_item.arguments),
607
+ )
608
+
609
+ # Create tool request using streaming context (immediate completion)
610
+ async with (
611
+ self.streaming_service.streaming_task_message_context(
612
+ task_id=task_id,
613
+ initial_content=tool_request_content,
614
+ ) as streaming_context
615
+ ):
616
+ # The message has already been persisted, but we still need to send an upda
617
+ await streaming_context.stream_update(
618
+ update=StreamTaskMessageFull(
619
+ parent_task_message=streaming_context.task_message,
620
+ content=tool_request_content,
621
+ ),
622
+ )
623
+
624
+ elif event.item.type == "tool_call_output_item":
625
+ tool_output_item = event.item.raw_item
626
+
627
+ tool_response_content = ToolResponseContent(
628
+ author="agent",
629
+ tool_call_id=tool_output_item["call_id"],
630
+ name=tool_call_map[
631
+ tool_output_item["call_id"]
632
+ ].name,
633
+ content=tool_output_item["output"],
634
+ )
635
+
636
+ # Create tool response using streaming context (immediate completion)
637
+ async with (
638
+ self.streaming_service.streaming_task_message_context(
639
+ task_id=task_id,
640
+ initial_content=tool_response_content,
641
+ ) as streaming_context
642
+ ):
643
+ # The message has already been persisted, but we still need to send an update
644
+ await streaming_context.stream_update(
645
+ update=StreamTaskMessageFull(
646
+ parent_task_message=streaming_context.task_message,
647
+ content=tool_response_content,
648
+ ),
649
+ )
650
+
651
+ elif event.type == "raw_response_event":
652
+ if isinstance(event.data, ResponseTextDeltaEvent):
653
+ # Handle text delta
654
+ item_id = event.data.item_id
655
+
656
+ # Check if we already have a streaming context for this item
657
+ if item_id not in item_id_to_streaming_context:
658
+ # Create a new streaming context for this item
659
+ streaming_context = self.streaming_service.streaming_task_message_context(
660
+ task_id=task_id,
661
+ initial_content=TextContent(
662
+ author="agent",
663
+ content="",
664
+ ),
665
+ )
666
+ # Open the streaming context
667
+ item_id_to_streaming_context[
668
+ item_id
669
+ ] = await streaming_context.open()
670
+ unclosed_item_ids.add(item_id)
671
+ else:
672
+ streaming_context = item_id_to_streaming_context[
673
+ item_id
674
+ ]
675
+
676
+ # Stream the delta through the streaming service
677
+ await streaming_context.stream_update(
678
+ update=StreamTaskMessageDelta(
679
+ parent_task_message=streaming_context.task_message,
680
+ delta=TextDelta(text_delta=event.data.delta),
681
+ ),
682
+ )
683
+
684
+ elif isinstance(event.data, ResponseOutputItemDoneEvent):
685
+ # Handle item completion
686
+ item_id = event.data.item.id
687
+
688
+ # Finish the streaming context (sends DONE event and updates message)
689
+ if item_id in item_id_to_streaming_context:
690
+ streaming_context = item_id_to_streaming_context[
691
+ item_id
692
+ ]
693
+ await streaming_context.close()
694
+ unclosed_item_ids.remove(item_id)
695
+
696
+ elif isinstance(event.data, ResponseCompletedEvent):
697
+ # All items complete, finish all remaining streaming contexts for this session
698
+ for item_id in unclosed_item_ids:
699
+ streaming_context = item_id_to_streaming_context[
700
+ item_id
701
+ ]
702
+ await streaming_context.close()
703
+ unclosed_item_ids.remove(item_id)
704
+
705
+ finally:
706
+ # Cleanup: ensure all streaming contexts for this session are properly finished
707
+ for item_id in unclosed_item_ids:
708
+ streaming_context = item_id_to_streaming_context[item_id]
709
+ await streaming_context.close()
710
+ unclosed_item_ids.remove(item_id)
711
+
712
+ if span:
713
+ span.output = {
714
+ "new_items": [
715
+ item.raw_item.model_dump()
716
+ if isinstance(item.raw_item, BaseModel)
717
+ else item.raw_item
718
+ for item in result.new_items
719
+ ],
720
+ "final_output": result.final_output,
721
+ }
722
+
723
+ return result