agentex-sdk 0.4.11__py3-none-any.whl → 0.4.12__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.
- agentex/_version.py +1 -1
- agentex/lib/adk/_modules/acp.py +15 -3
- agentex/lib/adk/providers/_modules/openai.py +15 -0
- agentex/lib/cli/handlers/deploy_handlers.py +4 -1
- agentex/lib/cli/templates/temporal/environments.yaml.j2 +1 -1
- agentex/lib/core/services/adk/acp/acp.py +27 -12
- agentex/lib/core/services/adk/providers/openai.py +149 -25
- agentex/lib/core/temporal/activities/adk/acp/acp_activities.py +6 -0
- agentex/lib/core/temporal/activities/adk/providers/openai_activities.py +265 -149
- {agentex_sdk-0.4.11.dist-info → agentex_sdk-0.4.12.dist-info}/METADATA +1 -1
- {agentex_sdk-0.4.11.dist-info → agentex_sdk-0.4.12.dist-info}/RECORD +14 -14
- {agentex_sdk-0.4.11.dist-info → agentex_sdk-0.4.12.dist-info}/WHEEL +0 -0
- {agentex_sdk-0.4.11.dist-info → agentex_sdk-0.4.12.dist-info}/entry_points.txt +0 -0
- {agentex_sdk-0.4.11.dist-info → agentex_sdk-0.4.12.dist-info}/licenses/LICENSE +0 -0
agentex/_version.py
CHANGED
agentex/lib/adk/_modules/acp.py
CHANGED
@@ -205,6 +205,8 @@ class ACPModule:
|
|
205
205
|
self,
|
206
206
|
task_id: str | None = None,
|
207
207
|
task_name: str | None = None,
|
208
|
+
agent_id: str | None = None,
|
209
|
+
agent_name: str | None = None,
|
208
210
|
trace_id: str | None = None,
|
209
211
|
parent_span_id: str | None = None,
|
210
212
|
start_to_close_timeout: timedelta = timedelta(seconds=5),
|
@@ -212,11 +214,13 @@ class ACPModule:
|
|
212
214
|
retry_policy: RetryPolicy = DEFAULT_RETRY_POLICY,
|
213
215
|
) -> Task:
|
214
216
|
"""
|
215
|
-
Cancel a task.
|
217
|
+
Cancel a task by sending cancel request to the agent that owns the task.
|
216
218
|
|
217
219
|
Args:
|
218
|
-
task_id:
|
219
|
-
task_name:
|
220
|
+
task_id: ID of the task to cancel.
|
221
|
+
task_name: Name of the task to cancel.
|
222
|
+
agent_id: ID of the agent that owns the task.
|
223
|
+
agent_name: Name of the agent that owns the task.
|
220
224
|
trace_id: The trace ID for the task.
|
221
225
|
parent_span_id: The parent span ID for the task.
|
222
226
|
start_to_close_timeout: The start to close timeout for the task.
|
@@ -225,6 +229,10 @@ class ACPModule:
|
|
225
229
|
|
226
230
|
Returns:
|
227
231
|
The task entry.
|
232
|
+
|
233
|
+
Raises:
|
234
|
+
ValueError: If neither agent_name nor agent_id is provided,
|
235
|
+
or if neither task_name nor task_id is provided
|
228
236
|
"""
|
229
237
|
if in_temporal_workflow():
|
230
238
|
return await ActivityHelpers.execute_activity(
|
@@ -232,6 +240,8 @@ class ACPModule:
|
|
232
240
|
request=TaskCancelParams(
|
233
241
|
task_id=task_id,
|
234
242
|
task_name=task_name,
|
243
|
+
agent_id=agent_id,
|
244
|
+
agent_name=agent_name,
|
235
245
|
trace_id=trace_id,
|
236
246
|
parent_span_id=parent_span_id,
|
237
247
|
),
|
@@ -244,6 +254,8 @@ class ACPModule:
|
|
244
254
|
return await self._acp_service.task_cancel(
|
245
255
|
task_id=task_id,
|
246
256
|
task_name=task_name,
|
257
|
+
agent_id=agent_id,
|
258
|
+
agent_name=agent_name,
|
247
259
|
trace_id=trace_id,
|
248
260
|
parent_span_id=parent_span_id,
|
249
261
|
)
|
@@ -88,6 +88,7 @@ class OpenAIModule:
|
|
88
88
|
mcp_timeout_seconds: int | None = None,
|
89
89
|
input_guardrails: list[InputGuardrail] | None = None,
|
90
90
|
output_guardrails: list[OutputGuardrail] | None = None,
|
91
|
+
max_turns: int | None = None,
|
91
92
|
) -> SerializableRunResult | RunResult:
|
92
93
|
"""
|
93
94
|
Run an agent without streaming or TaskMessage creation.
|
@@ -114,6 +115,7 @@ class OpenAIModule:
|
|
114
115
|
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
115
116
|
input_guardrails: Optional list of input guardrails to run on initial user input.
|
116
117
|
output_guardrails: Optional list of output guardrails to run on final agent output.
|
118
|
+
max_turns: Maximum number of turns the agent can take. Uses Runner's default if None.
|
117
119
|
|
118
120
|
Returns:
|
119
121
|
Union[SerializableRunResult, RunResult]: SerializableRunResult when in Temporal, RunResult otherwise.
|
@@ -136,6 +138,7 @@ class OpenAIModule:
|
|
136
138
|
mcp_timeout_seconds=mcp_timeout_seconds,
|
137
139
|
input_guardrails=input_guardrails,
|
138
140
|
output_guardrails=output_guardrails,
|
141
|
+
max_turns=max_turns,
|
139
142
|
)
|
140
143
|
return await ActivityHelpers.execute_activity(
|
141
144
|
activity_name=OpenAIActivityName.RUN_AGENT,
|
@@ -163,6 +166,7 @@ class OpenAIModule:
|
|
163
166
|
mcp_timeout_seconds=mcp_timeout_seconds,
|
164
167
|
input_guardrails=input_guardrails,
|
165
168
|
output_guardrails=output_guardrails,
|
169
|
+
max_turns=max_turns,
|
166
170
|
)
|
167
171
|
|
168
172
|
async def run_agent_auto_send(
|
@@ -191,6 +195,7 @@ class OpenAIModule:
|
|
191
195
|
mcp_timeout_seconds: int | None = None,
|
192
196
|
input_guardrails: list[InputGuardrail] | None = None,
|
193
197
|
output_guardrails: list[OutputGuardrail] | None = None,
|
198
|
+
max_turns: int | None = None,
|
194
199
|
) -> SerializableRunResult | RunResult:
|
195
200
|
"""
|
196
201
|
Run an agent with automatic TaskMessage creation.
|
@@ -216,6 +221,7 @@ class OpenAIModule:
|
|
216
221
|
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
217
222
|
input_guardrails: Optional list of input guardrails to run on initial user input.
|
218
223
|
output_guardrails: Optional list of output guardrails to run on final agent output.
|
224
|
+
max_turns: Maximum number of turns the agent can take. Uses Runner's default if None.
|
219
225
|
|
220
226
|
Returns:
|
221
227
|
Union[SerializableRunResult, RunResult]: SerializableRunResult when in Temporal, RunResult otherwise.
|
@@ -239,6 +245,7 @@ class OpenAIModule:
|
|
239
245
|
mcp_timeout_seconds=mcp_timeout_seconds,
|
240
246
|
input_guardrails=input_guardrails,
|
241
247
|
output_guardrails=output_guardrails,
|
248
|
+
max_turns=max_turns,
|
242
249
|
)
|
243
250
|
return await ActivityHelpers.execute_activity(
|
244
251
|
activity_name=OpenAIActivityName.RUN_AGENT_AUTO_SEND,
|
@@ -267,6 +274,7 @@ class OpenAIModule:
|
|
267
274
|
mcp_timeout_seconds=mcp_timeout_seconds,
|
268
275
|
input_guardrails=input_guardrails,
|
269
276
|
output_guardrails=output_guardrails,
|
277
|
+
max_turns=max_turns,
|
270
278
|
)
|
271
279
|
|
272
280
|
async def run_agent_streamed(
|
@@ -291,6 +299,7 @@ class OpenAIModule:
|
|
291
299
|
mcp_timeout_seconds: int | None = None,
|
292
300
|
input_guardrails: list[InputGuardrail] | None = None,
|
293
301
|
output_guardrails: list[OutputGuardrail] | None = None,
|
302
|
+
max_turns: int | None = None,
|
294
303
|
) -> RunResultStreaming:
|
295
304
|
"""
|
296
305
|
Run an agent with streaming enabled but no TaskMessage creation.
|
@@ -320,6 +329,7 @@ class OpenAIModule:
|
|
320
329
|
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
321
330
|
input_guardrails: Optional list of input guardrails to run on initial user input.
|
322
331
|
output_guardrails: Optional list of output guardrails to run on final agent output.
|
332
|
+
max_turns: Maximum number of turns the agent can take. Uses Runner's default if None.
|
323
333
|
|
324
334
|
Returns:
|
325
335
|
RunResultStreaming: The result of the agent run with streaming.
|
@@ -352,6 +362,7 @@ class OpenAIModule:
|
|
352
362
|
mcp_timeout_seconds=mcp_timeout_seconds,
|
353
363
|
input_guardrails=input_guardrails,
|
354
364
|
output_guardrails=output_guardrails,
|
365
|
+
max_turns=max_turns,
|
355
366
|
)
|
356
367
|
|
357
368
|
async def run_agent_streamed_auto_send(
|
@@ -380,6 +391,7 @@ class OpenAIModule:
|
|
380
391
|
mcp_timeout_seconds: int | None = None,
|
381
392
|
input_guardrails: list[InputGuardrail] | None = None,
|
382
393
|
output_guardrails: list[OutputGuardrail] | None = None,
|
394
|
+
max_turns: int | None = None,
|
383
395
|
) -> SerializableRunResultStreaming | RunResultStreaming:
|
384
396
|
"""
|
385
397
|
Run an agent with streaming enabled and automatic TaskMessage creation.
|
@@ -405,6 +417,7 @@ class OpenAIModule:
|
|
405
417
|
output_type: Optional output type.
|
406
418
|
tool_use_behavior: Optional tool use behavior.
|
407
419
|
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
420
|
+
max_turns: Maximum number of turns the agent can take. Uses Runner's default if None.
|
408
421
|
|
409
422
|
Returns:
|
410
423
|
Union[SerializableRunResultStreaming, RunResultStreaming]: SerializableRunResultStreaming when in Temporal, RunResultStreaming otherwise.
|
@@ -428,6 +441,7 @@ class OpenAIModule:
|
|
428
441
|
mcp_timeout_seconds=mcp_timeout_seconds,
|
429
442
|
input_guardrails=input_guardrails,
|
430
443
|
output_guardrails=output_guardrails,
|
444
|
+
max_turns=max_turns
|
431
445
|
)
|
432
446
|
return await ActivityHelpers.execute_activity(
|
433
447
|
activity_name=OpenAIActivityName.RUN_AGENT_STREAMED_AUTO_SEND,
|
@@ -456,4 +470,5 @@ class OpenAIModule:
|
|
456
470
|
mcp_timeout_seconds=mcp_timeout_seconds,
|
457
471
|
input_guardrails=input_guardrails,
|
458
472
|
output_guardrails=output_guardrails,
|
473
|
+
max_turns=max_turns,
|
459
474
|
)
|
@@ -229,9 +229,12 @@ def merge_deployment_configs(
|
|
229
229
|
all_env_vars[EnvVarKeys.AUTH_PRINCIPAL_B64.value] = encoded_principal
|
230
230
|
else:
|
231
231
|
raise DeploymentError(f"Auth principal unable to be encoded for agent_env_config: {agent_env_config}")
|
232
|
-
|
232
|
+
|
233
|
+
logger.info(f"Defined agent helm overrides: {agent_env_config.helm_overrides}")
|
234
|
+
logger.info(f"Before-merge helm values: {helm_values}")
|
233
235
|
if agent_env_config.helm_overrides:
|
234
236
|
_deep_merge(helm_values, agent_env_config.helm_overrides)
|
237
|
+
logger.info(f"After-merge helm values: {helm_values}")
|
235
238
|
|
236
239
|
# Set final environment variables
|
237
240
|
# Environment variable precedence: manifest -> environments.yaml -> secrets (highest)
|
@@ -180,9 +180,19 @@ class ACPService:
|
|
180
180
|
self,
|
181
181
|
task_id: str | None = None,
|
182
182
|
task_name: str | None = None,
|
183
|
+
agent_id: str | None = None,
|
184
|
+
agent_name: str | None = None,
|
183
185
|
trace_id: str | None = None,
|
184
186
|
parent_span_id: str | None = None,
|
185
|
-
) -> Task:
|
187
|
+
) -> Task:
|
188
|
+
# Require agent identification
|
189
|
+
if not agent_name and not agent_id:
|
190
|
+
raise ValueError("Either agent_name or agent_id must be provided to identify the agent that owns the task")
|
191
|
+
|
192
|
+
# Require task identification
|
193
|
+
if not task_name and not task_id:
|
194
|
+
raise ValueError("Either task_name or task_id must be provided to identify the task to cancel")
|
195
|
+
|
186
196
|
trace = self._tracer.trace(trace_id=trace_id)
|
187
197
|
async with trace.span(
|
188
198
|
parent_id=parent_span_id,
|
@@ -190,27 +200,32 @@ class ACPService:
|
|
190
200
|
input={
|
191
201
|
"task_id": task_id,
|
192
202
|
"task_name": task_name,
|
203
|
+
"agent_id": agent_id,
|
204
|
+
"agent_name": agent_name,
|
193
205
|
},
|
194
206
|
) as span:
|
195
207
|
heartbeat_if_in_workflow("task cancel")
|
208
|
+
|
209
|
+
# Build params for the agent (task identification)
|
210
|
+
params = {}
|
211
|
+
if task_id:
|
212
|
+
params["task_id"] = task_id
|
196
213
|
if task_name:
|
214
|
+
params["task_name"] = task_name
|
215
|
+
|
216
|
+
# Send cancel request to the correct agent
|
217
|
+
if agent_name:
|
197
218
|
json_rpc_response = await self._agentex_client.agents.rpc_by_name(
|
198
|
-
agent_name=
|
219
|
+
agent_name=agent_name,
|
199
220
|
method="task/cancel",
|
200
|
-
params=
|
201
|
-
"task_name": task_name,
|
202
|
-
},
|
221
|
+
params=params,
|
203
222
|
)
|
204
|
-
|
223
|
+
else: # agent_id is provided (validated above)
|
205
224
|
json_rpc_response = await self._agentex_client.agents.rpc(
|
206
|
-
agent_id=
|
225
|
+
agent_id=agent_id,
|
207
226
|
method="task/cancel",
|
208
|
-
params=
|
209
|
-
"task_id": task_id,
|
210
|
-
},
|
227
|
+
params=params,
|
211
228
|
)
|
212
|
-
else:
|
213
|
-
raise ValueError("Either task_name or task_id must be provided")
|
214
229
|
|
215
230
|
task_entry = Task.model_validate(json_rpc_response.result)
|
216
231
|
if span:
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# Standard library imports
|
2
|
-
import json
|
3
2
|
from contextlib import AsyncExitStack, asynccontextmanager
|
4
3
|
from typing import Any, Literal
|
5
4
|
|
@@ -11,7 +10,8 @@ from agents.mcp import MCPServerStdio
|
|
11
10
|
from mcp import StdioServerParameters
|
12
11
|
from openai.types.responses import (
|
13
12
|
ResponseCompletedEvent,
|
14
|
-
|
13
|
+
ResponseFunctionWebSearch,
|
14
|
+
ResponseCodeInterpreterToolCall,
|
15
15
|
ResponseOutputItemDoneEvent,
|
16
16
|
ResponseTextDeltaEvent,
|
17
17
|
ResponseReasoningSummaryTextDeltaEvent,
|
@@ -85,6 +85,86 @@ class OpenAIService:
|
|
85
85
|
self.streaming_service = streaming_service
|
86
86
|
self.tracer = tracer
|
87
87
|
|
88
|
+
def _extract_tool_call_info(
|
89
|
+
self, tool_call_item: Any
|
90
|
+
) -> tuple[str, str, dict[str, Any]]:
|
91
|
+
"""
|
92
|
+
Extract call_id, tool_name, and tool_arguments from a tool call item.
|
93
|
+
|
94
|
+
Args:
|
95
|
+
tool_call_item: The tool call item to process
|
96
|
+
|
97
|
+
Returns:
|
98
|
+
A tuple of (call_id, tool_name, tool_arguments)
|
99
|
+
"""
|
100
|
+
# Generic handling for different tool call types
|
101
|
+
# Try 'call_id' first, then 'id', then generate placeholder
|
102
|
+
if hasattr(tool_call_item, 'call_id'):
|
103
|
+
call_id = tool_call_item.call_id
|
104
|
+
elif hasattr(tool_call_item, 'id'):
|
105
|
+
call_id = tool_call_item.id
|
106
|
+
else:
|
107
|
+
call_id = f"unknown_call_{id(tool_call_item)}"
|
108
|
+
logger.warning(
|
109
|
+
f"Warning: Tool call item {type(tool_call_item)} has "
|
110
|
+
f"neither 'call_id' nor 'id' attribute, using placeholder: "
|
111
|
+
f"{call_id}"
|
112
|
+
)
|
113
|
+
|
114
|
+
if isinstance(tool_call_item, ResponseFunctionWebSearch):
|
115
|
+
tool_name = "web_search"
|
116
|
+
tool_arguments = {
|
117
|
+
"action": tool_call_item.action.model_dump(),
|
118
|
+
"status": tool_call_item.status
|
119
|
+
}
|
120
|
+
elif isinstance(tool_call_item, ResponseCodeInterpreterToolCall):
|
121
|
+
tool_name = "code_interpreter"
|
122
|
+
tool_arguments = {
|
123
|
+
"code": tool_call_item.code,
|
124
|
+
"status": tool_call_item.status
|
125
|
+
}
|
126
|
+
else:
|
127
|
+
# Generic handling for any tool call type
|
128
|
+
tool_name = getattr(tool_call_item, 'name', type(tool_call_item).__name__)
|
129
|
+
tool_arguments = tool_call_item.model_dump()
|
130
|
+
|
131
|
+
return call_id, tool_name, tool_arguments
|
132
|
+
|
133
|
+
def _extract_tool_response_info(
|
134
|
+
self, tool_call_map: dict[str, Any], tool_output_item: Any
|
135
|
+
) -> tuple[str, str, str]:
|
136
|
+
"""
|
137
|
+
Extract call_id, tool_name, and content from a tool output item.
|
138
|
+
|
139
|
+
Args:
|
140
|
+
tool_call_map: Map of call_ids to tool_call items
|
141
|
+
tool_output_item: The tool output item to process
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
A tuple of (call_id, tool_name, content)
|
145
|
+
"""
|
146
|
+
# Extract call_id and content from the tool_output_item
|
147
|
+
# Handle both dictionary access and attribute access
|
148
|
+
if hasattr(tool_output_item, 'get') and callable(tool_output_item.get):
|
149
|
+
# Dictionary-like access
|
150
|
+
call_id = tool_output_item["call_id"]
|
151
|
+
content = tool_output_item["output"]
|
152
|
+
else:
|
153
|
+
# Attribute access for structured objects
|
154
|
+
call_id = getattr(tool_output_item, 'call_id', None)
|
155
|
+
content = getattr(tool_output_item, 'output', None)
|
156
|
+
|
157
|
+
# Get the name from the tool call map using generic approach
|
158
|
+
tool_call = tool_call_map[call_id]
|
159
|
+
if hasattr(tool_call, "name"):
|
160
|
+
tool_name = getattr(tool_call, "name")
|
161
|
+
elif hasattr(tool_call, "type"):
|
162
|
+
tool_name = getattr(tool_call, "type")
|
163
|
+
else:
|
164
|
+
tool_name = type(tool_call).__name__
|
165
|
+
|
166
|
+
return call_id, tool_name, content
|
167
|
+
|
88
168
|
async def run_agent(
|
89
169
|
self,
|
90
170
|
input_list: list[dict[str, Any]],
|
@@ -107,6 +187,7 @@ class OpenAIService:
|
|
107
187
|
mcp_timeout_seconds: int | None = None,
|
108
188
|
input_guardrails: list[InputGuardrail] | None = None,
|
109
189
|
output_guardrails: list[OutputGuardrail] | None = None,
|
190
|
+
max_turns: int | None = None,
|
110
191
|
) -> RunResult:
|
111
192
|
"""
|
112
193
|
Run an agent without streaming or TaskMessage creation.
|
@@ -131,6 +212,8 @@ class OpenAIService:
|
|
131
212
|
initial user input.
|
132
213
|
output_guardrails: Optional list of output guardrails to run on
|
133
214
|
final agent output.
|
215
|
+
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
216
|
+
max_turns: Maximum number of turns the agent can take. Uses Runner's default if None.
|
134
217
|
Returns:
|
135
218
|
SerializableRunResult: The result of the agent run.
|
136
219
|
"""
|
@@ -152,6 +235,7 @@ class OpenAIService:
|
|
152
235
|
"tools": tools,
|
153
236
|
"output_type": output_type,
|
154
237
|
"tool_use_behavior": tool_use_behavior,
|
238
|
+
"max_turns": max_turns,
|
155
239
|
},
|
156
240
|
) as span:
|
157
241
|
heartbeat_if_in_workflow("run agent")
|
@@ -159,7 +243,9 @@ class OpenAIService:
|
|
159
243
|
async with mcp_server_context(
|
160
244
|
mcp_server_params, mcp_timeout_seconds
|
161
245
|
) as servers:
|
162
|
-
tools = [
|
246
|
+
tools = [
|
247
|
+
tool.to_oai_function_tool()for tool in tools
|
248
|
+
] if tools else []
|
163
249
|
handoffs = (
|
164
250
|
[Agent(**handoff.model_dump()) for handoff in handoffs]
|
165
251
|
if handoffs
|
@@ -189,7 +275,10 @@ class OpenAIService:
|
|
189
275
|
agent = Agent(**agent_kwargs)
|
190
276
|
|
191
277
|
# Run without streaming
|
192
|
-
|
278
|
+
if max_turns is not None:
|
279
|
+
result = await Runner.run(starting_agent=agent, input=input_list, max_turns=max_turns)
|
280
|
+
else:
|
281
|
+
result = await Runner.run(starting_agent=agent, input=input_list)
|
193
282
|
|
194
283
|
if span:
|
195
284
|
span.output = {
|
@@ -227,6 +316,7 @@ class OpenAIService:
|
|
227
316
|
mcp_timeout_seconds: int | None = None,
|
228
317
|
input_guardrails: list[InputGuardrail] | None = None,
|
229
318
|
output_guardrails: list[OutputGuardrail] | None = None,
|
319
|
+
max_turns: int | None = None,
|
230
320
|
) -> RunResult:
|
231
321
|
"""
|
232
322
|
Run an agent with automatic TaskMessage creation.
|
@@ -249,6 +339,7 @@ class OpenAIService:
|
|
249
339
|
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
250
340
|
input_guardrails: Optional list of input guardrails to run on initial user input.
|
251
341
|
output_guardrails: Optional list of output guardrails to run on final agent output.
|
342
|
+
max_turns: Maximum number of turns the agent can take. Uses Runner's default if None.
|
252
343
|
Returns:
|
253
344
|
SerializableRunResult: The result of the agent run.
|
254
345
|
"""
|
@@ -276,6 +367,7 @@ class OpenAIService:
|
|
276
367
|
"tools": tools,
|
277
368
|
"output_type": output_type,
|
278
369
|
"tool_use_behavior": tool_use_behavior,
|
370
|
+
"max_turns": max_turns,
|
279
371
|
},
|
280
372
|
) as span:
|
281
373
|
heartbeat_if_in_workflow("run agent auto send")
|
@@ -312,7 +404,10 @@ class OpenAIService:
|
|
312
404
|
agent = Agent(**agent_kwargs)
|
313
405
|
|
314
406
|
# Run without streaming
|
315
|
-
|
407
|
+
if max_turns is not None:
|
408
|
+
result = await Runner.run(starting_agent=agent, input=input_list, max_turns=max_turns)
|
409
|
+
else:
|
410
|
+
result = await Runner.run(starting_agent=agent, input=input_list)
|
316
411
|
|
317
412
|
if span:
|
318
413
|
span.output = {
|
@@ -325,7 +420,7 @@ class OpenAIService:
|
|
325
420
|
"final_output": result.final_output,
|
326
421
|
}
|
327
422
|
|
328
|
-
tool_call_map: dict[str,
|
423
|
+
tool_call_map: dict[str, Any] = {}
|
329
424
|
|
330
425
|
for item in result.new_items:
|
331
426
|
if item.type == "message_output_item":
|
@@ -349,13 +444,17 @@ class OpenAIService:
|
|
349
444
|
)
|
350
445
|
|
351
446
|
elif item.type == "tool_call_item":
|
352
|
-
|
447
|
+
tool_call_item = item.raw_item
|
448
|
+
|
449
|
+
# Extract tool call information using the helper method
|
450
|
+
call_id, tool_name, tool_arguments = self._extract_tool_call_info(tool_call_item)
|
451
|
+
tool_call_map[call_id] = tool_call_item
|
353
452
|
|
354
453
|
tool_request_content = ToolRequestContent(
|
355
454
|
author="agent",
|
356
|
-
tool_call_id=
|
357
|
-
name=
|
358
|
-
arguments=
|
455
|
+
tool_call_id=call_id,
|
456
|
+
name=tool_name,
|
457
|
+
arguments=tool_arguments,
|
359
458
|
)
|
360
459
|
|
361
460
|
# Create tool request using streaming context
|
@@ -376,11 +475,16 @@ class OpenAIService:
|
|
376
475
|
elif item.type == "tool_call_output_item":
|
377
476
|
tool_output_item = item.raw_item
|
378
477
|
|
478
|
+
# Extract tool response information using the helper method
|
479
|
+
call_id, tool_name, content = self._extract_tool_response_info(
|
480
|
+
tool_call_map, tool_output_item
|
481
|
+
)
|
482
|
+
|
379
483
|
tool_response_content = ToolResponseContent(
|
380
484
|
author="agent",
|
381
|
-
tool_call_id=
|
382
|
-
name=
|
383
|
-
content=
|
485
|
+
tool_call_id=call_id,
|
486
|
+
name=tool_name,
|
487
|
+
content=content,
|
384
488
|
)
|
385
489
|
# Create tool response using streaming context
|
386
490
|
async with (
|
@@ -422,6 +526,7 @@ class OpenAIService:
|
|
422
526
|
mcp_timeout_seconds: int | None = None,
|
423
527
|
input_guardrails: list[InputGuardrail] | None = None,
|
424
528
|
output_guardrails: list[OutputGuardrail] | None = None,
|
529
|
+
max_turns: int | None = None,
|
425
530
|
) -> RunResultStreaming:
|
426
531
|
"""
|
427
532
|
Run an agent with streaming enabled but no TaskMessage creation.
|
@@ -446,6 +551,8 @@ class OpenAIService:
|
|
446
551
|
initial user input.
|
447
552
|
output_guardrails: Optional list of output guardrails to run on
|
448
553
|
final agent output.
|
554
|
+
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
555
|
+
max_turns: Maximum number of turns the agent can take. Uses Runner's default if None.
|
449
556
|
Returns:
|
450
557
|
RunResultStreaming: The result of the agent run with streaming.
|
451
558
|
"""
|
@@ -467,6 +574,7 @@ class OpenAIService:
|
|
467
574
|
"tools": tools,
|
468
575
|
"output_type": output_type,
|
469
576
|
"tool_use_behavior": tool_use_behavior,
|
577
|
+
"max_turns": max_turns,
|
470
578
|
},
|
471
579
|
) as span:
|
472
580
|
heartbeat_if_in_workflow("run agent streamed")
|
@@ -503,7 +611,10 @@ class OpenAIService:
|
|
503
611
|
agent = Agent(**agent_kwargs)
|
504
612
|
|
505
613
|
# Run with streaming (but no TaskMessage creation)
|
506
|
-
|
614
|
+
if max_turns is not None:
|
615
|
+
result = Runner.run_streamed(starting_agent=agent, input=input_list, max_turns=max_turns)
|
616
|
+
else:
|
617
|
+
result = Runner.run_streamed(starting_agent=agent, input=input_list)
|
507
618
|
|
508
619
|
if span:
|
509
620
|
span.output = {
|
@@ -541,6 +652,7 @@ class OpenAIService:
|
|
541
652
|
mcp_timeout_seconds: int | None = None,
|
542
653
|
input_guardrails: list[InputGuardrail] | None = None,
|
543
654
|
output_guardrails: list[OutputGuardrail] | None = None,
|
655
|
+
max_turns: int | None = None,
|
544
656
|
) -> RunResultStreaming:
|
545
657
|
"""
|
546
658
|
Run an agent with streaming enabled and automatic TaskMessage creation.
|
@@ -566,6 +678,8 @@ class OpenAIService:
|
|
566
678
|
initial user input.
|
567
679
|
output_guardrails: Optional list of output guardrails to run on
|
568
680
|
final agent output.
|
681
|
+
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
682
|
+
max_turns: Maximum number of turns the agent can take. Uses Runner's default if None.
|
569
683
|
|
570
684
|
Returns:
|
571
685
|
RunResultStreaming: The result of the agent run with streaming.
|
@@ -575,7 +689,7 @@ class OpenAIService:
|
|
575
689
|
if self.agentex_client is None:
|
576
690
|
raise ValueError("Agentex client must be provided for auto_send methods")
|
577
691
|
|
578
|
-
tool_call_map: dict[str,
|
692
|
+
tool_call_map: dict[str, Any] = {}
|
579
693
|
|
580
694
|
trace = self.tracer.trace(trace_id)
|
581
695
|
redacted_params = redact_mcp_server_params(mcp_server_params)
|
@@ -596,6 +710,7 @@ class OpenAIService:
|
|
596
710
|
"tools": tools,
|
597
711
|
"output_type": output_type,
|
598
712
|
"tool_use_behavior": tool_use_behavior,
|
713
|
+
"max_turns": max_turns,
|
599
714
|
},
|
600
715
|
) as span:
|
601
716
|
heartbeat_if_in_workflow("run agent streamed auto send")
|
@@ -632,7 +747,10 @@ class OpenAIService:
|
|
632
747
|
agent = Agent(**agent_kwargs)
|
633
748
|
|
634
749
|
# Run with streaming
|
635
|
-
|
750
|
+
if max_turns is not None:
|
751
|
+
result = Runner.run_streamed(starting_agent=agent, input=input_list, max_turns=max_turns)
|
752
|
+
else:
|
753
|
+
result = Runner.run_streamed(starting_agent=agent, input=input_list)
|
636
754
|
|
637
755
|
item_id_to_streaming_context: dict[
|
638
756
|
str, StreamingTaskMessageContext
|
@@ -649,13 +767,16 @@ class OpenAIService:
|
|
649
767
|
if event.type == "run_item_stream_event":
|
650
768
|
if event.item.type == "tool_call_item":
|
651
769
|
tool_call_item = event.item.raw_item
|
652
|
-
|
770
|
+
|
771
|
+
# Extract tool call information using the helper method
|
772
|
+
call_id, tool_name, tool_arguments = self._extract_tool_call_info(tool_call_item)
|
773
|
+
tool_call_map[call_id] = tool_call_item
|
653
774
|
|
654
775
|
tool_request_content = ToolRequestContent(
|
655
776
|
author="agent",
|
656
|
-
tool_call_id=
|
657
|
-
name=
|
658
|
-
arguments=
|
777
|
+
tool_call_id=call_id,
|
778
|
+
name=tool_name,
|
779
|
+
arguments=tool_arguments,
|
659
780
|
)
|
660
781
|
|
661
782
|
# Create tool request using streaming context (immediate completion)
|
@@ -677,13 +798,16 @@ class OpenAIService:
|
|
677
798
|
elif event.item.type == "tool_call_output_item":
|
678
799
|
tool_output_item = event.item.raw_item
|
679
800
|
|
801
|
+
# Extract tool response information using the helper method
|
802
|
+
call_id, tool_name, content = self._extract_tool_response_info(
|
803
|
+
tool_call_map, tool_output_item
|
804
|
+
)
|
805
|
+
|
680
806
|
tool_response_content = ToolResponseContent(
|
681
807
|
author="agent",
|
682
|
-
tool_call_id=
|
683
|
-
name=
|
684
|
-
|
685
|
-
].name,
|
686
|
-
content=tool_output_item["output"],
|
808
|
+
tool_call_id=call_id,
|
809
|
+
name=tool_name,
|
810
|
+
content=content,
|
687
811
|
)
|
688
812
|
|
689
813
|
# Create tool response using streaming context (immediate completion)
|
@@ -45,6 +45,8 @@ class EventSendParams(BaseModelWithTraceParams):
|
|
45
45
|
class TaskCancelParams(BaseModelWithTraceParams):
|
46
46
|
task_id: str | None = None
|
47
47
|
task_name: str | None = None
|
48
|
+
agent_id: str | None = None
|
49
|
+
agent_name: str | None = None
|
48
50
|
|
49
51
|
|
50
52
|
class ACPActivities:
|
@@ -83,4 +85,8 @@ class ACPActivities:
|
|
83
85
|
return await self._acp_service.task_cancel(
|
84
86
|
task_id=params.task_id,
|
85
87
|
task_name=params.task_name,
|
88
|
+
agent_id=params.agent_id,
|
89
|
+
agent_name=params.agent_name,
|
90
|
+
trace_id=params.trace_id,
|
91
|
+
parent_span_id=params.parent_span_id,
|
86
92
|
)
|