Merge branch 'main' into lorenze/imp/docs-improvements

This commit is contained in:
Greyson LaLonde
2026-02-20 02:11:13 -05:00
committed by GitHub
20 changed files with 4062 additions and 926 deletions

View File

@@ -7,6 +7,7 @@ and memory management.
from __future__ import annotations
from collections.abc import Callable
from concurrent.futures import ThreadPoolExecutor, as_completed
import logging
from typing import TYPE_CHECKING, Any, Literal, cast
@@ -685,30 +686,138 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
Returns:
AgentFinish if tool has result_as_answer=True, None otherwise.
"""
from datetime import datetime
import json
from crewai.events import crewai_event_bus
from crewai.events.types.tool_usage_events import (
ToolUsageErrorEvent,
ToolUsageFinishedEvent,
ToolUsageStartedEvent,
)
if not tool_calls:
return None
# Only process the FIRST tool call for sequential execution with reflection
tool_call = tool_calls[0]
parsed_calls = [
parsed
for tool_call in tool_calls
if (parsed := self._parse_native_tool_call(tool_call)) is not None
]
if not parsed_calls:
return None
# Extract tool call info - handle OpenAI-style, Anthropic-style, and Gemini-style
original_tools_by_name: dict[str, Any] = {}
for tool in self.original_tools or []:
original_tools_by_name[sanitize_tool_name(tool.name)] = tool
if len(parsed_calls) > 1:
has_result_as_answer_in_batch = any(
bool(
original_tools_by_name.get(func_name)
and getattr(
original_tools_by_name.get(func_name), "result_as_answer", False
)
)
for _, func_name, _ in parsed_calls
)
has_max_usage_count_in_batch = any(
bool(
original_tools_by_name.get(func_name)
and getattr(
original_tools_by_name.get(func_name),
"max_usage_count",
None,
)
is not None
)
for _, func_name, _ in parsed_calls
)
# Preserve historical sequential behavior for result_as_answer batches.
# Also avoid threading around usage counters for max_usage_count tools.
if has_result_as_answer_in_batch or has_max_usage_count_in_batch:
logger.debug(
"Skipping parallel native execution because batch includes result_as_answer or max_usage_count tool"
)
else:
execution_plan: list[
tuple[str, str, str | dict[str, Any], Any | None]
] = []
for call_id, func_name, func_args in parsed_calls:
original_tool = original_tools_by_name.get(func_name)
execution_plan.append((call_id, func_name, func_args, original_tool))
self._append_assistant_tool_calls_message(
[
(call_id, func_name, func_args)
for call_id, func_name, func_args, _ in execution_plan
]
)
max_workers = min(8, len(execution_plan))
ordered_results: list[dict[str, Any] | None] = [None] * len(execution_plan)
with ThreadPoolExecutor(max_workers=max_workers) as pool:
futures = {
pool.submit(
self._execute_single_native_tool_call,
call_id=call_id,
func_name=func_name,
func_args=func_args,
available_functions=available_functions,
original_tool=original_tool,
should_execute=True,
): idx
for idx, (
call_id,
func_name,
func_args,
original_tool,
) in enumerate(execution_plan)
}
for future in as_completed(futures):
idx = futures[future]
ordered_results[idx] = future.result()
for execution_result in ordered_results:
if not execution_result:
continue
tool_finish = self._append_tool_result_and_check_finality(
execution_result
)
if tool_finish:
return tool_finish
reasoning_prompt = self._i18n.slice("post_tool_reasoning")
reasoning_message: LLMMessage = {
"role": "user",
"content": reasoning_prompt,
}
self.messages.append(reasoning_message)
return None
# Sequential behavior: process only first tool call, then force reflection.
call_id, func_name, func_args = parsed_calls[0]
self._append_assistant_tool_calls_message([(call_id, func_name, func_args)])
execution_result = self._execute_single_native_tool_call(
call_id=call_id,
func_name=func_name,
func_args=func_args,
available_functions=available_functions,
original_tool=original_tools_by_name.get(func_name),
should_execute=True,
)
tool_finish = self._append_tool_result_and_check_finality(execution_result)
if tool_finish:
return tool_finish
reasoning_prompt = self._i18n.slice("post_tool_reasoning")
reasoning_message: LLMMessage = {
"role": "user",
"content": reasoning_prompt,
}
self.messages.append(reasoning_message)
return None
def _parse_native_tool_call(
self, tool_call: Any
) -> tuple[str, str, str | dict[str, Any]] | None:
if hasattr(tool_call, "function"):
# OpenAI-style: has .function.name and .function.arguments
call_id = getattr(tool_call, "id", f"call_{id(tool_call)}")
func_name = sanitize_tool_name(tool_call.function.name)
func_args = tool_call.function.arguments
elif hasattr(tool_call, "function_call") and tool_call.function_call:
# Gemini-style: has .function_call.name and .function_call.args
return call_id, func_name, tool_call.function.arguments
if hasattr(tool_call, "function_call") and tool_call.function_call:
call_id = f"call_{id(tool_call)}"
func_name = sanitize_tool_name(tool_call.function_call.name)
func_args = (
@@ -716,13 +825,12 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
if tool_call.function_call.args
else {}
)
elif hasattr(tool_call, "name") and hasattr(tool_call, "input"):
# Anthropic format: has .name and .input (ToolUseBlock)
return call_id, func_name, func_args
if hasattr(tool_call, "name") and hasattr(tool_call, "input"):
call_id = getattr(tool_call, "id", f"call_{id(tool_call)}")
func_name = sanitize_tool_name(tool_call.name)
func_args = tool_call.input # Already a dict in Anthropic
elif isinstance(tool_call, dict):
# Support OpenAI "id", Bedrock "toolUseId", or generate one
return call_id, func_name, tool_call.input
if isinstance(tool_call, dict):
call_id = (
tool_call.get("id")
or tool_call.get("toolUseId")
@@ -733,10 +841,15 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
func_info.get("name", "") or tool_call.get("name", "")
)
func_args = func_info.get("arguments", "{}") or tool_call.get("input", {})
else:
return None
return call_id, func_name, func_args
return None
def _append_assistant_tool_calls_message(
self,
parsed_calls: list[tuple[str, str, str | dict[str, Any]]],
) -> None:
import json
# Append assistant message with single tool call
assistant_message: LLMMessage = {
"role": "assistant",
"content": None,
@@ -751,12 +864,30 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
else json.dumps(func_args),
},
}
for call_id, func_name, func_args in parsed_calls
],
}
self.messages.append(assistant_message)
# Parse arguments for the single tool call
def _execute_single_native_tool_call(
self,
*,
call_id: str,
func_name: str,
func_args: str | dict[str, Any],
available_functions: dict[str, Callable[..., Any]],
original_tool: Any | None = None,
should_execute: bool = True,
) -> dict[str, Any]:
from datetime import datetime
import json
from crewai.events.types.tool_usage_events import (
ToolUsageErrorEvent,
ToolUsageFinishedEvent,
ToolUsageStartedEvent,
)
if isinstance(func_args, str):
try:
args_dict = json.loads(func_args)
@@ -765,28 +896,26 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
else:
args_dict = func_args
agent_key = getattr(self.agent, "key", "unknown") if self.agent else "unknown"
if original_tool is None:
for tool in self.original_tools or []:
if sanitize_tool_name(tool.name) == func_name:
original_tool = tool
break
# Find original tool by matching sanitized name (needed for cache_function and result_as_answer)
original_tool = None
for tool in self.original_tools or []:
if sanitize_tool_name(tool.name) == func_name:
original_tool = tool
break
# Check if tool has reached max usage count
max_usage_reached = False
if original_tool:
if (
hasattr(original_tool, "max_usage_count")
and original_tool.max_usage_count is not None
and original_tool.current_usage_count >= original_tool.max_usage_count
):
max_usage_reached = True
if not should_execute and original_tool:
max_usage_reached = True
elif (
should_execute
and original_tool
and getattr(original_tool, "max_usage_count", None) is not None
and getattr(original_tool, "current_usage_count", 0)
>= original_tool.max_usage_count
):
max_usage_reached = True
# Check cache before executing
from_cache = False
result: str = "Tool not found"
input_str = json.dumps(args_dict) if args_dict else ""
if self.tools_handler and self.tools_handler.cache:
cached_result = self.tools_handler.cache.read(
@@ -800,7 +929,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
)
from_cache = True
# Emit tool usage started event
agent_key = getattr(self.agent, "key", "unknown") if self.agent else "unknown"
started_at = datetime.now()
crewai_event_bus.emit(
self,
@@ -816,14 +945,12 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
track_delegation_if_needed(func_name, args_dict, self.task)
# Find the structured tool for hook context
structured_tool: CrewStructuredTool | None = None
for structured in self.tools or []:
if sanitize_tool_name(structured.name) == func_name:
structured_tool = structured
break
# Execute before_tool_call hooks
hook_blocked = False
before_hook_context = ToolCallHookContext(
tool_name=func_name,
@@ -847,58 +974,44 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
color="red",
)
# If hook blocked execution, set result and skip tool execution
if hook_blocked:
result = f"Tool execution blocked by hook. Tool: {func_name}"
# Execute the tool (only if not cached, not at max usage, and not blocked by hook)
elif not from_cache and not max_usage_reached:
result = "Tool not found"
if func_name in available_functions:
try:
tool_func = available_functions[func_name]
raw_result = tool_func(**args_dict)
# Add to cache after successful execution (before string conversion)
if self.tools_handler and self.tools_handler.cache:
should_cache = True
if (
original_tool
and hasattr(original_tool, "cache_function")
and callable(original_tool.cache_function)
):
should_cache = original_tool.cache_function(
args_dict, raw_result
)
if should_cache:
self.tools_handler.cache.add(
tool=func_name, input=input_str, output=raw_result
)
# Convert to string for message
result = (
str(raw_result)
if not isinstance(raw_result, str)
else raw_result
)
except Exception as e:
result = f"Error executing tool: {e}"
if self.task:
self.task.increment_tools_errors()
crewai_event_bus.emit(
self,
event=ToolUsageErrorEvent(
tool_name=func_name,
tool_args=args_dict,
from_agent=self.agent,
from_task=self.task,
agent_key=agent_key,
error=e,
),
)
error_event_emitted = True
elif max_usage_reached and original_tool:
# Return error message when max usage limit is reached
result = f"Tool '{func_name}' has reached its usage limit of {original_tool.max_usage_count} times and cannot be used anymore."
elif not from_cache and func_name in available_functions:
try:
raw_result = available_functions[func_name](**args_dict)
if self.tools_handler and self.tools_handler.cache:
should_cache = True
if (
original_tool
and hasattr(original_tool, "cache_function")
and callable(original_tool.cache_function)
):
should_cache = original_tool.cache_function(args_dict, raw_result)
if should_cache:
self.tools_handler.cache.add(
tool=func_name, input=input_str, output=raw_result
)
result = str(raw_result) if not isinstance(raw_result, str) else raw_result
except Exception as e:
result = f"Error executing tool: {e}"
if self.task:
self.task.increment_tools_errors()
crewai_event_bus.emit(
self,
event=ToolUsageErrorEvent(
tool_name=func_name,
tool_args=args_dict,
from_agent=self.agent,
from_task=self.task,
agent_key=agent_key,
error=e,
),
)
error_event_emitted = True
after_hook_context = ToolCallHookContext(
tool_name=func_name,
@@ -938,7 +1051,23 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
),
)
# Append tool result message
return {
"call_id": call_id,
"func_name": func_name,
"result": result,
"from_cache": from_cache,
"original_tool": original_tool,
}
def _append_tool_result_and_check_finality(
self, execution_result: dict[str, Any]
) -> AgentFinish | None:
call_id = cast(str, execution_result["call_id"])
func_name = cast(str, execution_result["func_name"])
result = cast(str, execution_result["result"])
from_cache = cast(bool, execution_result["from_cache"])
original_tool = execution_result["original_tool"]
tool_message: LLMMessage = {
"role": "tool",
"tool_call_id": call_id,
@@ -947,7 +1076,6 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
}
self.messages.append(tool_message)
# Log the tool execution
if self.agent and self.agent.verbose:
cache_info = " (from cache)" if from_cache else ""
self._printer.print(
@@ -960,20 +1088,11 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
and hasattr(original_tool, "result_as_answer")
and original_tool.result_as_answer
):
# Return immediately with tool result as final answer
return AgentFinish(
thought="Tool result is the final answer",
output=result,
text=result,
)
# Inject post-tool reasoning prompt to enforce analysis
reasoning_prompt = self._i18n.slice("post_tool_reasoning")
reasoning_message: LLMMessage = {
"role": "user",
"content": reasoning_prompt,
}
self.messages.append(reasoning_message)
return None
async def ainvoke(self, inputs: dict[str, Any]) -> dict[str, Any]:

View File

@@ -1,6 +1,7 @@
from __future__ import annotations
from collections.abc import Callable, Coroutine
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime
import json
import threading
@@ -668,9 +669,12 @@ class AgentExecutor(Flow[AgentReActState], CrewAgentExecutorMixin):
if not self.state.pending_tool_calls:
return "native_tool_completed"
pending_tool_calls = list(self.state.pending_tool_calls)
self.state.pending_tool_calls.clear()
# Group all tool calls into a single assistant message
tool_calls_to_report = []
for tool_call in self.state.pending_tool_calls:
for tool_call in pending_tool_calls:
info = extract_tool_call_info(tool_call)
if not info:
continue
@@ -695,201 +699,85 @@ class AgentExecutor(Flow[AgentReActState], CrewAgentExecutorMixin):
"content": None,
"tool_calls": tool_calls_to_report,
}
if all(
type(tc).__qualname__ == "Part" for tc in self.state.pending_tool_calls
):
assistant_message["raw_tool_call_parts"] = list(
self.state.pending_tool_calls
)
if all(type(tc).__qualname__ == "Part" for tc in pending_tool_calls):
assistant_message["raw_tool_call_parts"] = list(pending_tool_calls)
self.state.messages.append(assistant_message)
# Now execute each tool
while self.state.pending_tool_calls:
tool_call = self.state.pending_tool_calls.pop(0)
info = extract_tool_call_info(tool_call)
if not info:
continue
runnable_tool_calls = [
tool_call
for tool_call in pending_tool_calls
if extract_tool_call_info(tool_call) is not None
]
should_parallelize = self._should_parallelize_native_tool_calls(
runnable_tool_calls
)
call_id, func_name, func_args = info
# Parse arguments
if isinstance(func_args, str):
try:
args_dict = json.loads(func_args)
except json.JSONDecodeError:
args_dict = {}
else:
args_dict = func_args
# Get agent_key for event tracking
agent_key = (
getattr(self.agent, "key", "unknown") if self.agent else "unknown"
)
# Find original tool by matching sanitized name (needed for cache_function and result_as_answer)
original_tool = None
for tool in self.original_tools or []:
if sanitize_tool_name(tool.name) == func_name:
original_tool = tool
break
# Check if tool has reached max usage count
max_usage_reached = False
if (
original_tool
and original_tool.max_usage_count is not None
and original_tool.current_usage_count >= original_tool.max_usage_count
):
max_usage_reached = True
# Check cache before executing
from_cache = False
input_str = json.dumps(args_dict) if args_dict else ""
if self.tools_handler and self.tools_handler.cache:
cached_result = self.tools_handler.cache.read(
tool=func_name, input=input_str
execution_results: list[dict[str, Any]] = []
if should_parallelize:
max_workers = min(8, len(runnable_tool_calls))
with ThreadPoolExecutor(max_workers=max_workers) as pool:
future_to_idx = {
pool.submit(self._execute_single_native_tool_call, tool_call): idx
for idx, tool_call in enumerate(runnable_tool_calls)
}
ordered_results: list[dict[str, Any] | None] = [None] * len(
runnable_tool_calls
)
if cached_result is not None:
result = (
str(cached_result)
if not isinstance(cached_result, str)
else cached_result
)
from_cache = True
for future in as_completed(future_to_idx):
idx = future_to_idx[future]
ordered_results[idx] = future.result()
execution_results = [
result for result in ordered_results if result is not None
]
else:
# Execute sequentially so result_as_answer tools can short-circuit
# immediately without running remaining calls.
for tool_call in runnable_tool_calls:
execution_result = self._execute_single_native_tool_call(tool_call)
call_id = cast(str, execution_result["call_id"])
func_name = cast(str, execution_result["func_name"])
result = cast(str, execution_result["result"])
from_cache = cast(bool, execution_result["from_cache"])
original_tool = execution_result["original_tool"]
# Emit tool usage started event
started_at = datetime.now()
crewai_event_bus.emit(
self,
event=ToolUsageStartedEvent(
tool_name=func_name,
tool_args=args_dict,
from_agent=self.agent,
from_task=self.task,
agent_key=agent_key,
),
)
error_event_emitted = False
tool_message: LLMMessage = {
"role": "tool",
"tool_call_id": call_id,
"name": func_name,
"content": result,
}
self.state.messages.append(tool_message)
track_delegation_if_needed(func_name, args_dict, self.task)
structured_tool: CrewStructuredTool | None = None
for structured in self.tools or []:
if sanitize_tool_name(structured.name) == func_name:
structured_tool = structured
break
hook_blocked = False
before_hook_context = ToolCallHookContext(
tool_name=func_name,
tool_input=args_dict,
tool=structured_tool, # type: ignore[arg-type]
agent=self.agent,
task=self.task,
crew=self.crew,
)
before_hooks = get_before_tool_call_hooks()
try:
for hook in before_hooks:
hook_result = hook(before_hook_context)
if hook_result is False:
hook_blocked = True
break
except Exception as hook_error:
if self.agent.verbose:
# Log the tool execution
if self.agent and self.agent.verbose:
cache_info = " (from cache)" if from_cache else ""
self._printer.print(
content=f"Error in before_tool_call hook: {hook_error}",
color="red",
content=f"Tool {func_name} executed with result{cache_info}: {result[:200]}...",
color="green",
)
if hook_blocked:
result = f"Tool execution blocked by hook. Tool: {func_name}"
elif not from_cache and not max_usage_reached:
result = "Tool not found"
if func_name in self._available_functions:
try:
tool_func = self._available_functions[func_name]
raw_result = tool_func(**args_dict)
# Add to cache after successful execution (before string conversion)
if self.tools_handler and self.tools_handler.cache:
should_cache = True
if original_tool:
should_cache = original_tool.cache_function(
args_dict, raw_result
)
if should_cache:
self.tools_handler.cache.add(
tool=func_name, input=input_str, output=raw_result
)
# Convert to string for message
result = (
str(raw_result)
if not isinstance(raw_result, str)
else raw_result
)
except Exception as e:
result = f"Error executing tool: {e}"
if self.task:
self.task.increment_tools_errors()
# Emit tool usage error event
crewai_event_bus.emit(
self,
event=ToolUsageErrorEvent(
tool_name=func_name,
tool_args=args_dict,
from_agent=self.agent,
from_task=self.task,
agent_key=agent_key,
error=e,
),
)
error_event_emitted = True
elif max_usage_reached and original_tool:
# Return error message when max usage limit is reached
result = f"Tool '{func_name}' has reached its usage limit of {original_tool.max_usage_count} times and cannot be used anymore."
# Execute after_tool_call hooks (even if blocked, to allow logging/monitoring)
after_hook_context = ToolCallHookContext(
tool_name=func_name,
tool_input=args_dict,
tool=structured_tool, # type: ignore[arg-type]
agent=self.agent,
task=self.task,
crew=self.crew,
tool_result=result,
)
after_hooks = get_after_tool_call_hooks()
try:
for after_hook in after_hooks:
after_hook_result = after_hook(after_hook_context)
if after_hook_result is not None:
result = after_hook_result
after_hook_context.tool_result = result
except Exception as hook_error:
if self.agent.verbose:
self._printer.print(
content=f"Error in after_tool_call hook: {hook_error}",
color="red",
)
if not error_event_emitted:
crewai_event_bus.emit(
self,
event=ToolUsageFinishedEvent(
if (
original_tool
and hasattr(original_tool, "result_as_answer")
and original_tool.result_as_answer
):
self.state.current_answer = AgentFinish(
thought="Tool result is the final answer",
output=result,
tool_name=func_name,
tool_args=args_dict,
from_agent=self.agent,
from_task=self.task,
agent_key=agent_key,
started_at=started_at,
finished_at=datetime.now(),
),
)
text=result,
)
self.state.is_finished = True
return "tool_result_is_final"
return "native_tool_completed"
for execution_result in execution_results:
call_id = cast(str, execution_result["call_id"])
func_name = cast(str, execution_result["func_name"])
result = cast(str, execution_result["result"])
from_cache = cast(bool, execution_result["from_cache"])
original_tool = execution_result["original_tool"]
# Append tool result message
tool_message: LLMMessage = {
"role": "tool",
"tool_call_id": call_id,
@@ -922,6 +810,224 @@ class AgentExecutor(Flow[AgentReActState], CrewAgentExecutorMixin):
return "native_tool_completed"
def _should_parallelize_native_tool_calls(self, tool_calls: list[Any]) -> bool:
"""Determine if native tool calls are safe to run in parallel."""
if len(tool_calls) <= 1:
return False
for tool_call in tool_calls:
info = extract_tool_call_info(tool_call)
if not info:
continue
_, func_name, _ = info
original_tool = None
for tool in self.original_tools or []:
if sanitize_tool_name(tool.name) == func_name:
original_tool = tool
break
if not original_tool:
continue
if getattr(original_tool, "result_as_answer", False):
return False
if getattr(original_tool, "max_usage_count", None) is not None:
return False
return True
def _execute_single_native_tool_call(self, tool_call: Any) -> dict[str, Any]:
"""Execute a single native tool call and return metadata/result."""
info = extract_tool_call_info(tool_call)
if not info:
raise ValueError("Invalid native tool call format")
call_id, func_name, func_args = info
# Parse arguments
if isinstance(func_args, str):
try:
args_dict = json.loads(func_args)
except json.JSONDecodeError:
args_dict = {}
else:
args_dict = func_args
# Get agent_key for event tracking
agent_key = getattr(self.agent, "key", "unknown") if self.agent else "unknown"
# Find original tool by matching sanitized name (needed for cache_function and result_as_answer)
original_tool = None
for tool in self.original_tools or []:
if sanitize_tool_name(tool.name) == func_name:
original_tool = tool
break
# Check if tool has reached max usage count
max_usage_reached = False
if (
original_tool
and original_tool.max_usage_count is not None
and original_tool.current_usage_count >= original_tool.max_usage_count
):
max_usage_reached = True
# Check cache before executing
from_cache = False
input_str = json.dumps(args_dict) if args_dict else ""
if self.tools_handler and self.tools_handler.cache:
cached_result = self.tools_handler.cache.read(
tool=func_name, input=input_str
)
if cached_result is not None:
result = (
str(cached_result)
if not isinstance(cached_result, str)
else cached_result
)
from_cache = True
# Emit tool usage started event
started_at = datetime.now()
crewai_event_bus.emit(
self,
event=ToolUsageStartedEvent(
tool_name=func_name,
tool_args=args_dict,
from_agent=self.agent,
from_task=self.task,
agent_key=agent_key,
),
)
error_event_emitted = False
track_delegation_if_needed(func_name, args_dict, self.task)
structured_tool: CrewStructuredTool | None = None
for structured in self.tools or []:
if sanitize_tool_name(structured.name) == func_name:
structured_tool = structured
break
hook_blocked = False
before_hook_context = ToolCallHookContext(
tool_name=func_name,
tool_input=args_dict,
tool=structured_tool, # type: ignore[arg-type]
agent=self.agent,
task=self.task,
crew=self.crew,
)
before_hooks = get_before_tool_call_hooks()
try:
for hook in before_hooks:
hook_result = hook(before_hook_context)
if hook_result is False:
hook_blocked = True
break
except Exception as hook_error:
if self.agent.verbose:
self._printer.print(
content=f"Error in before_tool_call hook: {hook_error}",
color="red",
)
if hook_blocked:
result = f"Tool execution blocked by hook. Tool: {func_name}"
elif not from_cache and not max_usage_reached:
result = "Tool not found"
if func_name in self._available_functions:
try:
tool_func = self._available_functions[func_name]
raw_result = tool_func(**args_dict)
# Add to cache after successful execution (before string conversion)
if self.tools_handler and self.tools_handler.cache:
should_cache = True
if original_tool:
should_cache = original_tool.cache_function(
args_dict, raw_result
)
if should_cache:
self.tools_handler.cache.add(
tool=func_name, input=input_str, output=raw_result
)
# Convert to string for message
result = (
str(raw_result)
if not isinstance(raw_result, str)
else raw_result
)
except Exception as e:
result = f"Error executing tool: {e}"
if self.task:
self.task.increment_tools_errors()
# Emit tool usage error event
crewai_event_bus.emit(
self,
event=ToolUsageErrorEvent(
tool_name=func_name,
tool_args=args_dict,
from_agent=self.agent,
from_task=self.task,
agent_key=agent_key,
error=e,
),
)
error_event_emitted = True
elif max_usage_reached and original_tool:
# Return error message when max usage limit is reached
result = f"Tool '{func_name}' has reached its usage limit of {original_tool.max_usage_count} times and cannot be used anymore."
# Execute after_tool_call hooks (even if blocked, to allow logging/monitoring)
after_hook_context = ToolCallHookContext(
tool_name=func_name,
tool_input=args_dict,
tool=structured_tool, # type: ignore[arg-type]
agent=self.agent,
task=self.task,
crew=self.crew,
tool_result=result,
)
after_hooks = get_after_tool_call_hooks()
try:
for after_hook in after_hooks:
after_hook_result = after_hook(after_hook_context)
if after_hook_result is not None:
result = after_hook_result
after_hook_context.tool_result = result
except Exception as hook_error:
if self.agent.verbose:
self._printer.print(
content=f"Error in after_tool_call hook: {hook_error}",
color="red",
)
if not error_event_emitted:
crewai_event_bus.emit(
self,
event=ToolUsageFinishedEvent(
output=result,
tool_name=func_name,
tool_args=args_dict,
from_agent=self.agent,
from_task=self.task,
agent_key=agent_key,
started_at=started_at,
finished_at=datetime.now(),
),
)
return {
"call_id": call_id,
"func_name": func_name,
"result": result,
"from_cache": from_cache,
"original_tool": original_tool,
}
def _extract_tool_name(self, tool_call: Any) -> str:
"""Extract tool name from various tool call formats."""
if hasattr(tool_call, "function"):

View File

@@ -10,6 +10,7 @@ import asyncio
from collections.abc import (
Callable,
ItemsView,
Iterable,
Iterator,
KeysView,
Sequence,
@@ -17,6 +18,7 @@ from collections.abc import (
)
from concurrent.futures import Future
import copy
import enum
import inspect
import logging
import threading
@@ -27,8 +29,10 @@ from typing import (
Generic,
Literal,
ParamSpec,
SupportsIndex,
TypeVar,
cast,
overload,
)
from uuid import uuid4
@@ -77,7 +81,12 @@ from crewai.flow.flow_wrappers import (
StartMethod,
)
from crewai.flow.persistence.base import FlowPersistence
from crewai.flow.types import FlowExecutionData, FlowMethodName, InputHistoryEntry, PendingListenerKey
from crewai.flow.types import (
FlowExecutionData,
FlowMethodName,
InputHistoryEntry,
PendingListenerKey,
)
from crewai.flow.utils import (
_extract_all_methods,
_extract_all_methods_recursive,
@@ -426,8 +435,7 @@ class LockedListProxy(list, Generic[T]): # type: ignore[type-arg]
"""
def __init__(self, lst: list[T], lock: threading.Lock) -> None:
# Do NOT call super().__init__() -- we don't want to copy data into
# the builtin list storage. All access goes through self._list.
super().__init__() # empty builtin list; all access goes through self._list
self._list = lst
self._lock = lock
@@ -435,11 +443,11 @@ class LockedListProxy(list, Generic[T]): # type: ignore[type-arg]
with self._lock:
self._list.append(item)
def extend(self, items: list[T]) -> None:
def extend(self, items: Iterable[T]) -> None:
with self._lock:
self._list.extend(items)
def insert(self, index: int, item: T) -> None:
def insert(self, index: SupportsIndex, item: T) -> None:
with self._lock:
self._list.insert(index, item)
@@ -447,7 +455,7 @@ class LockedListProxy(list, Generic[T]): # type: ignore[type-arg]
with self._lock:
self._list.remove(item)
def pop(self, index: int = -1) -> T:
def pop(self, index: SupportsIndex = -1) -> T:
with self._lock:
return self._list.pop(index)
@@ -455,15 +463,23 @@ class LockedListProxy(list, Generic[T]): # type: ignore[type-arg]
with self._lock:
self._list.clear()
def __setitem__(self, index: int, value: T) -> None:
@overload
def __setitem__(self, index: SupportsIndex, value: T) -> None: ...
@overload
def __setitem__(self, index: slice, value: Iterable[T]) -> None: ...
def __setitem__(self, index: Any, value: Any) -> None:
with self._lock:
self._list[index] = value
def __delitem__(self, index: int) -> None:
def __delitem__(self, index: SupportsIndex | slice) -> None:
with self._lock:
del self._list[index]
def __getitem__(self, index: int) -> T:
@overload
def __getitem__(self, index: SupportsIndex) -> T: ...
@overload
def __getitem__(self, index: slice) -> list[T]: ...
def __getitem__(self, index: Any) -> Any:
return self._list[index]
def __len__(self) -> int:
@@ -481,7 +497,7 @@ class LockedListProxy(list, Generic[T]): # type: ignore[type-arg]
def __bool__(self) -> bool:
return bool(self._list)
def __eq__(self, other: object) -> bool: # type: ignore[override]
def __eq__(self, other: object) -> bool:
"""Compare based on the underlying list contents."""
if isinstance(other, LockedListProxy):
# Avoid deadlocks by acquiring locks in a consistent order.
@@ -492,7 +508,7 @@ class LockedListProxy(list, Generic[T]): # type: ignore[type-arg]
with self._lock:
return self._list == other
def __ne__(self, other: object) -> bool: # type: ignore[override]
def __ne__(self, other: object) -> bool:
return not self.__eq__(other)
@@ -505,8 +521,7 @@ class LockedDictProxy(dict, Generic[T]): # type: ignore[type-arg]
"""
def __init__(self, d: dict[str, T], lock: threading.Lock) -> None:
# Do NOT call super().__init__() -- we don't want to copy data into
# the builtin dict storage. All access goes through self._dict.
super().__init__() # empty builtin dict; all access goes through self._dict
self._dict = d
self._lock = lock
@@ -518,11 +533,11 @@ class LockedDictProxy(dict, Generic[T]): # type: ignore[type-arg]
with self._lock:
del self._dict[key]
def pop(self, key: str, *default: T) -> T:
def pop(self, key: str, *default: T) -> T: # type: ignore[override]
with self._lock:
return self._dict.pop(key, *default)
def update(self, other: dict[str, T]) -> None:
def update(self, other: dict[str, T]) -> None: # type: ignore[override]
with self._lock:
self._dict.update(other)
@@ -530,7 +545,7 @@ class LockedDictProxy(dict, Generic[T]): # type: ignore[type-arg]
with self._lock:
self._dict.clear()
def setdefault(self, key: str, default: T) -> T:
def setdefault(self, key: str, default: T) -> T: # type: ignore[override]
with self._lock:
return self._dict.setdefault(key, default)
@@ -546,16 +561,16 @@ class LockedDictProxy(dict, Generic[T]): # type: ignore[type-arg]
def __contains__(self, key: object) -> bool:
return key in self._dict
def keys(self) -> KeysView[str]:
def keys(self) -> KeysView[str]: # type: ignore[override]
return self._dict.keys()
def values(self) -> ValuesView[T]:
def values(self) -> ValuesView[T]: # type: ignore[override]
return self._dict.values()
def items(self) -> ItemsView[str, T]:
def items(self) -> ItemsView[str, T]: # type: ignore[override]
return self._dict.items()
def get(self, key: str, default: T | None = None) -> T | None:
def get(self, key: str, default: T | None = None) -> T | None: # type: ignore[override]
return self._dict.get(key, default)
def __repr__(self) -> str:
@@ -564,7 +579,7 @@ class LockedDictProxy(dict, Generic[T]): # type: ignore[type-arg]
def __bool__(self) -> bool:
return bool(self._dict)
def __eq__(self, other: object) -> bool: # type: ignore[override]
def __eq__(self, other: object) -> bool:
"""Compare based on the underlying dict contents."""
if isinstance(other, LockedDictProxy):
# Avoid deadlocks by acquiring locks in a consistent order.
@@ -575,7 +590,7 @@ class LockedDictProxy(dict, Generic[T]): # type: ignore[type-arg]
with self._lock:
return self._dict == other
def __ne__(self, other: object) -> bool: # type: ignore[override]
def __ne__(self, other: object) -> bool:
return not self.__eq__(other)
@@ -737,7 +752,9 @@ class Flow(Generic[T], metaclass=FlowMeta):
name: str | None = None
tracing: bool | None = None
stream: bool = False
memory: Any = None # Memory | MemoryScope | MemorySlice | None; auto-created if not set
memory: Any = (
None # Memory | MemoryScope | MemorySlice | None; auto-created if not set
)
input_provider: Any = None # InputProvider | None; per-flow override for self.ask()
def __class_getitem__(cls: type[Flow[T]], item: type[T]) -> type[Flow[T]]:
@@ -881,7 +898,8 @@ class Flow(Generic[T], metaclass=FlowMeta):
"""
if self.memory is None:
raise ValueError("No memory configured for this flow")
return self.memory.extract_memories(content)
result: list[str] = self.memory.extract_memories(content)
return result
def _mark_or_listener_fired(self, listener_name: FlowMethodName) -> bool:
"""Mark an OR listener as fired atomically.
@@ -1352,8 +1370,10 @@ class Flow(Generic[T], metaclass=FlowMeta):
ValueError: If structured state model lacks 'id' field
TypeError: If state is neither BaseModel nor dictionary
"""
init_state = self.initial_state
# Handle case where initial_state is None but we have a type parameter
if self.initial_state is None and hasattr(self, "_initial_state_t"):
if init_state is None and hasattr(self, "_initial_state_t"):
state_type = self._initial_state_t
if isinstance(state_type, type):
if issubclass(state_type, FlowState):
@@ -1377,12 +1397,12 @@ class Flow(Generic[T], metaclass=FlowMeta):
return cast(T, {"id": str(uuid4())})
# Handle case where no initial state is provided
if self.initial_state is None:
if init_state is None:
return cast(T, {"id": str(uuid4())})
# Handle case where initial_state is a type (class)
if isinstance(self.initial_state, type):
state_class: type[T] = self.initial_state
if isinstance(init_state, type):
state_class = init_state
if issubclass(state_class, FlowState):
return state_class()
if issubclass(state_class, BaseModel):
@@ -1393,19 +1413,19 @@ class Flow(Generic[T], metaclass=FlowMeta):
if not getattr(model_instance, "id", None):
object.__setattr__(model_instance, "id", str(uuid4()))
return model_instance
if self.initial_state is dict:
if init_state is dict:
return cast(T, {"id": str(uuid4())})
# Handle dictionary instance case
if isinstance(self.initial_state, dict):
new_state = dict(self.initial_state) # Copy to avoid mutations
if isinstance(init_state, dict):
new_state = dict(init_state) # Copy to avoid mutations
if "id" not in new_state:
new_state["id"] = str(uuid4())
return cast(T, new_state)
# Handle BaseModel instance case
if isinstance(self.initial_state, BaseModel):
model = cast(BaseModel, self.initial_state)
if isinstance(init_state, BaseModel):
model = cast(BaseModel, init_state)
if not hasattr(model, "id"):
raise ValueError("Flow state model must have an 'id' field")
@@ -2178,6 +2198,8 @@ class Flow(Generic[T], metaclass=FlowMeta):
from crewai.flow.async_feedback.types import HumanFeedbackPending
if isinstance(e, HumanFeedbackPending):
e.context.method_name = method_name
# Auto-save pending feedback (create default persistence if needed)
if self._persistence is None:
from crewai.flow.persistence import SQLiteFlowPersistence
@@ -2277,14 +2299,23 @@ class Flow(Generic[T], metaclass=FlowMeta):
router_name, router_input, current_triggering_event_id
)
if router_result: # Only add non-None results
router_results.append(FlowMethodName(str(router_result)))
router_result_str = (
router_result.value
if isinstance(router_result, enum.Enum)
else str(router_result)
)
router_results.append(FlowMethodName(router_result_str))
# If this was a human_feedback router, map the outcome to the feedback
if self.last_human_feedback is not None:
router_result_to_feedback[str(router_result)] = (
router_result_to_feedback[router_result_str] = (
self.last_human_feedback
)
current_trigger = (
FlowMethodName(str(router_result))
FlowMethodName(
router_result.value
if isinstance(router_result, enum.Enum)
else str(router_result)
)
if router_result is not None
else FlowMethodName("") # Update for next iteration of router chain
)
@@ -2701,7 +2732,10 @@ class Flow(Generic[T], metaclass=FlowMeta):
return topic
```
"""
from concurrent.futures import ThreadPoolExecutor, TimeoutError as FuturesTimeoutError
from concurrent.futures import (
ThreadPoolExecutor,
TimeoutError as FuturesTimeoutError,
)
from datetime import datetime
from crewai.events.types.flow_events import (
@@ -2770,14 +2804,16 @@ class Flow(Generic[T], metaclass=FlowMeta):
response = None
# Record in history
self._input_history.append({
"message": message,
"response": response,
"method_name": method_name,
"timestamp": datetime.now(),
"metadata": metadata,
"response_metadata": response_metadata,
})
self._input_history.append(
{
"message": message,
"response": response,
"method_name": method_name,
"timestamp": datetime.now(),
"metadata": metadata,
"response_metadata": response_metadata,
}
)
# Emit input received event
crewai_event_bus.emit(

View File

@@ -4,6 +4,7 @@ Tests the Flow-based agent executor implementation including state management,
flow methods, routing logic, and error handling.
"""
import time
from unittest.mock import Mock, patch
import pytest
@@ -462,3 +463,176 @@ class TestFlowInvoke:
assert result == {"output": "Done"}
assert len(executor.state.messages) >= 2
class TestNativeToolExecution:
"""Test native tool execution behavior."""
@pytest.fixture
def mock_dependencies(self):
llm = Mock()
llm.supports_stop_words.return_value = True
task = Mock()
task.name = "Test Task"
task.description = "Test"
task.human_input = False
task.response_model = None
crew = Mock()
crew._memory = None
crew.verbose = False
crew._train = False
agent = Mock()
agent.id = "test-agent-id"
agent.role = "Test Agent"
agent.verbose = False
agent.key = "test-key"
prompt = {"prompt": "Test {input} {tool_names} {tools}"}
tools_handler = Mock()
tools_handler.cache = None
return {
"llm": llm,
"task": task,
"crew": crew,
"agent": agent,
"prompt": prompt,
"max_iter": 10,
"tools": [],
"tools_names": "",
"stop_words": [],
"tools_description": "",
"tools_handler": tools_handler,
}
def test_execute_native_tool_runs_parallel_for_multiple_calls(
self, mock_dependencies
):
executor = AgentExecutor(**mock_dependencies)
def slow_one() -> str:
time.sleep(0.2)
return "one"
def slow_two() -> str:
time.sleep(0.2)
return "two"
executor._available_functions = {"slow_one": slow_one, "slow_two": slow_two}
executor.state.pending_tool_calls = [
{
"id": "call_1",
"function": {"name": "slow_one", "arguments": "{}"},
},
{
"id": "call_2",
"function": {"name": "slow_two", "arguments": "{}"},
},
]
started = time.perf_counter()
result = executor.execute_native_tool()
elapsed = time.perf_counter() - started
assert result == "native_tool_completed"
assert elapsed < 0.5
tool_messages = [m for m in executor.state.messages if m.get("role") == "tool"]
assert len(tool_messages) == 2
assert tool_messages[0]["tool_call_id"] == "call_1"
assert tool_messages[1]["tool_call_id"] == "call_2"
def test_execute_native_tool_falls_back_to_sequential_for_result_as_answer(
self, mock_dependencies
):
executor = AgentExecutor(**mock_dependencies)
def slow_one() -> str:
time.sleep(0.2)
return "one"
def slow_two() -> str:
time.sleep(0.2)
return "two"
result_tool = Mock()
result_tool.name = "slow_one"
result_tool.result_as_answer = True
result_tool.max_usage_count = None
result_tool.current_usage_count = 0
executor.original_tools = [result_tool]
executor._available_functions = {"slow_one": slow_one, "slow_two": slow_two}
executor.state.pending_tool_calls = [
{
"id": "call_1",
"function": {"name": "slow_one", "arguments": "{}"},
},
{
"id": "call_2",
"function": {"name": "slow_two", "arguments": "{}"},
},
]
started = time.perf_counter()
result = executor.execute_native_tool()
elapsed = time.perf_counter() - started
assert result == "tool_result_is_final"
assert elapsed >= 0.2
assert elapsed < 0.8
assert isinstance(executor.state.current_answer, AgentFinish)
assert executor.state.current_answer.output == "one"
def test_execute_native_tool_result_as_answer_short_circuits_remaining_calls(
self, mock_dependencies
):
executor = AgentExecutor(**mock_dependencies)
call_counts = {"slow_one": 0, "slow_two": 0}
def slow_one() -> str:
call_counts["slow_one"] += 1
time.sleep(0.2)
return "one"
def slow_two() -> str:
call_counts["slow_two"] += 1
time.sleep(0.2)
return "two"
result_tool = Mock()
result_tool.name = "slow_one"
result_tool.result_as_answer = True
result_tool.max_usage_count = None
result_tool.current_usage_count = 0
executor.original_tools = [result_tool]
executor._available_functions = {"slow_one": slow_one, "slow_two": slow_two}
executor.state.pending_tool_calls = [
{
"id": "call_1",
"function": {"name": "slow_one", "arguments": "{}"},
},
{
"id": "call_2",
"function": {"name": "slow_two", "arguments": "{}"},
},
]
started = time.perf_counter()
result = executor.execute_native_tool()
elapsed = time.perf_counter() - started
assert result == "tool_result_is_final"
assert isinstance(executor.state.current_answer, AgentFinish)
assert executor.state.current_answer.output == "one"
assert call_counts["slow_one"] == 1
assert call_counts["slow_two"] == 0
assert elapsed < 0.5
tool_messages = [m for m in executor.state.messages if m.get("role") == "tool"]
assert len(tool_messages) == 1
assert tool_messages[0]["tool_call_id"] == "call_1"

View File

@@ -6,13 +6,20 @@ when the LLM supports it, across multiple providers.
from __future__ import annotations
from collections.abc import Generator
import os
import threading
import time
from collections import Counter
from unittest.mock import patch
import pytest
from pydantic import BaseModel, Field
from crewai import Agent, Crew, Task
from crewai.events import crewai_event_bus
from crewai.hooks import register_after_tool_call_hook, register_before_tool_call_hook
from crewai.hooks.tool_hooks import ToolCallHookContext
from crewai.llm import LLM
from crewai.tools.base_tool import BaseTool
@@ -64,6 +71,73 @@ class FailingTool(BaseTool):
def _run(self) -> str:
raise Exception("This tool always fails")
class LocalSearchInput(BaseModel):
query: str = Field(description="Search query")
class ParallelProbe:
"""Thread-safe in-memory recorder for tool execution windows."""
_lock = threading.Lock()
_windows: list[tuple[str, float, float]] = []
@classmethod
def reset(cls) -> None:
with cls._lock:
cls._windows = []
@classmethod
def record(cls, tool_name: str, start: float, end: float) -> None:
with cls._lock:
cls._windows.append((tool_name, start, end))
@classmethod
def windows(cls) -> list[tuple[str, float, float]]:
with cls._lock:
return list(cls._windows)
def _parallel_prompt() -> str:
return (
"This is a tool-calling compliance test. "
"In your next assistant turn, emit exactly 3 tool calls in the same response (parallel tool calls), in this order: "
"1) parallel_local_search_one(query='latest OpenAI model release notes'), "
"2) parallel_local_search_two(query='latest Anthropic model release notes'), "
"3) parallel_local_search_three(query='latest Gemini model release notes'). "
"Do not call any other tools and do not answer before those 3 tool calls are emitted. "
"After the tool results return, provide a one paragraph summary."
)
def _max_concurrency(windows: list[tuple[str, float, float]]) -> int:
points: list[tuple[float, int]] = []
for _, start, end in windows:
points.append((start, 1))
points.append((end, -1))
points.sort(key=lambda p: (p[0], p[1]))
current = 0
maximum = 0
for _, delta in points:
current += delta
if current > maximum:
maximum = current
return maximum
def _assert_tools_overlapped() -> None:
windows = ParallelProbe.windows()
local_windows = [
w
for w in windows
if w[0].startswith("parallel_local_search_")
]
assert len(local_windows) >= 3, f"Expected at least 3 local tool calls, got {len(local_windows)}"
assert _max_concurrency(local_windows) >= 2, "Expected overlapping local tool executions"
@pytest.fixture
def calculator_tool() -> CalculatorTool:
"""Create a calculator tool for testing."""
@@ -82,6 +156,65 @@ def failing_tool() -> BaseTool:
)
@pytest.fixture
def parallel_tools() -> list[BaseTool]:
"""Create local tools used to verify native parallel execution deterministically."""
class ParallelLocalSearchOne(BaseTool):
name: str = "parallel_local_search_one"
description: str = "Local search tool #1 for concurrency testing."
args_schema: type[BaseModel] = LocalSearchInput
def _run(self, query: str) -> str:
start = time.perf_counter()
time.sleep(1.0)
end = time.perf_counter()
ParallelProbe.record(self.name, start, end)
return f"[one] {query}"
class ParallelLocalSearchTwo(BaseTool):
name: str = "parallel_local_search_two"
description: str = "Local search tool #2 for concurrency testing."
args_schema: type[BaseModel] = LocalSearchInput
def _run(self, query: str) -> str:
start = time.perf_counter()
time.sleep(1.0)
end = time.perf_counter()
ParallelProbe.record(self.name, start, end)
return f"[two] {query}"
class ParallelLocalSearchThree(BaseTool):
name: str = "parallel_local_search_three"
description: str = "Local search tool #3 for concurrency testing."
args_schema: type[BaseModel] = LocalSearchInput
def _run(self, query: str) -> str:
start = time.perf_counter()
time.sleep(1.0)
end = time.perf_counter()
ParallelProbe.record(self.name, start, end)
return f"[three] {query}"
return [
ParallelLocalSearchOne(),
ParallelLocalSearchTwo(),
ParallelLocalSearchThree(),
]
def _attach_parallel_probe_handler() -> None:
@crewai_event_bus.on(ToolUsageFinishedEvent)
def _capture_tool_window(_source, event: ToolUsageFinishedEvent):
if not event.tool_name.startswith("parallel_local_search_"):
return
ParallelProbe.record(
event.tool_name,
event.started_at.timestamp(),
event.finished_at.timestamp(),
)
# =============================================================================
# OpenAI Provider Tests
# =============================================================================
@@ -122,7 +255,7 @@ class TestOpenAINativeToolCalling:
self, calculator_tool: CalculatorTool
) -> None:
"""Test OpenAI agent kickoff with mocked LLM call."""
llm = LLM(model="gpt-4o-mini")
llm = LLM(model="gpt-5-nano")
with patch.object(llm, "call", return_value="The answer is 120.") as mock_call:
agent = Agent(
@@ -146,6 +279,174 @@ class TestOpenAINativeToolCalling:
assert mock_call.called
assert result is not None
@pytest.mark.vcr()
@pytest.mark.timeout(180)
def test_openai_parallel_native_tool_calling_test_crew(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="gpt-5-nano", temperature=1),
verbose=False,
max_iter=3,
)
task = Task(
description=_parallel_prompt(),
expected_output="A one sentence summary of both tool outputs",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff()
assert result is not None
_assert_tools_overlapped()
@pytest.mark.vcr()
@pytest.mark.timeout(180)
def test_openai_parallel_native_tool_calling_test_agent_kickoff(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="gpt-4o-mini"),
verbose=False,
max_iter=3,
)
result = agent.kickoff(_parallel_prompt())
assert result is not None
_assert_tools_overlapped()
@pytest.mark.vcr()
@pytest.mark.timeout(180)
def test_openai_parallel_native_tool_calling_tool_hook_parity_crew(
self, parallel_tools: list[BaseTool]
) -> None:
hook_calls: dict[str, list[dict[str, str]]] = {"before": [], "after": []}
def before_hook(context: ToolCallHookContext) -> bool | None:
if context.tool_name.startswith("parallel_local_search_"):
hook_calls["before"].append(
{
"tool_name": context.tool_name,
"query": str(context.tool_input.get("query", "")),
}
)
return None
def after_hook(context: ToolCallHookContext) -> str | None:
if context.tool_name.startswith("parallel_local_search_"):
hook_calls["after"].append(
{
"tool_name": context.tool_name,
"query": str(context.tool_input.get("query", "")),
}
)
return None
register_before_tool_call_hook(before_hook)
register_after_tool_call_hook(after_hook)
try:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="gpt-5-nano", temperature=1),
verbose=False,
max_iter=3,
)
task = Task(
description=_parallel_prompt(),
expected_output="A one sentence summary of both tool outputs",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff()
assert result is not None
_assert_tools_overlapped()
before_names = [call["tool_name"] for call in hook_calls["before"]]
after_names = [call["tool_name"] for call in hook_calls["after"]]
assert len(before_names) >= 3, "Expected before hooks for all parallel calls"
assert Counter(before_names) == Counter(after_names)
assert all(call["query"] for call in hook_calls["before"])
assert all(call["query"] for call in hook_calls["after"])
finally:
from crewai.hooks import (
unregister_after_tool_call_hook,
unregister_before_tool_call_hook,
)
unregister_before_tool_call_hook(before_hook)
unregister_after_tool_call_hook(after_hook)
@pytest.mark.vcr()
@pytest.mark.timeout(180)
def test_openai_parallel_native_tool_calling_tool_hook_parity_agent_kickoff(
self, parallel_tools: list[BaseTool]
) -> None:
hook_calls: dict[str, list[dict[str, str]]] = {"before": [], "after": []}
def before_hook(context: ToolCallHookContext) -> bool | None:
if context.tool_name.startswith("parallel_local_search_"):
hook_calls["before"].append(
{
"tool_name": context.tool_name,
"query": str(context.tool_input.get("query", "")),
}
)
return None
def after_hook(context: ToolCallHookContext) -> str | None:
if context.tool_name.startswith("parallel_local_search_"):
hook_calls["after"].append(
{
"tool_name": context.tool_name,
"query": str(context.tool_input.get("query", "")),
}
)
return None
register_before_tool_call_hook(before_hook)
register_after_tool_call_hook(after_hook)
try:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="gpt-5-nano", temperature=1),
verbose=False,
max_iter=3,
)
result = agent.kickoff(_parallel_prompt())
assert result is not None
_assert_tools_overlapped()
before_names = [call["tool_name"] for call in hook_calls["before"]]
after_names = [call["tool_name"] for call in hook_calls["after"]]
assert len(before_names) >= 3, "Expected before hooks for all parallel calls"
assert Counter(before_names) == Counter(after_names)
assert all(call["query"] for call in hook_calls["before"])
assert all(call["query"] for call in hook_calls["after"])
finally:
from crewai.hooks import (
unregister_after_tool_call_hook,
unregister_before_tool_call_hook,
)
unregister_before_tool_call_hook(before_hook)
unregister_after_tool_call_hook(after_hook)
# =============================================================================
# Anthropic Provider Tests
@@ -217,6 +518,46 @@ class TestAnthropicNativeToolCalling:
assert mock_call.called
assert result is not None
@pytest.mark.vcr()
def test_anthropic_parallel_native_tool_calling_test_crew(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="anthropic/claude-sonnet-4-6"),
verbose=False,
max_iter=3,
)
task = Task(
description=_parallel_prompt(),
expected_output="A one sentence summary of both tool outputs",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff()
assert result is not None
_assert_tools_overlapped()
@pytest.mark.vcr()
def test_anthropic_parallel_native_tool_calling_test_agent_kickoff(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="anthropic/claude-sonnet-4-6"),
verbose=False,
max_iter=3,
)
result = agent.kickoff(_parallel_prompt())
assert result is not None
_assert_tools_overlapped()
# =============================================================================
# Google/Gemini Provider Tests
@@ -247,7 +588,7 @@ class TestGeminiNativeToolCalling:
goal="Help users with mathematical calculations",
backstory="You are a helpful math assistant.",
tools=[calculator_tool],
llm=LLM(model="gemini/gemini-2.0-flash-exp"),
llm=LLM(model="gemini/gemini-2.5-flash"),
)
task = Task(
@@ -266,7 +607,7 @@ class TestGeminiNativeToolCalling:
self, calculator_tool: CalculatorTool
) -> None:
"""Test Gemini agent kickoff with mocked LLM call."""
llm = LLM(model="gemini/gemini-2.0-flash-001")
llm = LLM(model="gemini/gemini-2.5-flash")
with patch.object(llm, "call", return_value="The answer is 120.") as mock_call:
agent = Agent(
@@ -290,6 +631,46 @@ class TestGeminiNativeToolCalling:
assert mock_call.called
assert result is not None
@pytest.mark.vcr()
def test_gemini_parallel_native_tool_calling_test_crew(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="gemini/gemini-2.5-flash"),
verbose=False,
max_iter=3,
)
task = Task(
description=_parallel_prompt(),
expected_output="A one sentence summary of both tool outputs",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff()
assert result is not None
_assert_tools_overlapped()
@pytest.mark.vcr()
def test_gemini_parallel_native_tool_calling_test_agent_kickoff(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="gemini/gemini-2.5-flash"),
verbose=False,
max_iter=3,
)
result = agent.kickoff(_parallel_prompt())
assert result is not None
_assert_tools_overlapped()
# =============================================================================
# Azure Provider Tests
@@ -324,7 +705,7 @@ class TestAzureNativeToolCalling:
goal="Help users with mathematical calculations",
backstory="You are a helpful math assistant.",
tools=[calculator_tool],
llm=LLM(model="azure/gpt-4o-mini"),
llm=LLM(model="azure/gpt-5-nano"),
verbose=False,
max_iter=3,
)
@@ -347,7 +728,7 @@ class TestAzureNativeToolCalling:
) -> None:
"""Test Azure agent kickoff with mocked LLM call."""
llm = LLM(
model="azure/gpt-4o-mini",
model="azure/gpt-5-nano",
api_key="test-key",
base_url="https://test.openai.azure.com",
)
@@ -374,6 +755,46 @@ class TestAzureNativeToolCalling:
assert mock_call.called
assert result is not None
@pytest.mark.vcr()
def test_azure_parallel_native_tool_calling_test_crew(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="azure/gpt-5-nano"),
verbose=False,
max_iter=3,
)
task = Task(
description=_parallel_prompt(),
expected_output="A one sentence summary of both tool outputs",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff()
assert result is not None
_assert_tools_overlapped()
@pytest.mark.vcr()
def test_azure_parallel_native_tool_calling_test_agent_kickoff(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="azure/gpt-5-nano"),
verbose=False,
max_iter=3,
)
result = agent.kickoff(_parallel_prompt())
assert result is not None
_assert_tools_overlapped()
# =============================================================================
# Bedrock Provider Tests
@@ -384,18 +805,30 @@ class TestBedrockNativeToolCalling:
"""Tests for native tool calling with AWS Bedrock models."""
@pytest.fixture(autouse=True)
def mock_aws_env(self):
"""Mock AWS environment variables for tests."""
env_vars = {
"AWS_ACCESS_KEY_ID": "test-key",
"AWS_SECRET_ACCESS_KEY": "test-secret",
"AWS_REGION": "us-east-1",
}
if "AWS_ACCESS_KEY_ID" not in os.environ:
with patch.dict(os.environ, env_vars):
yield
else:
yield
def validate_bedrock_credentials_for_live_recording(self):
"""Run Bedrock tests only when explicitly enabled."""
run_live_bedrock = os.getenv("RUN_BEDROCK_LIVE_TESTS", "false").lower() == "true"
if not run_live_bedrock:
pytest.skip(
"Skipping Bedrock tests by default. "
"Set RUN_BEDROCK_LIVE_TESTS=true with valid AWS credentials to enable."
)
access_key = os.getenv("AWS_ACCESS_KEY_ID", "")
secret_key = os.getenv("AWS_SECRET_ACCESS_KEY", "")
if (
not access_key
or not secret_key
or access_key.startswith(("fake-", "test-"))
or secret_key.startswith(("fake-", "test-"))
):
pytest.skip(
"Skipping Bedrock tests: valid AWS credentials are required when "
"RUN_BEDROCK_LIVE_TESTS=true."
)
yield
@pytest.mark.vcr()
def test_bedrock_agent_kickoff_with_tools_mocked(
@@ -427,6 +860,46 @@ class TestBedrockNativeToolCalling:
assert result.raw is not None
assert "120" in str(result.raw)
@pytest.mark.vcr()
def test_bedrock_parallel_native_tool_calling_test_crew(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="bedrock/anthropic.claude-3-haiku-20240307-v1:0"),
verbose=False,
max_iter=3,
)
task = Task(
description=_parallel_prompt(),
expected_output="A one sentence summary of both tool outputs",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff()
assert result is not None
_assert_tools_overlapped()
@pytest.mark.vcr()
def test_bedrock_parallel_native_tool_calling_test_agent_kickoff(
self, parallel_tools: list[BaseTool]
) -> None:
agent = Agent(
role="Parallel Tool Agent",
goal="Use both tools exactly as instructed",
backstory="You follow tool instructions precisely.",
tools=parallel_tools,
llm=LLM(model="bedrock/anthropic.claude-3-haiku-20240307-v1:0"),
verbose=False,
max_iter=3,
)
result = agent.kickoff(_parallel_prompt())
assert result is not None
_assert_tools_overlapped()
# =============================================================================
# Cross-Provider Native Tool Calling Behavior Tests
@@ -439,7 +912,7 @@ class TestNativeToolCallingBehavior:
def test_supports_function_calling_check(self) -> None:
"""Test that supports_function_calling() is properly checked."""
# OpenAI should support function calling
openai_llm = LLM(model="gpt-4o-mini")
openai_llm = LLM(model="gpt-5-nano")
assert hasattr(openai_llm, "supports_function_calling")
assert openai_llm.supports_function_calling() is True
@@ -475,7 +948,7 @@ class TestNativeToolCallingTokenUsage:
goal="Perform calculations efficiently",
backstory="You calculate things.",
tools=[calculator_tool],
llm=LLM(model="gpt-4o-mini"),
llm=LLM(model="gpt-5-nano"),
verbose=False,
max_iter=3,
)
@@ -519,7 +992,7 @@ def test_native_tool_calling_error_handling(failing_tool: FailingTool):
goal="Perform calculations efficiently",
backstory="You calculate things.",
tools=[failing_tool],
llm=LLM(model="gpt-4o-mini"),
llm=LLM(model="gpt-5-nano"),
verbose=False,
max_iter=3,
)
@@ -578,7 +1051,7 @@ class TestMaxUsageCountWithNativeToolCalling:
goal="Call the counting tool multiple times",
backstory="You are an agent that counts things.",
tools=[tool],
llm=LLM(model="gpt-4o-mini"),
llm=LLM(model="gpt-5-nano"),
verbose=False,
max_iter=5,
)
@@ -606,7 +1079,7 @@ class TestMaxUsageCountWithNativeToolCalling:
goal="Use the counting tool as many times as requested",
backstory="You are an agent that counts things. You must try to use the tool for each value requested.",
tools=[tool],
llm=LLM(model="gpt-4o-mini"),
llm=LLM(model="gpt-5-nano"),
verbose=False,
max_iter=5,
)
@@ -638,7 +1111,7 @@ class TestMaxUsageCountWithNativeToolCalling:
goal="Use the counting tool exactly as requested",
backstory="You are an agent that counts things precisely.",
tools=[tool],
llm=LLM(model="gpt-4o-mini"),
llm=LLM(model="gpt-5-nano"),
verbose=False,
max_iter=5,
)
@@ -653,5 +1126,6 @@ class TestMaxUsageCountWithNativeToolCalling:
result = crew.kickoff()
assert result is not None
# Verify usage count was incremented for each successful call
assert tool.current_usage_count == 2
# Verify the requested calls occurred while keeping usage bounded.
assert tool.current_usage_count >= 2
assert tool.current_usage_count <= tool.max_usage_count

View File

@@ -0,0 +1,247 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"\nCurrent Task:
This is a tool-calling compliance test. In your next assistant turn, emit exactly
3 tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."}],"model":"claude-sonnet-4-6","stop_sequences":["\nObservation:"],"stream":false,"system":"You
are Parallel Tool Agent. You follow tool instructions precisely.\nYour personal
goal is: Use both tools exactly as instructed","tools":[{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}},{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}},{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '1639'
content-type:
- application/json
host:
- api.anthropic.com
x-api-key:
- X-API-KEY-XXX
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.73.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: '{"model":"claude-sonnet-4-6","id":"msg_01XeN1XTXZgmPyLMMGjivabb","type":"message","role":"assistant","content":[{"type":"text","text":"I''ll
execute all 3 parallel searches simultaneously right now!"},{"type":"tool_use","id":"toolu_01NwzvrxEz6tvT3A8ydvMtHu","name":"parallel_local_search_one","input":{"query":"latest
OpenAI model release notes"},"caller":{"type":"direct"}},{"type":"tool_use","id":"toolu_01YCxzSB1suk9uPVC1uwfHz9","name":"parallel_local_search_two","input":{"query":"latest
Anthropic model release notes"},"caller":{"type":"direct"}},{"type":"tool_use","id":"toolu_01Mauvxzv58eDY7pUt9HMKGy","name":"parallel_local_search_three","input":{"query":"latest
Gemini model release notes"},"caller":{"type":"direct"}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":914,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":169,"service_tier":"standard","inference_geo":"global"}}'
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Security-Policy:
- CSP-FILTERED
Content-Type:
- application/json
Date:
- Wed, 18 Feb 2026 23:54:43 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Robots-Tag:
- none
anthropic-organization-id:
- ANTHROPIC-ORGANIZATION-ID-XXX
anthropic-ratelimit-input-tokens-limit:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-LIMIT-XXX
anthropic-ratelimit-input-tokens-remaining:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-REMAINING-XXX
anthropic-ratelimit-input-tokens-reset:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-RESET-XXX
anthropic-ratelimit-output-tokens-limit:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-LIMIT-XXX
anthropic-ratelimit-output-tokens-remaining:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-REMAINING-XXX
anthropic-ratelimit-output-tokens-reset:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-RESET-XXX
anthropic-ratelimit-requests-limit:
- '20000'
anthropic-ratelimit-requests-remaining:
- '19999'
anthropic-ratelimit-requests-reset:
- '2026-02-18T23:54:41Z'
anthropic-ratelimit-tokens-limit:
- ANTHROPIC-RATELIMIT-TOKENS-LIMIT-XXX
anthropic-ratelimit-tokens-remaining:
- ANTHROPIC-RATELIMIT-TOKENS-REMAINING-XXX
anthropic-ratelimit-tokens-reset:
- ANTHROPIC-RATELIMIT-TOKENS-RESET-XXX
cf-cache-status:
- DYNAMIC
request-id:
- REQUEST-ID-XXX
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2099'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"\nCurrent Task:
This is a tool-calling compliance test. In your next assistant turn, emit exactly
3 tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."},{"role":"assistant","content":[{"type":"tool_use","id":"toolu_01NwzvrxEz6tvT3A8ydvMtHu","name":"parallel_local_search_one","input":{"query":"latest
OpenAI model release notes"}},{"type":"tool_use","id":"toolu_01YCxzSB1suk9uPVC1uwfHz9","name":"parallel_local_search_two","input":{"query":"latest
Anthropic model release notes"}},{"type":"tool_use","id":"toolu_01Mauvxzv58eDY7pUt9HMKGy","name":"parallel_local_search_three","input":{"query":"latest
Gemini model release notes"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_01NwzvrxEz6tvT3A8ydvMtHu","content":"[one]
latest OpenAI model release notes"},{"type":"tool_result","tool_use_id":"toolu_01YCxzSB1suk9uPVC1uwfHz9","content":"[two]
latest Anthropic model release notes"},{"type":"tool_result","tool_use_id":"toolu_01Mauvxzv58eDY7pUt9HMKGy","content":"[three]
latest Gemini model release notes"}]}],"model":"claude-sonnet-4-6","stop_sequences":["\nObservation:"],"stream":false,"system":"You
are Parallel Tool Agent. You follow tool instructions precisely.\nYour personal
goal is: Use both tools exactly as instructed","tools":[{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}},{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}},{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '2517'
content-type:
- application/json
host:
- api.anthropic.com
x-api-key:
- X-API-KEY-XXX
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.73.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: "{\"model\":\"claude-sonnet-4-6\",\"id\":\"msg_01PFXqwwdwwHWadPdtNU5tUZ\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[{\"type\":\"text\",\"text\":\"The
three parallel searches were executed successfully, each targeting the latest
release notes for the leading AI model families. The search results confirm
that queries were dispatched simultaneously to retrieve the most recent developments
from **OpenAI** (via tool one), **Anthropic** (via tool two), and **Google's
Gemini** (via tool three). While the local search tools returned placeholder
outputs in this test environment rather than detailed release notes, the structure
of the test validates that all three parallel tool calls were emitted correctly
and in the specified order \u2014 demonstrating proper concurrent tool-call
behavior with no dependencies between the three independent searches.\"}],\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"usage\":{\"input_tokens\":1197,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":131,\"service_tier\":\"standard\",\"inference_geo\":\"global\"}}"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Security-Policy:
- CSP-FILTERED
Content-Type:
- application/json
Date:
- Wed, 18 Feb 2026 23:54:49 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Robots-Tag:
- none
anthropic-organization-id:
- ANTHROPIC-ORGANIZATION-ID-XXX
anthropic-ratelimit-input-tokens-limit:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-LIMIT-XXX
anthropic-ratelimit-input-tokens-remaining:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-REMAINING-XXX
anthropic-ratelimit-input-tokens-reset:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-RESET-XXX
anthropic-ratelimit-output-tokens-limit:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-LIMIT-XXX
anthropic-ratelimit-output-tokens-remaining:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-REMAINING-XXX
anthropic-ratelimit-output-tokens-reset:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-RESET-XXX
anthropic-ratelimit-requests-limit:
- '20000'
anthropic-ratelimit-requests-remaining:
- '19999'
anthropic-ratelimit-requests-reset:
- '2026-02-18T23:54:44Z'
anthropic-ratelimit-tokens-limit:
- ANTHROPIC-RATELIMIT-TOKENS-LIMIT-XXX
anthropic-ratelimit-tokens-remaining:
- ANTHROPIC-RATELIMIT-TOKENS-REMAINING-XXX
anthropic-ratelimit-tokens-reset:
- ANTHROPIC-RATELIMIT-TOKENS-RESET-XXX
cf-cache-status:
- DYNAMIC
request-id:
- REQUEST-ID-XXX
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '4092'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,254 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"\nCurrent Task:
This is a tool-calling compliance test. In your next assistant turn, emit exactly
3 tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}],"model":"claude-sonnet-4-6","stop_sequences":["\nObservation:"],"stream":false,"system":"You
are Parallel Tool Agent. You follow tool instructions precisely.\nYour personal
goal is: Use both tools exactly as instructed","tools":[{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}},{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}},{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '1820'
content-type:
- application/json
host:
- api.anthropic.com
x-api-key:
- X-API-KEY-XXX
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.73.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: '{"model":"claude-sonnet-4-6","id":"msg_01RJ4CphwpmkmsJFJjeCNvXz","type":"message","role":"assistant","content":[{"type":"text","text":"I''ll
execute all 3 parallel tool calls simultaneously right away!"},{"type":"tool_use","id":"toolu_01YWY3cSomRuv4USmq55Prk3","name":"parallel_local_search_one","input":{"query":"latest
OpenAI model release notes"},"caller":{"type":"direct"}},{"type":"tool_use","id":"toolu_01Aaqj3LMXksE1nB3pscRhV5","name":"parallel_local_search_two","input":{"query":"latest
Anthropic model release notes"},"caller":{"type":"direct"}},{"type":"tool_use","id":"toolu_01AcYxQvy8aYmAoUg9zx9qfq","name":"parallel_local_search_three","input":{"query":"latest
Gemini model release notes"},"caller":{"type":"direct"}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":951,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":170,"service_tier":"standard","inference_geo":"global"}}'
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Security-Policy:
- CSP-FILTERED
Content-Type:
- application/json
Date:
- Wed, 18 Feb 2026 23:54:51 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Robots-Tag:
- none
anthropic-organization-id:
- ANTHROPIC-ORGANIZATION-ID-XXX
anthropic-ratelimit-input-tokens-limit:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-LIMIT-XXX
anthropic-ratelimit-input-tokens-remaining:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-REMAINING-XXX
anthropic-ratelimit-input-tokens-reset:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-RESET-XXX
anthropic-ratelimit-output-tokens-limit:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-LIMIT-XXX
anthropic-ratelimit-output-tokens-remaining:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-REMAINING-XXX
anthropic-ratelimit-output-tokens-reset:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-RESET-XXX
anthropic-ratelimit-requests-limit:
- '20000'
anthropic-ratelimit-requests-remaining:
- '19999'
anthropic-ratelimit-requests-reset:
- '2026-02-18T23:54:49Z'
anthropic-ratelimit-tokens-limit:
- ANTHROPIC-RATELIMIT-TOKENS-LIMIT-XXX
anthropic-ratelimit-tokens-remaining:
- ANTHROPIC-RATELIMIT-TOKENS-REMAINING-XXX
anthropic-ratelimit-tokens-reset:
- ANTHROPIC-RATELIMIT-TOKENS-RESET-XXX
cf-cache-status:
- DYNAMIC
request-id:
- REQUEST-ID-XXX
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '1967'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"\nCurrent Task:
This is a tool-calling compliance test. In your next assistant turn, emit exactly
3 tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."},{"role":"assistant","content":[{"type":"tool_use","id":"toolu_01YWY3cSomRuv4USmq55Prk3","name":"parallel_local_search_one","input":{"query":"latest
OpenAI model release notes"}},{"type":"tool_use","id":"toolu_01Aaqj3LMXksE1nB3pscRhV5","name":"parallel_local_search_two","input":{"query":"latest
Anthropic model release notes"}},{"type":"tool_use","id":"toolu_01AcYxQvy8aYmAoUg9zx9qfq","name":"parallel_local_search_three","input":{"query":"latest
Gemini model release notes"}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_01YWY3cSomRuv4USmq55Prk3","content":"[one]
latest OpenAI model release notes"},{"type":"tool_result","tool_use_id":"toolu_01Aaqj3LMXksE1nB3pscRhV5","content":"[two]
latest Anthropic model release notes"},{"type":"tool_result","tool_use_id":"toolu_01AcYxQvy8aYmAoUg9zx9qfq","content":"[three]
latest Gemini model release notes"}]},{"role":"user","content":"Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}],"model":"claude-sonnet-4-6","stop_sequences":["\nObservation:"],"stream":false,"system":"You
are Parallel Tool Agent. You follow tool instructions precisely.\nYour personal
goal is: Use both tools exactly as instructed","tools":[{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}},{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}},{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","input_schema":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '2882'
content-type:
- application/json
host:
- api.anthropic.com
x-api-key:
- X-API-KEY-XXX
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.73.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: "{\"model\":\"claude-sonnet-4-6\",\"id\":\"msg_0143MHUne1az3Tt69EoLjyZd\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[{\"type\":\"text\",\"text\":\"Here
is the complete content returned from all three tool calls:\\n\\n- **parallel_local_search_one**
result: `[one] latest OpenAI model release notes`\\n- **parallel_local_search_two**
result: `[two] latest Anthropic model release notes`\\n- **parallel_local_search_three**
result: `[three] latest Gemini model release notes`\\n\\nAll three parallel
tool calls were executed successfully in the same response turn, returning
their respective outputs: the first tool searched for the latest OpenAI model
release notes, the second tool searched for the latest Anthropic model release
notes, and the third tool searched for the latest Gemini model release notes
\u2014 confirming that all search queries were dispatched concurrently and
their results retrieved as expected.\"}],\"stop_reason\":\"end_turn\",\"stop_sequence\":null,\"usage\":{\"input_tokens\":1272,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":172,\"service_tier\":\"standard\",\"inference_geo\":\"global\"}}"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Security-Policy:
- CSP-FILTERED
Content-Type:
- application/json
Date:
- Wed, 18 Feb 2026 23:54:55 GMT
Server:
- cloudflare
Transfer-Encoding:
- chunked
X-Robots-Tag:
- none
anthropic-organization-id:
- ANTHROPIC-ORGANIZATION-ID-XXX
anthropic-ratelimit-input-tokens-limit:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-LIMIT-XXX
anthropic-ratelimit-input-tokens-remaining:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-REMAINING-XXX
anthropic-ratelimit-input-tokens-reset:
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-RESET-XXX
anthropic-ratelimit-output-tokens-limit:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-LIMIT-XXX
anthropic-ratelimit-output-tokens-remaining:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-REMAINING-XXX
anthropic-ratelimit-output-tokens-reset:
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-RESET-XXX
anthropic-ratelimit-requests-limit:
- '20000'
anthropic-ratelimit-requests-remaining:
- '19999'
anthropic-ratelimit-requests-reset:
- '2026-02-18T23:54:52Z'
anthropic-ratelimit-tokens-limit:
- ANTHROPIC-RATELIMIT-TOKENS-LIMIT-XXX
anthropic-ratelimit-tokens-remaining:
- ANTHROPIC-RATELIMIT-TOKENS-REMAINING-XXX
anthropic-ratelimit-tokens-reset:
- ANTHROPIC-RATELIMIT-TOKENS-RESET-XXX
cf-cache-status:
- DYNAMIC
request-id:
- REQUEST-ID-XXX
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '3144'
status:
code: 200
message: OK
version: 1

View File

@@ -5,20 +5,19 @@ interactions:
calculations"}, {"role": "user", "content": "\nCurrent Task: Calculate what
is 15 * 8\n\nThis is the expected criteria for your final answer: The result
of the calculation\nyou MUST return the actual complete content as the final
answer, not a summary.\n\nThis is VERY important to you, your job depends on
it!"}], "stream": false, "stop": ["\nObservation:"], "tool_choice": "auto",
"tools": [{"function": {"name": "calculator", "description": "Perform mathematical
calculations. Use this for any math operations.", "parameters": {"properties":
{"expression": {"description": "Mathematical expression to evaluate", "title":
"Expression", "type": "string"}}, "required": ["expression"], "type": "object"}},
"type": "function"}]}'
answer, not a summary."}], "stream": false, "tool_choice": "auto", "tools":
[{"function": {"name": "calculator", "description": "Perform mathematical calculations.
Use this for any math operations.", "parameters": {"properties": {"expression":
{"description": "Mathematical expression to evaluate", "title": "Expression",
"type": "string"}}, "required": ["expression"], "type": "object", "additionalProperties":
false}}, "type": "function"}]}'
headers:
Accept:
- application/json
Connection:
- keep-alive
Content-Length:
- '883'
- '828'
Content-Type:
- application/json
User-Agent:
@@ -32,20 +31,20 @@ interactions:
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
method: POST
uri: https://fake-azure-endpoint.openai.azure.com/openai/deployments/gpt-4o-mini/chat/completions?api-version=2024-12-01-preview
uri: https://fake-azure-endpoint.openai.azure.com/openai/deployments/gpt-5-nano/chat/completions?api-version=2024-12-01-preview
response:
body:
string: '{"choices":[{"content_filter_results":{},"finish_reason":"tool_calls","index":0,"logprobs":null,"message":{"annotations":[],"content":null,"refusal":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"expression\":\"15
* 8\"}","name":"calculator"},"id":"call_cJWzKh5LdBpY3Sk8GATS3eRe","type":"function"}]}}],"created":1769122114,"id":"chatcmpl-D0xlavS0V3m00B9Fsjyv39xQWUGFV","model":"gpt-4o-mini-2024-07-18","object":"chat.completion","prompt_filter_results":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"jailbreak":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"system_fingerprint":"fp_f97eff32c5","usage":{"completion_tokens":18,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":137,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":155}}
* 8\"}","name":"calculator"},"id":"call_Cow46pNllpDx0pxUgZFeqlh1","type":"function"}]}}],"created":1771459544,"id":"chatcmpl-DAlq4osCP9ABJ1HyXFBoYWylMg0bi","model":"gpt-5-nano-2025-08-07","object":"chat.completion","prompt_filter_results":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"jailbreak":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"system_fingerprint":null,"usage":{"completion_tokens":219,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":192,"rejected_prediction_tokens":0},"prompt_tokens":208,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":427}}
'
headers:
Content-Length:
- '1058'
- '1049'
Content-Type:
- application/json
Date:
- Thu, 22 Jan 2026 22:48:34 GMT
- Thu, 19 Feb 2026 00:05:45 GMT
Strict-Transport-Security:
- STS-XXX
apim-request-id:
@@ -59,7 +58,7 @@ interactions:
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
x-ms-deployment-name:
- gpt-4o-mini
- gpt-5-nano
x-ms-rai-invoked:
- 'true'
x-ms-region:
@@ -83,26 +82,25 @@ interactions:
calculations"}, {"role": "user", "content": "\nCurrent Task: Calculate what
is 15 * 8\n\nThis is the expected criteria for your final answer: The result
of the calculation\nyou MUST return the actual complete content as the final
answer, not a summary.\n\nThis is VERY important to you, your job depends on
it!"}, {"role": "assistant", "content": "", "tool_calls": [{"id": "call_cJWzKh5LdBpY3Sk8GATS3eRe",
"type": "function", "function": {"name": "calculator", "arguments": "{\"expression\":\"15
* 8\"}"}}]}, {"role": "tool", "tool_call_id": "call_cJWzKh5LdBpY3Sk8GATS3eRe",
"content": "The result of 15 * 8 is 120"}, {"role": "user", "content": "Analyze
the tool result. If requirements are met, provide the Final Answer. Otherwise,
call the next tool. Deliver only the answer without meta-commentary."}], "stream":
false, "stop": ["\nObservation:"], "tool_choice": "auto", "tools": [{"function":
{"name": "calculator", "description": "Perform mathematical calculations. Use
this for any math operations.", "parameters": {"properties": {"expression":
{"description": "Mathematical expression to evaluate", "title": "Expression",
"type": "string"}}, "required": ["expression"], "type": "object"}}, "type":
"function"}]}'
answer, not a summary."}, {"role": "assistant", "content": "", "tool_calls":
[{"id": "call_Cow46pNllpDx0pxUgZFeqlh1", "type": "function", "function": {"name":
"calculator", "arguments": "{\"expression\":\"15 * 8\"}"}}]}, {"role": "tool",
"tool_call_id": "call_Cow46pNllpDx0pxUgZFeqlh1", "content": "The result of 15
* 8 is 120"}, {"role": "user", "content": "Analyze the tool result. If requirements
are met, provide the Final Answer. Otherwise, call the next tool. Deliver only
the answer without meta-commentary."}], "stream": false, "tool_choice": "auto",
"tools": [{"function": {"name": "calculator", "description": "Perform mathematical
calculations. Use this for any math operations.", "parameters": {"properties":
{"expression": {"description": "Mathematical expression to evaluate", "title":
"Expression", "type": "string"}}, "required": ["expression"], "type": "object",
"additionalProperties": false}}, "type": "function"}]}'
headers:
Accept:
- application/json
Connection:
- keep-alive
Content-Length:
- '1375'
- '1320'
Content-Type:
- application/json
User-Agent:
@@ -116,20 +114,19 @@ interactions:
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
method: POST
uri: https://fake-azure-endpoint.openai.azure.com/openai/deployments/gpt-4o-mini/chat/completions?api-version=2024-12-01-preview
uri: https://fake-azure-endpoint.openai.azure.com/openai/deployments/gpt-5-nano/chat/completions?api-version=2024-12-01-preview
response:
body:
string: '{"choices":[{"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"protected_material_code":{"filtered":false,"detected":false},"protected_material_text":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}},"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"The
result of the calculation is 120.","refusal":null,"role":"assistant"}}],"created":1769122115,"id":"chatcmpl-D0xlbUNVA7RVkn0GsuBGoNhgQTtac","model":"gpt-4o-mini-2024-07-18","object":"chat.completion","prompt_filter_results":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"jailbreak":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"system_fingerprint":"fp_f97eff32c5","usage":{"completion_tokens":11,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":207,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":218}}
string: '{"choices":[{"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"protected_material_code":{"filtered":false,"detected":false},"protected_material_text":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}},"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"120","refusal":null,"role":"assistant"}}],"created":1771459547,"id":"chatcmpl-DAlq7zJimnIMoXieNww8jY5f2pIPd","model":"gpt-5-nano-2025-08-07","object":"chat.completion","prompt_filter_results":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"jailbreak":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"system_fingerprint":null,"usage":{"completion_tokens":203,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":192,"rejected_prediction_tokens":0},"prompt_tokens":284,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":487}}
'
headers:
Content-Length:
- '1250'
- '1207'
Content-Type:
- application/json
Date:
- Thu, 22 Jan 2026 22:48:34 GMT
- Thu, 19 Feb 2026 00:05:49 GMT
Strict-Transport-Security:
- STS-XXX
apim-request-id:
@@ -143,7 +140,7 @@ interactions:
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
x-ms-deployment-name:
- gpt-4o-mini
- gpt-5-nano
x-ms-rai-invoked:
- 'true'
x-ms-region:

View File

@@ -0,0 +1,198 @@
interactions:
- request:
body: '{"messages": [{"role": "system", "content": "You are Parallel Tool Agent.
You follow tool instructions precisely.\nYour personal goal is: Use both tools
exactly as instructed"}, {"role": "user", "content": "\nCurrent Task: This is
a tool-calling compliance test. In your next assistant turn, emit exactly 3
tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."}], "stream": false, "tool_choice": "auto", "tools": [{"function":
{"name": "parallel_local_search_one", "description": "Local search tool #1 for
concurrency testing.", "parameters": {"properties": {"query": {"description":
"Search query", "title": "Query", "type": "string"}}, "required": ["query"],
"type": "object", "additionalProperties": false}}, "type": "function"}, {"function":
{"name": "parallel_local_search_two", "description": "Local search tool #2 for
concurrency testing.", "parameters": {"properties": {"query": {"description":
"Search query", "title": "Query", "type": "string"}}, "required": ["query"],
"type": "object", "additionalProperties": false}}, "type": "function"}, {"function":
{"name": "parallel_local_search_three", "description": "Local search tool #3
for concurrency testing.", "parameters": {"properties": {"query": {"description":
"Search query", "title": "Query", "type": "string"}}, "required": ["query"],
"type": "object", "additionalProperties": false}}, "type": "function"}]}'
headers:
Accept:
- application/json
Connection:
- keep-alive
Content-Length:
- '1763'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
api-key:
- X-API-KEY-XXX
authorization:
- AUTHORIZATION-XXX
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
method: POST
uri: https://fake-azure-endpoint.openai.azure.com/openai/deployments/gpt-5-nano/chat/completions?api-version=2024-12-01-preview
response:
body:
string: '{"choices":[{"content_filter_results":{},"finish_reason":"tool_calls","index":0,"logprobs":null,"message":{"annotations":[],"content":null,"refusal":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"query\":
\"latest OpenAI model release notes\"}","name":"parallel_local_search_one"},"id":"call_emQmocGydKuxvESfQopNngdm","type":"function"},{"function":{"arguments":"{\"query\":
\"latest Anthropic model release notes\"}","name":"parallel_local_search_two"},"id":"call_eNpK9WUYFCX2ZEUPhYCKvdMs","type":"function"},{"function":{"arguments":"{\"query\":
\"latest Gemini model release notes\"}","name":"parallel_local_search_three"},"id":"call_Wdtl6jFxGehSUMn5I1O4Mrdx","type":"function"}]}}],"created":1771459550,"id":"chatcmpl-DAlqAyJGnQKDkNCaTcjU2T8BeJaXM","model":"gpt-5-nano-2025-08-07","object":"chat.completion","prompt_filter_results":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"jailbreak":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"system_fingerprint":null,"usage":{"completion_tokens":666,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":576,"rejected_prediction_tokens":0},"prompt_tokens":343,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":1009}}
'
headers:
Content-Length:
- '1433'
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 00:05:55 GMT
Strict-Transport-Security:
- STS-XXX
apim-request-id:
- APIM-REQUEST-ID-XXX
azureml-model-session:
- AZUREML-MODEL-SESSION-XXX
x-accel-buffering:
- 'no'
x-content-type-options:
- X-CONTENT-TYPE-XXX
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
x-ms-deployment-name:
- gpt-5-nano
x-ms-rai-invoked:
- 'true'
x-ms-region:
- X-MS-REGION-XXX
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
- request:
body: '{"messages": [{"role": "system", "content": "You are Parallel Tool Agent.
You follow tool instructions precisely.\nYour personal goal is: Use both tools
exactly as instructed"}, {"role": "user", "content": "\nCurrent Task: This is
a tool-calling compliance test. In your next assistant turn, emit exactly 3
tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."}, {"role": "assistant", "content": "", "tool_calls": [{"id":
"call_emQmocGydKuxvESfQopNngdm", "type": "function", "function": {"name": "parallel_local_search_one",
"arguments": "{\"query\": \"latest OpenAI model release notes\"}"}}, {"id":
"call_eNpK9WUYFCX2ZEUPhYCKvdMs", "type": "function", "function": {"name": "parallel_local_search_two",
"arguments": "{\"query\": \"latest Anthropic model release notes\"}"}}, {"id":
"call_Wdtl6jFxGehSUMn5I1O4Mrdx", "type": "function", "function": {"name": "parallel_local_search_three",
"arguments": "{\"query\": \"latest Gemini model release notes\"}"}}]}, {"role":
"tool", "tool_call_id": "call_emQmocGydKuxvESfQopNngdm", "content": "[one] latest
OpenAI model release notes"}, {"role": "tool", "tool_call_id": "call_eNpK9WUYFCX2ZEUPhYCKvdMs",
"content": "[two] latest Anthropic model release notes"}, {"role": "tool", "tool_call_id":
"call_Wdtl6jFxGehSUMn5I1O4Mrdx", "content": "[three] latest Gemini model release
notes"}], "stream": false, "tool_choice": "auto", "tools": [{"function": {"name":
"parallel_local_search_one", "description": "Local search tool #1 for concurrency
testing.", "parameters": {"properties": {"query": {"description": "Search query",
"title": "Query", "type": "string"}}, "required": ["query"], "type": "object",
"additionalProperties": false}}, "type": "function"}, {"function": {"name":
"parallel_local_search_two", "description": "Local search tool #2 for concurrency
testing.", "parameters": {"properties": {"query": {"description": "Search query",
"title": "Query", "type": "string"}}, "required": ["query"], "type": "object",
"additionalProperties": false}}, "type": "function"}, {"function": {"name":
"parallel_local_search_three", "description": "Local search tool #3 for concurrency
testing.", "parameters": {"properties": {"query": {"description": "Search query",
"title": "Query", "type": "string"}}, "required": ["query"], "type": "object",
"additionalProperties": false}}, "type": "function"}]}'
headers:
Accept:
- application/json
Connection:
- keep-alive
Content-Length:
- '2727'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
api-key:
- X-API-KEY-XXX
authorization:
- AUTHORIZATION-XXX
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
method: POST
uri: https://fake-azure-endpoint.openai.azure.com/openai/deployments/gpt-5-nano/chat/completions?api-version=2024-12-01-preview
response:
body:
string: '{"choices":[{"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"protected_material_code":{"filtered":false,"detected":false},"protected_material_text":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}},"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"The
latest release notes have been published for the OpenAI, Anthropic, and Gemini
models, signaling concurrent updates across the leading AI model families.
Each set outlines new capabilities and performance improvements, along with
changes to APIs, tooling, and deployment guidelines. Users should review the
individual notes to understand new features, adjustments to tokenization,
latency or throughput, safety and alignment enhancements, pricing or access
changes, and any breaking changes or migration steps required to adopt the
updated models in existing workflows.","refusal":null,"role":"assistant"}}],"created":1771459556,"id":"chatcmpl-DAlqGKWXfGNlTIbDY9F6oHQp6hbxM","model":"gpt-5-nano-2025-08-07","object":"chat.completion","prompt_filter_results":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"jailbreak":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"system_fingerprint":null,"usage":{"completion_tokens":747,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":640,"rejected_prediction_tokens":0},"prompt_tokens":467,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":1214}}
'
headers:
Content-Length:
- '1778'
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 00:06:02 GMT
Strict-Transport-Security:
- STS-XXX
apim-request-id:
- APIM-REQUEST-ID-XXX
azureml-model-session:
- AZUREML-MODEL-SESSION-XXX
x-accel-buffering:
- 'no'
x-content-type-options:
- X-CONTENT-TYPE-XXX
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
x-ms-deployment-name:
- gpt-5-nano
x-ms-rai-invoked:
- 'true'
x-ms-region:
- X-MS-REGION-XXX
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,201 @@
interactions:
- request:
body: '{"messages": [{"role": "system", "content": "You are Parallel Tool Agent.
You follow tool instructions precisely.\nYour personal goal is: Use both tools
exactly as instructed"}, {"role": "user", "content": "\nCurrent Task: This is
a tool-calling compliance test. In your next assistant turn, emit exactly 3
tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}], "stream": false, "tool_choice":
"auto", "tools": [{"function": {"name": "parallel_local_search_one", "description":
"Local search tool #1 for concurrency testing.", "parameters": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}, "type":
"function"}, {"function": {"name": "parallel_local_search_two", "description":
"Local search tool #2 for concurrency testing.", "parameters": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}, "type":
"function"}, {"function": {"name": "parallel_local_search_three", "description":
"Local search tool #3 for concurrency testing.", "parameters": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}, "type":
"function"}]}'
headers:
Accept:
- application/json
Connection:
- keep-alive
Content-Length:
- '1944'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
api-key:
- X-API-KEY-XXX
authorization:
- AUTHORIZATION-XXX
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
method: POST
uri: https://fake-azure-endpoint.openai.azure.com/openai/deployments/gpt-5-nano/chat/completions?api-version=2024-12-01-preview
response:
body:
string: '{"choices":[{"content_filter_results":{},"finish_reason":"tool_calls","index":0,"logprobs":null,"message":{"annotations":[],"content":null,"refusal":null,"role":"assistant","tool_calls":[{"function":{"arguments":"{\"query\":
\"latest OpenAI model release notes\"}","name":"parallel_local_search_one"},"id":"call_NEvGoF86nhPQfXRoJd5SOyLd","type":"function"},{"function":{"arguments":"{\"query\":
\"latest Anthropic model release notes\"}","name":"parallel_local_search_two"},"id":"call_q8Q2du4gAMQLrGTgWgfwfbDZ","type":"function"},{"function":{"arguments":"{\"query\":
\"latest Gemini model release notes\"}","name":"parallel_local_search_three"},"id":"call_yTBal9ofZzuo10j0pWqhHCSj","type":"function"}]}}],"created":1771459563,"id":"chatcmpl-DAlqN7kyC5ACI5Yl1Pj63rOH5HIvI","model":"gpt-5-nano-2025-08-07","object":"chat.completion","prompt_filter_results":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"jailbreak":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"system_fingerprint":null,"usage":{"completion_tokens":2457,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":2368,"rejected_prediction_tokens":0},"prompt_tokens":378,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":2835}}
'
headers:
Content-Length:
- '1435'
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 00:06:17 GMT
Strict-Transport-Security:
- STS-XXX
apim-request-id:
- APIM-REQUEST-ID-XXX
azureml-model-session:
- AZUREML-MODEL-SESSION-XXX
x-accel-buffering:
- 'no'
x-content-type-options:
- X-CONTENT-TYPE-XXX
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
x-ms-deployment-name:
- gpt-5-nano
x-ms-rai-invoked:
- 'true'
x-ms-region:
- X-MS-REGION-XXX
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
- request:
body: '{"messages": [{"role": "system", "content": "You are Parallel Tool Agent.
You follow tool instructions precisely.\nYour personal goal is: Use both tools
exactly as instructed"}, {"role": "user", "content": "\nCurrent Task: This is
a tool-calling compliance test. In your next assistant turn, emit exactly 3
tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}, {"role": "assistant", "content":
"", "tool_calls": [{"id": "call_NEvGoF86nhPQfXRoJd5SOyLd", "type": "function",
"function": {"name": "parallel_local_search_one", "arguments": "{\"query\":
\"latest OpenAI model release notes\"}"}}, {"id": "call_q8Q2du4gAMQLrGTgWgfwfbDZ",
"type": "function", "function": {"name": "parallel_local_search_two", "arguments":
"{\"query\": \"latest Anthropic model release notes\"}"}}, {"id": "call_yTBal9ofZzuo10j0pWqhHCSj",
"type": "function", "function": {"name": "parallel_local_search_three", "arguments":
"{\"query\": \"latest Gemini model release notes\"}"}}]}, {"role": "tool", "tool_call_id":
"call_NEvGoF86nhPQfXRoJd5SOyLd", "content": "[one] latest OpenAI model release
notes"}, {"role": "tool", "tool_call_id": "call_q8Q2du4gAMQLrGTgWgfwfbDZ", "content":
"[two] latest Anthropic model release notes"}, {"role": "tool", "tool_call_id":
"call_yTBal9ofZzuo10j0pWqhHCSj", "content": "[three] latest Gemini model release
notes"}, {"role": "user", "content": "Analyze the tool result. If requirements
are met, provide the Final Answer. Otherwise, call the next tool. Deliver only
the answer without meta-commentary."}], "stream": false, "tool_choice": "auto",
"tools": [{"function": {"name": "parallel_local_search_one", "description":
"Local search tool #1 for concurrency testing.", "parameters": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}, "type":
"function"}, {"function": {"name": "parallel_local_search_two", "description":
"Local search tool #2 for concurrency testing.", "parameters": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}, "type":
"function"}, {"function": {"name": "parallel_local_search_three", "description":
"Local search tool #3 for concurrency testing.", "parameters": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}, "type":
"function"}]}'
headers:
Accept:
- application/json
Connection:
- keep-alive
Content-Length:
- '3096'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
api-key:
- X-API-KEY-XXX
authorization:
- AUTHORIZATION-XXX
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
method: POST
uri: https://fake-azure-endpoint.openai.azure.com/openai/deployments/gpt-5-nano/chat/completions?api-version=2024-12-01-preview
response:
body:
string: '{"choices":[{"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"protected_material_code":{"filtered":false,"detected":false},"protected_material_text":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}},"finish_reason":"stop","index":0,"logprobs":null,"message":{"annotations":[],"content":"The
three tool results indicate the latest release notes are available for OpenAI
models, Anthropic models, and Gemini models.","refusal":null,"role":"assistant"}}],"created":1771459579,"id":"chatcmpl-DAlqdRtr8EefmFfazuh4jm7KvVxim","model":"gpt-5-nano-2025-08-07","object":"chat.completion","prompt_filter_results":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"jailbreak":{"filtered":false,"detected":false},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"system_fingerprint":null,"usage":{"completion_tokens":1826,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":1792,"rejected_prediction_tokens":0},"prompt_tokens":537,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":2363}}
'
headers:
Content-Length:
- '1333'
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 00:06:31 GMT
Strict-Transport-Security:
- STS-XXX
apim-request-id:
- APIM-REQUEST-ID-XXX
azureml-model-session:
- AZUREML-MODEL-SESSION-XXX
x-accel-buffering:
- 'no'
x-content-type-options:
- X-CONTENT-TYPE-XXX
x-ms-client-request-id:
- X-MS-CLIENT-REQUEST-ID-XXX
x-ms-deployment-name:
- gpt-5-nano
x-ms-rai-invoked:
- 'true'
x-ms-region:
- X-MS-REGION-XXX
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,63 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "\nCurrent Task: This
is a tool-calling compliance test. In your next assistant turn, emit exactly
3 tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."}]}], "inferenceConfig": {"stopSequences": ["\nObservation:"]},
"system": [{"text": "You are Parallel Tool Agent. You follow tool instructions
precisely.\nYour personal goal is: Use both tools exactly as instructed"}],
"toolConfig": {"tools": [{"toolSpec": {"name": "parallel_local_search_one",
"description": "Local search tool #1 for concurrency testing.", "inputSchema":
{"json": {"properties": {"query": {"description": "Search query", "title": "Query",
"type": "string"}}, "required": ["query"], "type": "object", "additionalProperties":
false}}}}, {"toolSpec": {"name": "parallel_local_search_two", "description":
"Local search tool #2 for concurrency testing.", "inputSchema": {"json": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}}},
{"toolSpec": {"name": "parallel_local_search_three", "description": "Local search
tool #3 for concurrency testing.", "inputSchema": {"json": {"properties": {"query":
{"description": "Search query", "title": "Query", "type": "string"}}, "required":
["query"], "type": "object", "additionalProperties": false}}}}]}}'
headers:
Content-Length:
- '1773'
Content-Type:
- !!binary |
YXBwbGljYXRpb24vanNvbg==
User-Agent:
- X-USER-AGENT-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- !!binary |
YXR0ZW1wdD0x
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-3-haiku-20240307-v1%3A0/converse
response:
body:
string: '{"message":"The security token included in the request is invalid."}'
headers:
Connection:
- keep-alive
Content-Length:
- '68'
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 00:00:08 GMT
x-amzn-ErrorType:
- UnrecognizedClientException:http://internal.amazon.com/coral/com.amazon.coral.service/
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 403
message: Forbidden
version: 1

View File

@@ -0,0 +1,226 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "\nCurrent Task: This
is a tool-calling compliance test. In your next assistant turn, emit exactly
3 tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}]}], "inferenceConfig": {"stopSequences":
["\nObservation:"]}, "system": [{"text": "You are Parallel Tool Agent. You follow
tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed"}], "toolConfig": {"tools": [{"toolSpec": {"name": "parallel_local_search_one",
"description": "Local search tool #1 for concurrency testing.", "inputSchema":
{"json": {"properties": {"query": {"description": "Search query", "title": "Query",
"type": "string"}}, "required": ["query"], "type": "object", "additionalProperties":
false}}}}, {"toolSpec": {"name": "parallel_local_search_two", "description":
"Local search tool #2 for concurrency testing.", "inputSchema": {"json": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}}},
{"toolSpec": {"name": "parallel_local_search_three", "description": "Local search
tool #3 for concurrency testing.", "inputSchema": {"json": {"properties": {"query":
{"description": "Search query", "title": "Query", "type": "string"}}, "required":
["query"], "type": "object", "additionalProperties": false}}}}]}}'
headers:
Content-Length:
- '1954'
Content-Type:
- !!binary |
YXBwbGljYXRpb24vanNvbg==
User-Agent:
- X-USER-AGENT-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- !!binary |
YXR0ZW1wdD0x
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-3-haiku-20240307-v1%3A0/converse
response:
body:
string: '{"message":"The security token included in the request is invalid."}'
headers:
Connection:
- keep-alive
Content-Length:
- '68'
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 00:00:07 GMT
x-amzn-ErrorType:
- UnrecognizedClientException:http://internal.amazon.com/coral/com.amazon.coral.service/
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 403
message: Forbidden
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "\nCurrent Task: This
is a tool-calling compliance test. In your next assistant turn, emit exactly
3 tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}]}, {"role": "user", "content":
[{"text": "\nCurrent Task: This is a tool-calling compliance test. In your next
assistant turn, emit exactly 3 tool calls in the same response (parallel tool
calls), in this order: 1) parallel_local_search_one(query=''latest OpenAI model
release notes''), 2) parallel_local_search_two(query=''latest Anthropic model
release notes''), 3) parallel_local_search_three(query=''latest Gemini model
release notes''). Do not call any other tools and do not answer before those
3 tool calls are emitted. After the tool results return, provide a one paragraph
summary.\n\nThis is the expected criteria for your final answer: A one sentence
summary of both tool outputs\nyou MUST return the actual complete content as
the final answer, not a summary."}]}], "inferenceConfig": {"stopSequences":
["\nObservation:"]}, "system": [{"text": "You are Parallel Tool Agent. You follow
tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed\n\nYou are Parallel Tool Agent. You follow tool instructions precisely.\nYour
personal goal is: Use both tools exactly as instructed"}], "toolConfig": {"tools":
[{"toolSpec": {"name": "parallel_local_search_one", "description": "Local search
tool #1 for concurrency testing.", "inputSchema": {"json": {"properties": {"query":
{"description": "Search query", "title": "Query", "type": "string"}}, "required":
["query"], "type": "object", "additionalProperties": false}}}}, {"toolSpec":
{"name": "parallel_local_search_two", "description": "Local search tool #2 for
concurrency testing.", "inputSchema": {"json": {"properties": {"query": {"description":
"Search query", "title": "Query", "type": "string"}}, "required": ["query"],
"type": "object", "additionalProperties": false}}}}, {"toolSpec": {"name": "parallel_local_search_three",
"description": "Local search tool #3 for concurrency testing.", "inputSchema":
{"json": {"properties": {"query": {"description": "Search query", "title": "Query",
"type": "string"}}, "required": ["query"], "type": "object", "additionalProperties":
false}}}}]}}'
headers:
Content-Length:
- '2855'
Content-Type:
- !!binary |
YXBwbGljYXRpb24vanNvbg==
User-Agent:
- X-USER-AGENT-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- !!binary |
YXR0ZW1wdD0x
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-3-haiku-20240307-v1%3A0/converse
response:
body:
string: '{"message":"The security token included in the request is invalid."}'
headers:
Connection:
- keep-alive
Content-Length:
- '68'
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 00:00:07 GMT
x-amzn-ErrorType:
- UnrecognizedClientException:http://internal.amazon.com/coral/com.amazon.coral.service/
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 403
message: Forbidden
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "\nCurrent Task: This
is a tool-calling compliance test. In your next assistant turn, emit exactly
3 tool calls in the same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}]}, {"role": "user", "content":
[{"text": "\nCurrent Task: This is a tool-calling compliance test. In your next
assistant turn, emit exactly 3 tool calls in the same response (parallel tool
calls), in this order: 1) parallel_local_search_one(query=''latest OpenAI model
release notes''), 2) parallel_local_search_two(query=''latest Anthropic model
release notes''), 3) parallel_local_search_three(query=''latest Gemini model
release notes''). Do not call any other tools and do not answer before those
3 tool calls are emitted. After the tool results return, provide a one paragraph
summary.\n\nThis is the expected criteria for your final answer: A one sentence
summary of both tool outputs\nyou MUST return the actual complete content as
the final answer, not a summary."}]}, {"role": "user", "content": [{"text":
"\nCurrent Task: This is a tool-calling compliance test. In your next assistant
turn, emit exactly 3 tool calls in the same response (parallel tool calls),
in this order: 1) parallel_local_search_one(query=''latest OpenAI model release
notes''), 2) parallel_local_search_two(query=''latest Anthropic model release
notes''), 3) parallel_local_search_three(query=''latest Gemini model release
notes''). Do not call any other tools and do not answer before those 3 tool
calls are emitted. After the tool results return, provide a one paragraph summary.\n\nThis
is the expected criteria for your final answer: A one sentence summary of both
tool outputs\nyou MUST return the actual complete content as the final answer,
not a summary."}]}], "inferenceConfig": {"stopSequences": ["\nObservation:"]},
"system": [{"text": "You are Parallel Tool Agent. You follow tool instructions
precisely.\nYour personal goal is: Use both tools exactly as instructed\n\nYou
are Parallel Tool Agent. You follow tool instructions precisely.\nYour personal
goal is: Use both tools exactly as instructed\n\nYou are Parallel Tool Agent.
You follow tool instructions precisely.\nYour personal goal is: Use both tools
exactly as instructed"}], "toolConfig": {"tools": [{"toolSpec": {"name": "parallel_local_search_one",
"description": "Local search tool #1 for concurrency testing.", "inputSchema":
{"json": {"properties": {"query": {"description": "Search query", "title": "Query",
"type": "string"}}, "required": ["query"], "type": "object", "additionalProperties":
false}}}}, {"toolSpec": {"name": "parallel_local_search_two", "description":
"Local search tool #2 for concurrency testing.", "inputSchema": {"json": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}}},
{"toolSpec": {"name": "parallel_local_search_three", "description": "Local search
tool #3 for concurrency testing.", "inputSchema": {"json": {"properties": {"query":
{"description": "Search query", "title": "Query", "type": "string"}}, "required":
["query"], "type": "object", "additionalProperties": false}}}}]}}'
headers:
Content-Length:
- '3756'
Content-Type:
- !!binary |
YXBwbGljYXRpb24vanNvbg==
User-Agent:
- X-USER-AGENT-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- !!binary |
YXR0ZW1wdD0x
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/anthropic.claude-3-haiku-20240307-v1%3A0/converse
response:
body:
string: '{"message":"The security token included in the request is invalid."}'
headers:
Connection:
- keep-alive
Content-Length:
- '68'
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 00:00:07 GMT
x-amzn-ErrorType:
- UnrecognizedClientException:http://internal.amazon.com/coral/com.amazon.coral.service/
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 403
message: Forbidden
version: 1

View File

@@ -3,14 +3,14 @@ interactions:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: Calculate what is 15
* 8\n\nThis is the expected criteria for your final answer: The result of the
calculation\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nThis is VERY important to you, your job depends on it!"}],
"role": "user"}], "systemInstruction": {"parts": [{"text": "You are Math Assistant.
You are a helpful math assistant.\nYour personal goal is: Help users with mathematical
calculations"}], "role": "user"}, "tools": [{"functionDeclarations": [{"description":
"Perform mathematical calculations. Use this for any math operations.", "name":
"calculator", "parameters": {"properties": {"expression": {"description": "Mathematical
expression to evaluate", "title": "Expression", "type": "STRING"}}, "required":
["expression"], "type": "OBJECT"}}]}], "generationConfig": {"stopSequences":
not a summary."}], "role": "user"}], "systemInstruction": {"parts": [{"text":
"You are Math Assistant. You are a helpful math assistant.\nYour personal goal
is: Help users with mathematical calculations"}], "role": "user"}, "tools":
[{"functionDeclarations": [{"description": "Perform mathematical calculations.
Use this for any math operations.", "name": "calculator", "parameters_json_schema":
{"properties": {"expression": {"description": "Mathematical expression to evaluate",
"title": "Expression", "type": "string"}}, "required": ["expression"], "type":
"object", "additionalProperties": false}}]}], "generationConfig": {"stopSequences":
["\nObservation:"]}}'
headers:
User-Agent:
@@ -22,7 +22,7 @@ interactions:
connection:
- keep-alive
content-length:
- '907'
- '892'
content-type:
- application/json
host:
@@ -32,31 +32,31 @@ interactions:
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"functionCall\": {\n \"name\": \"calculator\",\n
\ \"args\": {\n \"expression\": \"15 * 8\"\n }\n
\ }\n }\n ],\n \"role\": \"model\"\n },\n
\ \"finishReason\": \"STOP\",\n \"avgLogprobs\": -0.00062879999833447594\n
\ }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\": 103,\n \"candidatesTokenCount\":
7,\n \"totalTokenCount\": 110,\n \"promptTokensDetails\": [\n {\n
\ \"modality\": \"TEXT\",\n \"tokenCount\": 103\n }\n ],\n
\ \"candidatesTokensDetails\": [\n {\n \"modality\": \"TEXT\",\n
\ \"tokenCount\": 7\n }\n ]\n },\n \"modelVersion\": \"gemini-2.0-flash-exp\",\n
\ \"responseId\": \"PpByabfUHsih_uMPlu2ysAM\"\n}\n"
\ },\n \"thoughtSignature\": \"Cp8DAb4+9vu74rJ0QQNTa6oMMh3QAlvx3cS4TL0I1od7EdQZtMBbsr5viQiTUR/LKj8nwPvtLjZxib5SXqmV0t2B2ZMdq1nqD62vLPD3i7tmUeRoysODfxomRGRhy/CPysMhobt5HWF1W/n6tNiQz3V36f0/dRx5yJeyN4tJL/RZePv77FUqywOfFlYOkOIyAkrE5LT6FicOjhHm/B9bGV/y7TNmN6TtwQDxoE9nU92Q/UNZ7rNyZE7aSR7KPJZuRXrrBBh+akt5dX5n6N9kGWkyRpWVgUox01+b22RSj4S/QY45IvadtmmkFk8DMVAtAnEiK0WazltC+TOdUJHwVgBD494fngoVcHU+R1yIJrVe7h6Ce3Ts5IYLrRCedDU3wW1ghn/hXx1nvTqQumpsGTGtE2v3KjF/7DmQA96WzB1X7+QUOF2J3pK9HemiKxAQl4U9fP2eNN8shvy2YykBlahWDujEwye7ji4wIWtNHbf0t+uFwGTQ3QruAKXvWB04ExjHM2I/8O9U5tOsH0cwPqnpFR2EaTqaPXXUllZ2K+DaaA==\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0,\n \"finishMessage\": \"Model generated
function call(s).\"\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
115,\n \"candidatesTokenCount\": 17,\n \"totalTokenCount\": 227,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 115\n
\ }\n ],\n \"thoughtsTokenCount\": 95\n },\n \"modelVersion\":
\"gemini-2.5-flash\",\n \"responseId\": \"Y1KWadvNMKz1jMcPiJeJmAI\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Thu, 22 Jan 2026 21:01:50 GMT
- Wed, 18 Feb 2026 23:59:32 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=521
- gfet4t7; dur=956
Transfer-Encoding:
- chunked
Vary:
@@ -76,18 +76,19 @@ interactions:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: Calculate what is 15
* 8\n\nThis is the expected criteria for your final answer: The result of the
calculation\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nThis is VERY important to you, your job depends on it!"}],
"role": "user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text":
"The result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze
the tool result. If requirements are met, provide the Final Answer. Otherwise,
call the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}], "systemInstruction": {"parts": [{"text": "You are Math Assistant.
You are a helpful math assistant.\nYour personal goal is: Help users with mathematical
calculations"}], "role": "user"}, "tools": [{"functionDeclarations": [{"description":
"Perform mathematical calculations. Use this for any math operations.", "name":
"calculator", "parameters": {"properties": {"expression": {"description": "Mathematical
expression to evaluate", "title": "Expression", "type": "STRING"}}, "required":
["expression"], "type": "OBJECT"}}]}], "generationConfig": {"stopSequences":
not a summary."}], "role": "user"}, {"parts": [{"functionCall": {"args": {"expression":
"15 * 8"}, "name": "calculator"}}], "role": "model"}, {"parts": [{"functionResponse":
{"name": "calculator", "response": {"result": "The result of 15 * 8 is 120"}}}],
"role": "user"}, {"parts": [{"text": "Analyze the tool result. If requirements
are met, provide the Final Answer. Otherwise, call the next tool. Deliver only
the answer without meta-commentary."}], "role": "user"}], "systemInstruction":
{"parts": [{"text": "You are Math Assistant. You are a helpful math assistant.\nYour
personal goal is: Help users with mathematical calculations"}], "role": "user"},
"tools": [{"functionDeclarations": [{"description": "Perform mathematical calculations.
Use this for any math operations.", "name": "calculator", "parameters_json_schema":
{"properties": {"expression": {"description": "Mathematical expression to evaluate",
"title": "Expression", "type": "string"}}, "required": ["expression"], "type":
"object", "additionalProperties": false}}]}], "generationConfig": {"stopSequences":
["\nObservation:"]}}'
headers:
User-Agent:
@@ -99,7 +100,7 @@ interactions:
connection:
- keep-alive
content-length:
- '1219'
- '1326'
content-type:
- application/json
host:
@@ -109,378 +110,28 @@ interactions:
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"functionCall\": {\n \"name\": \"calculator\",\n
\ \"args\": {\n \"expression\": \"15 * 8\"\n }\n
\ }\n }\n ],\n \"role\": \"model\"\n },\n
\ \"finishReason\": \"STOP\",\n \"avgLogprobs\": -0.013549212898526872\n
\ }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\": 149,\n \"candidatesTokenCount\":
7,\n \"totalTokenCount\": 156,\n \"promptTokensDetails\": [\n {\n
\ \"modality\": \"TEXT\",\n \"tokenCount\": 149\n }\n ],\n
\ \"candidatesTokensDetails\": [\n {\n \"modality\": \"TEXT\",\n
\ \"tokenCount\": 7\n }\n ]\n },\n \"modelVersion\": \"gemini-2.0-flash-exp\",\n
\ \"responseId\": \"P5Byadc8kJT-4w_p99XQAQ\"\n}\n"
[\n {\n \"text\": \"The result of 15 * 8 is 120\"\n }\n
\ ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
191,\n \"candidatesTokenCount\": 14,\n \"totalTokenCount\": 205,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 191\n
\ }\n ]\n },\n \"modelVersion\": \"gemini-2.5-flash\",\n \"responseId\":
\"ZFKWaf2BMM6MjMcP6P--kQM\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Thu, 22 Jan 2026 21:01:51 GMT
- Wed, 18 Feb 2026 23:59:33 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=444
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
X-Frame-Options:
- X-FRAME-OPTIONS-XXX
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
- request:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: Calculate what is 15
* 8\n\nThis is the expected criteria for your final answer: The result of the
calculation\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nThis is VERY important to you, your job depends on it!"}],
"role": "user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text":
"The result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze
the tool result. If requirements are met, provide the Final Answer. Otherwise,
call the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}], "systemInstruction": {"parts": [{"text": "You are Math Assistant.
You are a helpful math assistant.\nYour personal goal is: Help users with mathematical
calculations"}], "role": "user"}, "tools": [{"functionDeclarations": [{"description":
"Perform mathematical calculations. Use this for any math operations.", "name":
"calculator", "parameters": {"properties": {"expression": {"description": "Mathematical
expression to evaluate", "title": "Expression", "type": "STRING"}}, "required":
["expression"], "type": "OBJECT"}}]}], "generationConfig": {"stopSequences":
["\nObservation:"]}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- '*/*'
accept-encoding:
- ACCEPT-ENCODING-XXX
connection:
- keep-alive
content-length:
- '1531'
content-type:
- application/json
host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.49.0 gl-python/3.13.3
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"functionCall\": {\n \"name\": \"calculator\",\n
\ \"args\": {\n \"expression\": \"15 * 8\"\n }\n
\ }\n }\n ],\n \"role\": \"model\"\n },\n
\ \"finishReason\": \"STOP\",\n \"avgLogprobs\": -0.0409286447933742\n
\ }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\": 195,\n \"candidatesTokenCount\":
7,\n \"totalTokenCount\": 202,\n \"promptTokensDetails\": [\n {\n
\ \"modality\": \"TEXT\",\n \"tokenCount\": 195\n }\n ],\n
\ \"candidatesTokensDetails\": [\n {\n \"modality\": \"TEXT\",\n
\ \"tokenCount\": 7\n }\n ]\n },\n \"modelVersion\": \"gemini-2.0-flash-exp\",\n
\ \"responseId\": \"P5Byadn5HOK6_uMPnvmXwAk\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Thu, 22 Jan 2026 21:01:51 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=503
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
X-Frame-Options:
- X-FRAME-OPTIONS-XXX
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
- request:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: Calculate what is 15
* 8\n\nThis is the expected criteria for your final answer: The result of the
calculation\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nThis is VERY important to you, your job depends on it!"}],
"role": "user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text":
"The result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze
the tool result. If requirements are met, provide the Final Answer. Otherwise,
call the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}], "systemInstruction": {"parts": [{"text": "You are Math Assistant.
You are a helpful math assistant.\nYour personal goal is: Help users with mathematical
calculations"}], "role": "user"}, "tools": [{"functionDeclarations": [{"description":
"Perform mathematical calculations. Use this for any math operations.", "name":
"calculator", "parameters": {"properties": {"expression": {"description": "Mathematical
expression to evaluate", "title": "Expression", "type": "STRING"}}, "required":
["expression"], "type": "OBJECT"}}]}], "generationConfig": {"stopSequences":
["\nObservation:"]}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- '*/*'
accept-encoding:
- ACCEPT-ENCODING-XXX
connection:
- keep-alive
content-length:
- '1843'
content-type:
- application/json
host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.49.0 gl-python/3.13.3
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"functionCall\": {\n \"name\": \"calculator\",\n
\ \"args\": {\n \"expression\": \"15 * 8\"\n }\n
\ }\n }\n ],\n \"role\": \"model\"\n },\n
\ \"finishReason\": \"STOP\",\n \"avgLogprobs\": -0.018002046006066457\n
\ }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\": 241,\n \"candidatesTokenCount\":
7,\n \"totalTokenCount\": 248,\n \"promptTokensDetails\": [\n {\n
\ \"modality\": \"TEXT\",\n \"tokenCount\": 241\n }\n ],\n
\ \"candidatesTokensDetails\": [\n {\n \"modality\": \"TEXT\",\n
\ \"tokenCount\": 7\n }\n ]\n },\n \"modelVersion\": \"gemini-2.0-flash-exp\",\n
\ \"responseId\": \"P5Byafi2PKbn_uMPtIbfuQI\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Thu, 22 Jan 2026 21:01:52 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=482
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
X-Frame-Options:
- X-FRAME-OPTIONS-XXX
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
- request:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: Calculate what is 15
* 8\n\nThis is the expected criteria for your final answer: The result of the
calculation\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nThis is VERY important to you, your job depends on it!"}],
"role": "user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text":
"The result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze
the tool result. If requirements are met, provide the Final Answer. Otherwise,
call the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}], "systemInstruction": {"parts": [{"text": "You are Math Assistant.
You are a helpful math assistant.\nYour personal goal is: Help users with mathematical
calculations"}], "role": "user"}, "tools": [{"functionDeclarations": [{"description":
"Perform mathematical calculations. Use this for any math operations.", "name":
"calculator", "parameters": {"properties": {"expression": {"description": "Mathematical
expression to evaluate", "title": "Expression", "type": "STRING"}}, "required":
["expression"], "type": "OBJECT"}}]}], "generationConfig": {"stopSequences":
["\nObservation:"]}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- '*/*'
accept-encoding:
- ACCEPT-ENCODING-XXX
connection:
- keep-alive
content-length:
- '2155'
content-type:
- application/json
host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.49.0 gl-python/3.13.3
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"functionCall\": {\n \"name\": \"calculator\",\n
\ \"args\": {\n \"expression\": \"15 * 8\"\n }\n
\ }\n }\n ],\n \"role\": \"model\"\n },\n
\ \"finishReason\": \"STOP\",\n \"avgLogprobs\": -0.10329001290457589\n
\ }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\": 287,\n \"candidatesTokenCount\":
7,\n \"totalTokenCount\": 294,\n \"promptTokensDetails\": [\n {\n
\ \"modality\": \"TEXT\",\n \"tokenCount\": 287\n }\n ],\n
\ \"candidatesTokensDetails\": [\n {\n \"modality\": \"TEXT\",\n
\ \"tokenCount\": 7\n }\n ]\n },\n \"modelVersion\": \"gemini-2.0-flash-exp\",\n
\ \"responseId\": \"QJByaamVIP_g_uMPt6mI0Qg\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Thu, 22 Jan 2026 21:01:52 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=534
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
X-Frame-Options:
- X-FRAME-OPTIONS-XXX
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
- request:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: Calculate what is 15
* 8\n\nThis is the expected criteria for your final answer: The result of the
calculation\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nThis is VERY important to you, your job depends on it!"}],
"role": "user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text":
"The result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze
the tool result. If requirements are met, provide the Final Answer. Otherwise,
call the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}, {"parts": [{"text": ""}], "role": "model"}, {"parts": [{"text": "The
result of 15 * 8 is 120"}], "role": "user"}, {"parts": [{"text": "Analyze the
tool result. If requirements are met, provide the Final Answer. Otherwise, call
the next tool. Deliver only the answer without meta-commentary."}], "role":
"user"}], "systemInstruction": {"parts": [{"text": "You are Math Assistant.
You are a helpful math assistant.\nYour personal goal is: Help users with mathematical
calculations"}], "role": "user"}, "tools": [{"functionDeclarations": [{"description":
"Perform mathematical calculations. Use this for any math operations.", "name":
"calculator", "parameters": {"properties": {"expression": {"description": "Mathematical
expression to evaluate", "title": "Expression", "type": "STRING"}}, "required":
["expression"], "type": "OBJECT"}}]}], "generationConfig": {"stopSequences":
["\nObservation:"]}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- '*/*'
accept-encoding:
- ACCEPT-ENCODING-XXX
connection:
- keep-alive
content-length:
- '2467'
content-type:
- application/json
host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.49.0 gl-python/3.13.3
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"120\\n\"\n }\n ],\n
\ \"role\": \"model\"\n },\n \"finishReason\": \"STOP\",\n
\ \"avgLogprobs\": -0.0097615998238325119\n }\n ],\n \"usageMetadata\":
{\n \"promptTokenCount\": 333,\n \"candidatesTokenCount\": 4,\n \"totalTokenCount\":
337,\n \"promptTokensDetails\": [\n {\n \"modality\": \"TEXT\",\n
\ \"tokenCount\": 333\n }\n ],\n \"candidatesTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 4\n }\n
\ ]\n },\n \"modelVersion\": \"gemini-2.0-flash-exp\",\n \"responseId\":
\"QZByaZHABO-i_uMP58aYqAk\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Thu, 22 Jan 2026 21:01:53 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=412
- gfet4t7; dur=421
Transfer-Encoding:
- chunked
Vary:

View File

@@ -0,0 +1,188 @@
interactions:
- request:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."}], "role": "user"}], "systemInstruction": {"parts": [{"text":
"You are Parallel Tool Agent. You follow tool instructions precisely.\nYour
personal goal is: Use both tools exactly as instructed"}], "role": "user"},
"tools": [{"functionDeclarations": [{"description": "Local search tool #1 for
concurrency testing.", "name": "parallel_local_search_one", "parameters_json_schema":
{"properties": {"query": {"description": "Search query", "title": "Query", "type":
"string"}}, "required": ["query"], "type": "object", "additionalProperties":
false}}, {"description": "Local search tool #2 for concurrency testing.", "name":
"parallel_local_search_two", "parameters_json_schema": {"properties": {"query":
{"description": "Search query", "title": "Query", "type": "string"}}, "required":
["query"], "type": "object", "additionalProperties": false}}, {"description":
"Local search tool #3 for concurrency testing.", "name": "parallel_local_search_three",
"parameters_json_schema": {"properties": {"query": {"description": "Search query",
"title": "Query", "type": "string"}}, "required": ["query"], "type": "object",
"additionalProperties": false}}]}], "generationConfig": {"stopSequences": ["\nObservation:"]}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- '*/*'
accept-encoding:
- ACCEPT-ENCODING-XXX
connection:
- keep-alive
content-length:
- '1783'
content-type:
- application/json
host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.49.0 gl-python/3.13.3
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"functionCall\": {\n \"name\": \"parallel_local_search_one\",\n
\ \"args\": {\n \"query\": \"latest OpenAI model
release notes\"\n }\n },\n \"thoughtSignature\":
\"CrICAb4+9vtrrkiSatPyOs7fssb9akcgCIiQdJKp/k+hcEZVNFvU/H0e4FFmLIhTCPRyHxmU+AQPtBZ5vg6y9ZCcv11RdcWgYW8rPQzCnC+YTUxPAfDzaObky1QsL5pl9+yglQqVoVM31ZcnoiH02z85pwAv6TSJxdJZEekW6XwcIrCoHNCgY3ghHFEd3y3wLJ5JWL7wmiRNTC9TCT8aJHXKFohYrb+4JMULCx8BqKVxOucZPiDHA8GsoqSlzkYEe2xCh9oSdaZpCFrxhZ9bwoVDbVmPrjaq2hj5BoJ5hNxscHJ/E0EOl4ogeKZW+hIVfdzpjAFZW9Oejkb9G4ZSLbxXsoO7x8bi4LHFRABniGrWvNuOOH0Udh4t57oXHXZO4u5NNTood/GkJGcP+aHqUAH1fwqL\"\n
\ },\n {\n \"functionCall\": {\n \"name\":
\"parallel_local_search_two\",\n \"args\": {\n \"query\":
\"latest Anthropic model release notes\"\n }\n }\n
\ },\n {\n \"functionCall\": {\n \"name\":
\"parallel_local_search_three\",\n \"args\": {\n \"query\":
\"latest Gemini model release notes\"\n }\n }\n }\n
\ ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0,\n \"finishMessage\": \"Model generated
function call(s).\"\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
291,\n \"candidatesTokenCount\": 70,\n \"totalTokenCount\": 428,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 291\n
\ }\n ],\n \"thoughtsTokenCount\": 67\n },\n \"modelVersion\":
\"gemini-2.5-flash\",\n \"responseId\": \"alKWacytCLi5jMcPhISaoAI\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 18 Feb 2026 23:59:39 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=999
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
X-Frame-Options:
- X-FRAME-OPTIONS-XXX
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
- request:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."}], "role": "user"}, {"parts": [{"functionCall": {"args":
{"query": "latest OpenAI model release notes"}, "name": "parallel_local_search_one"},
"thoughtSignature": "CrICAb4-9vtrrkiSatPyOs7fssb9akcgCIiQdJKp_k-hcEZVNFvU_H0e4FFmLIhTCPRyHxmU-AQPtBZ5vg6y9ZCcv11RdcWgYW8rPQzCnC-YTUxPAfDzaObky1QsL5pl9-yglQqVoVM31ZcnoiH02z85pwAv6TSJxdJZEekW6XwcIrCoHNCgY3ghHFEd3y3wLJ5JWL7wmiRNTC9TCT8aJHXKFohYrb-4JMULCx8BqKVxOucZPiDHA8GsoqSlzkYEe2xCh9oSdaZpCFrxhZ9bwoVDbVmPrjaq2hj5BoJ5hNxscHJ_E0EOl4ogeKZW-hIVfdzpjAFZW9Oejkb9G4ZSLbxXsoO7x8bi4LHFRABniGrWvNuOOH0Udh4t57oXHXZO4u5NNTood_GkJGcP-aHqUAH1fwqL"},
{"functionCall": {"args": {"query": "latest Anthropic model release notes"},
"name": "parallel_local_search_two"}}, {"functionCall": {"args": {"query": "latest
Gemini model release notes"}, "name": "parallel_local_search_three"}}], "role":
"model"}, {"parts": [{"functionResponse": {"name": "parallel_local_search_one",
"response": {"result": "[one] latest OpenAI model release notes"}}}], "role":
"user"}, {"parts": [{"functionResponse": {"name": "parallel_local_search_two",
"response": {"result": "[two] latest Anthropic model release notes"}}}], "role":
"user"}, {"parts": [{"functionResponse": {"name": "parallel_local_search_three",
"response": {"result": "[three] latest Gemini model release notes"}}}], "role":
"user"}], "systemInstruction": {"parts": [{"text": "You are Parallel Tool Agent.
You follow tool instructions precisely.\nYour personal goal is: Use both tools
exactly as instructed"}], "role": "user"}, "tools": [{"functionDeclarations":
[{"description": "Local search tool #1 for concurrency testing.", "name": "parallel_local_search_one",
"parameters_json_schema": {"properties": {"query": {"description": "Search query",
"title": "Query", "type": "string"}}, "required": ["query"], "type": "object",
"additionalProperties": false}}, {"description": "Local search tool #2 for concurrency
testing.", "name": "parallel_local_search_two", "parameters_json_schema": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}, {"description":
"Local search tool #3 for concurrency testing.", "name": "parallel_local_search_three",
"parameters_json_schema": {"properties": {"query": {"description": "Search query",
"title": "Query", "type": "string"}}, "required": ["query"], "type": "object",
"additionalProperties": false}}]}], "generationConfig": {"stopSequences": ["\nObservation:"]}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- '*/*'
accept-encoding:
- ACCEPT-ENCODING-XXX
connection:
- keep-alive
content-length:
- '3071'
content-type:
- application/json
host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.49.0 gl-python/3.13.3
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"Here is a summary of the latest model
release notes: I have retrieved information regarding the latest OpenAI model
release notes, the latest Anthropic model release notes, and the latest Gemini
model release notes. The specific details of these release notes are available
through the respective tool outputs.\",\n \"thoughtSignature\":
\"CsoBAb4+9vtPvWFM08lR1S4QrLN+Z1+Zpf04Y/bC8tjOpnxz3EEvHyRNEwkslUX5pftBi8J78Xk4/FUER0xjJZc8clUObTvayxLNup4h1JwJ5ZdatulInNGTEieFnF4w8KjSFB/vqNCZvXWZbiLkpzqAnsoAIf0x4VmMN11V0Ozo+3f2QftD+iBrfu3g21UI5tbG0Z+0QHxjRVKXrQOp7dmoZPzaxI0zalfDEI+A2jGpVl/VvauVNv0jQn0yItcA5tkVeWLq6717CjNoig==\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
435,\n \"candidatesTokenCount\": 54,\n \"totalTokenCount\": 524,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 435\n
\ }\n ],\n \"thoughtsTokenCount\": 35\n },\n \"modelVersion\":
\"gemini-2.5-flash\",\n \"responseId\": \"bFKWaZOZCqCvjMcPvvGNgAc\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 18 Feb 2026 23:59:41 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=967
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
X-Frame-Options:
- X-FRAME-OPTIONS-XXX
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,192 @@
interactions:
- request:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}], "role": "user"}], "systemInstruction":
{"parts": [{"text": "You are Parallel Tool Agent. You follow tool instructions
precisely.\nYour personal goal is: Use both tools exactly as instructed"}],
"role": "user"}, "tools": [{"functionDeclarations": [{"description": "Local
search tool #1 for concurrency testing.", "name": "parallel_local_search_one",
"parameters_json_schema": {"properties": {"query": {"description": "Search query",
"title": "Query", "type": "string"}}, "required": ["query"], "type": "object",
"additionalProperties": false}}, {"description": "Local search tool #2 for concurrency
testing.", "name": "parallel_local_search_two", "parameters_json_schema": {"properties":
{"query": {"description": "Search query", "title": "Query", "type": "string"}},
"required": ["query"], "type": "object", "additionalProperties": false}}, {"description":
"Local search tool #3 for concurrency testing.", "name": "parallel_local_search_three",
"parameters_json_schema": {"properties": {"query": {"description": "Search query",
"title": "Query", "type": "string"}}, "required": ["query"], "type": "object",
"additionalProperties": false}}]}], "generationConfig": {"stopSequences": ["\nObservation:"]}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- '*/*'
accept-encoding:
- ACCEPT-ENCODING-XXX
connection:
- keep-alive
content-length:
- '1964'
content-type:
- application/json
host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.49.0 gl-python/3.13.3
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"functionCall\": {\n \"name\": \"parallel_local_search_one\",\n
\ \"args\": {\n \"query\": \"latest OpenAI model
release notes\"\n }\n },\n \"thoughtSignature\":
\"CuMEAb4+9vu1V1iOC9o/a8+jQqow8F4RTrjlnjnDCwsisMHLLJ+Wj3pZxbFDeIjCJe9pa6+14InyYHh/ezgHrv+xPGIJtX9pJQatDCBAfCmcZ3fDipVIMAHLcl0Q660EVuZ+vRgvNhPSau+uSN9u303wJsaKvdzOQnfww2LfLtJMNtOhSHfkfhfw2bkBOtMa5/FuLqKSr6m94dSdE7HShR6+jLMLbiSXkBLWsRp0jGl85Wvd0hoA7dUyq+uIuyOBr5Myo9uMrLbxfnrRRbPMorOpYTCmHK0HE8mEBRjzh1hNwcBcfRL0VcgA2UnBIurStIeVbq51BJQ1UOq6r1wVi50Wdh1GjIQ/iN9C15T1Ql3adjom5QbmY+XY08RJOiNyVplh1YQ0qlWCVHEpueEfdzcIB+BUauVrLNqBcBr5g6ekO5QZCAdt7PLerQU8jhKjDQy367jCKQyaHir0GmAISS8RlZ8tkLKNZlZhd11D76ui6X8ep9yznViBbqH0AS1R2hMm+ielMVFjhidglTMjqB0X+yk1K2eZXkc+R/xsXRPlnlZWRygnV+IbU8RAnZWtneM464Wccmc1scfF45GKiji5bLYO7Zx+ZF8mSLcQaC8M3z121D6VbFonhaIdkJ3Wb7nI2vEyxFjdinVk3/P0zL8nu3nHeqQviTrQIoHMsZk0yPyqu9NWxg3wGJL5pbcaQh87ROQuTsInkuzzEr0QMzjw9W5iquhMh4/Wy/OKXAgf3maQB9Jb4HoHZlc0io+KYqewFSVx2BvqXbqJbIrTkTo6XRTbK7dkwlCbMmE1wKIwjrrzZQI=\"\n
\ },\n {\n \"functionCall\": {\n \"name\":
\"parallel_local_search_two\",\n \"args\": {\n \"query\":
\"latest Anthropic model release notes\"\n }\n }\n
\ },\n {\n \"functionCall\": {\n \"name\":
\"parallel_local_search_three\",\n \"args\": {\n \"query\":
\"latest Gemini model release notes\"\n }\n }\n }\n
\ ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0,\n \"finishMessage\": \"Model generated
function call(s).\"\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
327,\n \"candidatesTokenCount\": 70,\n \"totalTokenCount\": 536,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 327\n
\ }\n ],\n \"thoughtsTokenCount\": 139\n },\n \"modelVersion\":
\"gemini-2.5-flash\",\n \"responseId\": \"ZVKWabziF7bcjMcP3r2SuAg\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 18 Feb 2026 23:59:34 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=1262
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
X-Frame-Options:
- X-FRAME-OPTIONS-XXX
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
- request:
body: '{"contents": [{"parts": [{"text": "\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}], "role": "user"}, {"parts": [{"functionCall":
{"args": {"query": "latest OpenAI model release notes"}, "name": "parallel_local_search_one"}},
{"functionCall": {"args": {"query": "latest Anthropic model release notes"},
"name": "parallel_local_search_two"}}, {"functionCall": {"args": {"query": "latest
Gemini model release notes"}, "name": "parallel_local_search_three"}}], "role":
"model"}, {"parts": [{"functionResponse": {"name": "parallel_local_search_one",
"response": {"result": "[one] latest OpenAI model release notes"}}}], "role":
"user"}, {"parts": [{"functionResponse": {"name": "parallel_local_search_two",
"response": {"result": "[two] latest Anthropic model release notes"}}}], "role":
"user"}, {"parts": [{"functionResponse": {"name": "parallel_local_search_three",
"response": {"result": "[three] latest Gemini model release notes"}}}], "role":
"user"}, {"parts": [{"text": "Analyze the tool result. If requirements are met,
provide the Final Answer. Otherwise, call the next tool. Deliver only the answer
without meta-commentary."}], "role": "user"}], "systemInstruction": {"parts":
[{"text": "You are Parallel Tool Agent. You follow tool instructions precisely.\nYour
personal goal is: Use both tools exactly as instructed"}], "role": "user"},
"tools": [{"functionDeclarations": [{"description": "Local search tool #1 for
concurrency testing.", "name": "parallel_local_search_one", "parameters_json_schema":
{"properties": {"query": {"description": "Search query", "title": "Query", "type":
"string"}}, "required": ["query"], "type": "object", "additionalProperties":
false}}, {"description": "Local search tool #2 for concurrency testing.", "name":
"parallel_local_search_two", "parameters_json_schema": {"properties": {"query":
{"description": "Search query", "title": "Query", "type": "string"}}, "required":
["query"], "type": "object", "additionalProperties": false}}, {"description":
"Local search tool #3 for concurrency testing.", "name": "parallel_local_search_three",
"parameters_json_schema": {"properties": {"query": {"description": "Search query",
"title": "Query", "type": "string"}}, "required": ["query"], "type": "object",
"additionalProperties": false}}]}], "generationConfig": {"stopSequences": ["\nObservation:"]}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- '*/*'
accept-encoding:
- ACCEPT-ENCODING-XXX
connection:
- keep-alive
content-length:
- '3014'
content-type:
- application/json
host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.49.0 gl-python/3.13.3
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"The search results indicate the latest
model release notes for OpenAI, Anthropic, and Gemini are: [one] latest OpenAI
model release notes[two] latest Anthropic model release notes[three] latest
Gemini model release notes.\",\n \"thoughtSignature\": \"CsUPAb4+9vs4hkuatQAakl1FSHx5DIde9nHYobJdlWs2HEzES9gHn7uwjMIlFPTzJUbnZqxpAK93hqsCofdfGANr8dwK+/IbZAiMSikpAq2ZjEbWADjfalU3ke4LcQMh6TEYFVGz1QCinjne3jZx5jOVaL8YdAtjOYnBZWA6KqdvfKjD7+Ct/BLoEqvu4LW6kxhXQgcV+D3M1QxGlr1dxpajj4wyYFI9LXchE2vCdAMPYTkPQ4WPbS3xjz0jJb6qFAwwg+BY5kGemkWWVHsvq28t09pd7FEH0bod5cEpR65qEefpJfhHsXYqmOwHDkfNePYnYC+5qmn7kvkN+fhF41SoMRZahMZGDjIo+q6vvru3eXKmZiuLsrh8AqQIks/4S3sSuxt16ogYKE+LlFxml2ygXFPww59nRAtc+xK6VW8jB2vyv9Eo5cpnG9ZBv1dOznJnmj4AWA1ddMlp+yq8AdaboTSo5dysYMwFcSXS3kuU+xi92dC+7GqZZbDr5frvnc+MnSuzYwHhNjSQqvTo5DKGit53zDwlFJT74kLBXk36BOFQp4xlfs+BpKkw11bow6qQoTvC68D023ZHami+McO1WYBDoO5CrDoosU8fAYljqaGArBoMlssF4O7VKHEaEbEZnYCr0Wxo6XP/mtPIpHQE4OyCz/GAJSJtQv1hO7DNCMzpSpkLyuemB1SOZGl3mlLQhosh3TAGP0xgqmHpKccdCSWoXGWjO48VluFuV9E1FwW1Xi++XhMRcUaljJXPZaNVjGcAG1uAxeVkUMsY8tBvQ0vaumUK2jkzbyQTWeStEWwl1yKmklI8JDXske/k6tYJOyF+8t0mF7oCEqNHSNicj7TomihpPlVjNl1Mm4l5fvwlKtAPJwiKrchCunlZB3uGN1AR0h0Hvznffutc/lV/FWFbNgFAaNJZKRs40vMk1xmRZyH2rs+Ob2fZriQ3BSwzzNeiwDLXxm0m/ytOai+K9ObFuC/IEh5fJfvQbNeo3TmiCAMCZPNXMDtlOyLqQzzKwmMFH4c53Ol+kkTiuAKECNQR1dOCufAL0U5lzEUFRxFvOq67lp6xqG8m+WzCIkbnF8QyJHfujtXVMJACaevUkM7+kAVyTwETEKQsanp0tBwzV42ieChp/h7pivcC++cFXdSG5dvR94BgkHmtpC9+jfNH32RREPLuyWfU5aBXiOkxjRs9fDexAFjrkGjM18I+jqHZNeuUR20BKe2jFsU8xJS3Fa4eXabm/YPL1t8R5jr572Ch/r4bspFp8MQ5RcFo8Nn/HiBmW8uZ2BcLEY1RPWUBvxVhfvh/hNxaRKu21x8vGz72RoiNuOjNbeADYAaBJqBGLp0MALxZ/rnXPzDLQUt6Mv07fWHAZr5p3r/skleot25lr2Tcl4qJCPM4/cfs6U0x4CY26ktBiCs4bWKqSEV1Q05nf5kpxVOIRSTgxqFOj/rWIAF3uw7mvsuRKd3YXILV5OrvEoETdQvf7BdYPbQbIQYDf7DBKhf51O8RKQgcfl6mVQswamdJ+PyqLbozTkFCjXMKI0PwJdy8tfKfCeeEe0TbOXSfeTczKQkL8WyWkBg4tS81JnWAVzfVlNjbvo/fk+wv7FyfJJS1HJGlxZ0kUlWi1369rSlldYPoSqopuekOxtYnpYpz92y/jVLNQXE1IVLqWYh9o3gTwjeyaHG7fCaWF2QRGrCUvejT8eJjevhj/sgadjPVcEP5o7Zcw5yTBCgc0+FX1j5KpCmfZ/dVvT4iIX8bOkhxjHQ8ifOx39BMM4EObgCA+g+BFN+Ra7kOf4hJ6tPNhqvJa4E4fyISlVrRiBqSt59ZkuLyWuY9SYy0nvbklP30WDUHSAvcuEwVMSuT524afHISfO/+tSgE7JAKzEPSOoVO3Z5NS9kcAqHuBSe/LL4XJbCKF9Oggm9/gwdAulnBANd4ydQ/raTPE/QUu/CGqqGhBd+wo8x0Jg/BMZWkwhz0fEzsh+OjnrEkHv4QIqZ9v/j1Rv9uc+cDeK7eGi62okGLrPFX2pNQtsZRdUM9aBSlTBUVSdCDpkvieENzLnR257EDZy1EV2HxGRfOFZVVdaW1n8XvL73pcFoQ5XABpfYuigOS8i4S8g43Qfe77GosnuXR5rcJCrL03q3hptb97K5ysKFLgumsaaWo92MBhZYKvQ6SwStgyWRlb22uQGQJYsS8OTD/uVNiQzFjOMsR/l71c9RI1Eb7SQJT6WWvL1YhA7sQw/lQf8soLKfWshoky6mMrGopjRak8xHpJe5VWbqK8PK6iXDd403JrHICyh4M3FpEja3eX2V3SN6U+EgIWKIE8lE/iQZakhLtG2KL7nNQy/cksxzIh5ElQCe5NkrQZO0fai6ek8qwbmz07RVg2FknD7F2hvmxZBqoJSXhsFVn/9+fnkcsZekEtUevFmlQQNspPc63XgO0XmpTye9uM/BbTEsNEWeHSFZTEQLLx1l+pgwsYO3NlNSIUN24/GIR7JrZFG4fAoljkDKjhrYQzr1Fiy3t5G+CmadZ0TcjRQQdDw36ETlf7cizcrQc4FNtnx5rNWEaf54vUvlsd2DD19UIkzP9omITsiuNPPcUNq0A6v1TkgnSNYfhb26nxJIg34r8MmCAhWzB2eCy54gvOHDGLFAwfFZrQdvl\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
504,\n \"candidatesTokenCount\": 45,\n \"totalTokenCount\": 973,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 504\n
\ }\n ],\n \"thoughtsTokenCount\": 424\n },\n \"modelVersion\":
\"gemini-2.5-flash\",\n \"responseId\": \"Z1KWaYbTKZvnjMcP7piEoAg\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Type:
- application/json; charset=UTF-8
Date:
- Wed, 18 Feb 2026 23:59:37 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=2283
Transfer-Encoding:
- chunked
Vary:
- Origin
- X-Origin
- Referer
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
X-Frame-Options:
- X-FRAME-OPTIONS-XXX
X-XSS-Protection:
- '0'
status:
code: 200
message: OK
version: 1

View File

@@ -5,9 +5,9 @@ interactions:
calculations"},{"role":"user","content":"\nCurrent Task: Calculate what is 15
* 8\n\nThis is the expected criteria for your final answer: The result of the
calculation\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nThis is VERY important to you, your job depends on it!"}],"model":"gpt-4o-mini","tool_choice":"auto","tools":[{"type":"function","function":{"name":"calculator","description":"Perform
mathematical calculations. Use this for any math operations.","parameters":{"properties":{"expression":{"description":"Mathematical
expression to evaluate","title":"Expression","type":"string"}},"required":["expression"],"type":"object"}}}]}'
not a summary."}],"model":"gpt-5-nano","tool_choice":"auto","tools":[{"type":"function","function":{"name":"calculator","description":"Perform
mathematical calculations. Use this for any math operations.","strict":true,"parameters":{"properties":{"expression":{"description":"Mathematical
expression to evaluate","title":"Expression","type":"string"}},"required":["expression"],"type":"object","additionalProperties":false}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
@@ -20,7 +20,7 @@ interactions:
connection:
- keep-alive
content-length:
- '829'
- '813'
content-type:
- application/json
host:
@@ -47,140 +47,17 @@ interactions:
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-D0vm7joOuDBPcMpfmOnftOoTCPtc8\",\n \"object\":
\"chat.completion\",\n \"created\": 1769114459,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_G73UZDvL4wC9EEdvm1UcRIRM\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"calculator\",\n
\ \"arguments\": \"{\\\"expression\\\":\\\"15 * 8\\\"}\"\n }\n
\ }\n ],\n \"refusal\": null,\n \"annotations\":
[]\n },\n \"logprobs\": null,\n \"finish_reason\": \"tool_calls\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 137,\n \"completion_tokens\":
17,\n \"total_tokens\": 154,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_c4585b5b9c\"\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Thu, 22 Jan 2026 20:40:59 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '761'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '1080'
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
- request:
body: '{"messages":[{"role":"system","content":"You are Math Assistant. You are
a helpful math assistant.\nYour personal goal is: Help users with mathematical
calculations"},{"role":"user","content":"\nCurrent Task: Calculate what is 15
* 8\n\nThis is the expected criteria for your final answer: The result of the
calculation\nyou MUST return the actual complete content as the final answer,
not a summary.\n\nThis is VERY important to you, your job depends on it!"},{"role":"assistant","content":null,"tool_calls":[{"id":"call_G73UZDvL4wC9EEdvm1UcRIRM","type":"function","function":{"name":"calculator","arguments":"{\"expression\":\"15
* 8\"}"}}]},{"role":"tool","tool_call_id":"call_G73UZDvL4wC9EEdvm1UcRIRM","content":"The
result of 15 * 8 is 120"},{"role":"user","content":"Analyze the tool result.
If requirements are met, provide the Final Answer. Otherwise, call the next
tool. Deliver only the answer without meta-commentary."}],"model":"gpt-4o-mini","tool_choice":"auto","tools":[{"type":"function","function":{"name":"calculator","description":"Perform
mathematical calculations. Use this for any math operations.","parameters":{"properties":{"expression":{"description":"Mathematical
expression to evaluate","title":"Expression","type":"string"}},"required":["expression"],"type":"object"}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '1299'
content-type:
- application/json
cookie:
- COOKIE-XXX
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-D0vm8mUnzLxu9pf1rc7MODkrMsCmf\",\n \"object\":
\"chat.completion\",\n \"created\": 1769114460,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
string: "{\n \"id\": \"chatcmpl-DAlG9W2mJYuOgpf3FwCRgbqaiHWf3\",\n \"object\":
\"chat.completion\",\n \"created\": 1771457317,\n \"model\": \"gpt-5-nano-2025-08-07\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"120\",\n \"refusal\": null,\n
\ \"annotations\": []\n },\n \"logprobs\": null,\n \"finish_reason\":
\"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\": 207,\n \"completion_tokens\":
2,\n \"total_tokens\": 209,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
\ \"annotations\": []\n },\n \"finish_reason\": \"stop\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 208,\n \"completion_tokens\":
138,\n \"total_tokens\": 346,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
{\n \"reasoning_tokens\": 128,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_c4585b5b9c\"\n}\n"
\"default\",\n \"system_fingerprint\": null\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
@@ -189,7 +66,7 @@ interactions:
Content-Type:
- application/json
Date:
- Thu, 22 Jan 2026 20:41:00 GMT
- Wed, 18 Feb 2026 23:28:39 GMT
Server:
- cloudflare
Strict-Transport-Security:
@@ -207,13 +84,13 @@ interactions:
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '262'
- '1869'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '496'
set-cookie:
- SET-COOKIE-XXX
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:

View File

@@ -0,0 +1,265 @@
interactions:
- request:
body: '{"messages":[{"role":"system","content":"You are Parallel Tool Agent. You
follow tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed"},{"role":"user","content":"\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."}],"model":"gpt-4o-mini","tool_choice":"auto","tools":[{"type":"function","function":{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '1733'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-DAldZHfQGVcV3FNwAJAtNooU3PAU7\",\n \"object\":
\"chat.completion\",\n \"created\": 1771458769,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_kz1qLLRsugXwWiQMeH9oFAep\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"parallel_local_search_one\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest OpenAI model release
notes\\\"}\"\n }\n },\n {\n \"id\":
\"call_yNouGq1Kv6P5W9fhTng6acZi\",\n \"type\": \"function\",\n
\ \"function\": {\n \"name\": \"parallel_local_search_two\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest Anthropic model
release notes\\\"}\"\n }\n },\n {\n \"id\":
\"call_O7MqnuniDmyT6a0BS31GTunB\",\n \"type\": \"function\",\n
\ \"function\": {\n \"name\": \"parallel_local_search_three\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest Gemini model release
notes\\\"}\"\n }\n }\n ],\n \"refusal\":
null,\n \"annotations\": []\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"tool_calls\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
259,\n \"completion_tokens\": 78,\n \"total_tokens\": 337,\n \"prompt_tokens_details\":
{\n \"cached_tokens\": 0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_414ba99a04\"\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Wed, 18 Feb 2026 23:52:50 GMT
Server:
- cloudflare
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '1418'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
set-cookie:
- SET-COOKIE-XXX
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
- request:
body: '{"messages":[{"role":"system","content":"You are Parallel Tool Agent. You
follow tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed"},{"role":"user","content":"\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."},{"role":"assistant","content":null,"tool_calls":[{"id":"call_kz1qLLRsugXwWiQMeH9oFAep","type":"function","function":{"name":"parallel_local_search_one","arguments":"{\"query\":
\"latest OpenAI model release notes\"}"}},{"id":"call_yNouGq1Kv6P5W9fhTng6acZi","type":"function","function":{"name":"parallel_local_search_two","arguments":"{\"query\":
\"latest Anthropic model release notes\"}"}},{"id":"call_O7MqnuniDmyT6a0BS31GTunB","type":"function","function":{"name":"parallel_local_search_three","arguments":"{\"query\":
\"latest Gemini model release notes\"}"}}]},{"role":"tool","tool_call_id":"call_kz1qLLRsugXwWiQMeH9oFAep","name":"parallel_local_search_one","content":"[one]
latest OpenAI model release notes"},{"role":"tool","tool_call_id":"call_yNouGq1Kv6P5W9fhTng6acZi","name":"parallel_local_search_two","content":"[two]
latest Anthropic model release notes"},{"role":"tool","tool_call_id":"call_O7MqnuniDmyT6a0BS31GTunB","name":"parallel_local_search_three","content":"[three]
latest Gemini model release notes"}],"model":"gpt-4o-mini","tool_choice":"auto","tools":[{"type":"function","function":{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '2756'
content-type:
- application/json
cookie:
- COOKIE-XXX
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-DAldbawkFNpOeXbaJTkTlsSi7OiII\",\n \"object\":
\"chat.completion\",\n \"created\": 1771458771,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"The latest release notes for OpenAI,
Anthropic, and Gemini models highlight significant updates and improvements
in each respective technology. OpenAI's notes detail new features and optimizations
that enhance user interaction and performance. Anthropic's release emphasizes
their focus on safety and alignment in AI development, showcasing advancements
in responsible AI practices. Gemini's notes underline their innovative approaches
and cutting-edge functionalities designed to push the boundaries of current
AI capabilities.\",\n \"refusal\": null,\n \"annotations\":
[]\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 377,\n \"completion_tokens\":
85,\n \"total_tokens\": 462,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 0,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": \"fp_414ba99a04\"\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Wed, 18 Feb 2026 23:52:53 GMT
Server:
- cloudflare
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '1755'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,265 @@
interactions:
- request:
body: '{"messages":[{"role":"system","content":"You are Parallel Tool Agent. You
follow tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed"},{"role":"user","content":"\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}],"model":"gpt-5-nano","temperature":1,"tool_choice":"auto","tools":[{"type":"function","function":{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '1929'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-DAlddfEozIpgleBufPaffZMQWK0Hj\",\n \"object\":
\"chat.completion\",\n \"created\": 1771458773,\n \"model\": \"gpt-5-nano-2025-08-07\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_Putc2jV5GhiIZMwx8mDcI61Q\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"parallel_local_search_one\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest OpenAI model release
notes\\\"}\"\n }\n },\n {\n \"id\":
\"call_iyjwcvkL3PdoOddxsqkHCT9T\",\n \"type\": \"function\",\n
\ \"function\": {\n \"name\": \"parallel_local_search_two\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest Anthropic model
release notes\\\"}\"\n }\n },\n {\n \"id\":
\"call_G728RseEU7SbGk5YTiyyp9IH\",\n \"type\": \"function\",\n
\ \"function\": {\n \"name\": \"parallel_local_search_three\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest Gemini model release
notes\\\"}\"\n }\n }\n ],\n \"refusal\":
null,\n \"annotations\": []\n },\n \"finish_reason\": \"tool_calls\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 378,\n \"completion_tokens\":
1497,\n \"total_tokens\": 1875,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 1408,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": null\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Wed, 18 Feb 2026 23:53:08 GMT
Server:
- cloudflare
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '14853'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
set-cookie:
- SET-COOKIE-XXX
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
- request:
body: '{"messages":[{"role":"system","content":"You are Parallel Tool Agent. You
follow tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed"},{"role":"user","content":"\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."},{"role":"assistant","content":null,"tool_calls":[{"id":"call_Putc2jV5GhiIZMwx8mDcI61Q","type":"function","function":{"name":"parallel_local_search_one","arguments":"{\"query\":
\"latest OpenAI model release notes\"}"}},{"id":"call_iyjwcvkL3PdoOddxsqkHCT9T","type":"function","function":{"name":"parallel_local_search_two","arguments":"{\"query\":
\"latest Anthropic model release notes\"}"}},{"id":"call_G728RseEU7SbGk5YTiyyp9IH","type":"function","function":{"name":"parallel_local_search_three","arguments":"{\"query\":
\"latest Gemini model release notes\"}"}}]},{"role":"tool","tool_call_id":"call_Putc2jV5GhiIZMwx8mDcI61Q","name":"parallel_local_search_one","content":"[one]
latest OpenAI model release notes"},{"role":"tool","tool_call_id":"call_iyjwcvkL3PdoOddxsqkHCT9T","name":"parallel_local_search_two","content":"[two]
latest Anthropic model release notes"},{"role":"tool","tool_call_id":"call_G728RseEU7SbGk5YTiyyp9IH","name":"parallel_local_search_three","content":"[three]
latest Gemini model release notes"},{"role":"user","content":"Analyze the tool
result. If requirements are met, provide the Final Answer. Otherwise, call the
next tool. Deliver only the answer without meta-commentary."}],"model":"gpt-5-nano","temperature":1,"tool_choice":"auto","tools":[{"type":"function","function":{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '3136'
content-type:
- application/json
cookie:
- COOKIE-XXX
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-DAldt2BXNqiYYLPgInjHCpYKfk2VK\",\n \"object\":
\"chat.completion\",\n \"created\": 1771458789,\n \"model\": \"gpt-5-nano-2025-08-07\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"The results show the latest model release
notes for OpenAI, Anthropic, and Gemini.\",\n \"refusal\": null,\n
\ \"annotations\": []\n },\n \"finish_reason\": \"stop\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 537,\n \"completion_tokens\":
2011,\n \"total_tokens\": 2548,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 1984,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": null\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Wed, 18 Feb 2026 23:53:25 GMT
Server:
- cloudflare
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '15368'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,264 @@
interactions:
- request:
body: '{"messages":[{"role":"system","content":"You are Parallel Tool Agent. You
follow tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed"},{"role":"user","content":"\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."}],"model":"gpt-5-nano","temperature":1,"tool_choice":"auto","tools":[{"type":"function","function":{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '1748'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-DB244zBgA66fzl8TNcIPRWoE4lDIQ\",\n \"object\":
\"chat.completion\",\n \"created\": 1771521916,\n \"model\": \"gpt-5-nano-2025-08-07\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_D2ojRWqkng6krQ51vWQEU8wR\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"parallel_local_search_one\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest OpenAI model release
notes\\\"}\"\n }\n },\n {\n \"id\":
\"call_v1tpTKw1sYcI75SWG1LCkAC3\",\n \"type\": \"function\",\n
\ \"function\": {\n \"name\": \"parallel_local_search_two\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest Anthropic model
release notes\\\"}\"\n }\n },\n {\n \"id\":
\"call_RrbyZClymnngoNLhlkQLLpwM\",\n \"type\": \"function\",\n
\ \"function\": {\n \"name\": \"parallel_local_search_three\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest Gemini model release
notes\\\"}\"\n }\n }\n ],\n \"refusal\":
null,\n \"annotations\": []\n },\n \"finish_reason\": \"tool_calls\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 343,\n \"completion_tokens\":
855,\n \"total_tokens\": 1198,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 768,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": null\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 17:25:23 GMT
Server:
- cloudflare
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '6669'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
set-cookie:
- SET-COOKIE-XXX
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
- request:
body: '{"messages":[{"role":"system","content":"You are Parallel Tool Agent. You
follow tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed"},{"role":"user","content":"\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary."},{"role":"assistant","content":null,"tool_calls":[{"id":"call_D2ojRWqkng6krQ51vWQEU8wR","type":"function","function":{"name":"parallel_local_search_one","arguments":"{\"query\":
\"latest OpenAI model release notes\"}"}},{"id":"call_v1tpTKw1sYcI75SWG1LCkAC3","type":"function","function":{"name":"parallel_local_search_two","arguments":"{\"query\":
\"latest Anthropic model release notes\"}"}},{"id":"call_RrbyZClymnngoNLhlkQLLpwM","type":"function","function":{"name":"parallel_local_search_three","arguments":"{\"query\":
\"latest Gemini model release notes\"}"}}]},{"role":"tool","tool_call_id":"call_D2ojRWqkng6krQ51vWQEU8wR","name":"parallel_local_search_one","content":"[one]
latest OpenAI model release notes"},{"role":"tool","tool_call_id":"call_v1tpTKw1sYcI75SWG1LCkAC3","name":"parallel_local_search_two","content":"[two]
latest Anthropic model release notes"},{"role":"tool","tool_call_id":"call_RrbyZClymnngoNLhlkQLLpwM","name":"parallel_local_search_three","content":"[three]
latest Gemini model release notes"}],"model":"gpt-5-nano","temperature":1,"tool_choice":"auto","tools":[{"type":"function","function":{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '2771'
content-type:
- application/json
cookie:
- COOKIE-XXX
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-DB24DjyYsIHiQJ7hHXob8tQFfeXBs\",\n \"object\":
\"chat.completion\",\n \"created\": 1771521925,\n \"model\": \"gpt-5-nano-2025-08-07\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"The three latest release-note references
retrieved encompass OpenAI, Anthropic, and Gemini, indicating that all three
major model families are actively updating their offerings. These notes typically
cover improvements to capabilities, safety measures, performance enhancements,
and any new APIs or features, suggesting a trend of ongoing refinement across
providers. If you\u2019d like, I can pull the full release notes or extract
and compare the key changes across the three sources.\",\n \"refusal\":
null,\n \"annotations\": []\n },\n \"finish_reason\": \"stop\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 467,\n \"completion_tokens\":
1437,\n \"total_tokens\": 1904,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 1344,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": null\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 17:25:35 GMT
Server:
- cloudflare
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '10369'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,339 @@
interactions:
- request:
body: '{"trace_id": "e456cc10-ce7b-4e68-a2cc-ddb806a2e7b9", "execution_type":
"crew", "user_identifier": null, "execution_context": {"crew_fingerprint": null,
"crew_name": "crew", "flow_name": null, "crewai_version": "1.9.3", "privacy_level":
"standard"}, "execution_metadata": {"expected_duration_estimate": 300, "agent_count":
0, "task_count": 0, "flow_method_count": 0, "execution_started_at": "2026-02-19T17:24:41.723158+00:00"},
"ephemeral_trace_id": "e456cc10-ce7b-4e68-a2cc-ddb806a2e7b9"}'
headers:
Accept:
- '*/*'
Connection:
- keep-alive
Content-Length:
- '488'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
X-Crewai-Organization-Id:
- 3433f0ee-8a94-4aa4-822b-2ac71aa38b18
X-Crewai-Version:
- 1.9.3
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
method: POST
uri: https://app.crewai.com/crewai_plus/api/v1/tracing/ephemeral/batches
response:
body:
string: '{"id":"a78f2aca-0525-47c7-8f37-b3fca0ad6672","ephemeral_trace_id":"e456cc10-ce7b-4e68-a2cc-ddb806a2e7b9","execution_type":"crew","crew_name":"crew","flow_name":null,"status":"running","duration_ms":null,"crewai_version":"1.9.3","total_events":0,"execution_context":{"crew_fingerprint":null,"crew_name":"crew","flow_name":null,"crewai_version":"1.9.3","privacy_level":"standard"},"created_at":"2026-02-19T17:24:41.989Z","updated_at":"2026-02-19T17:24:41.989Z","access_code":"TRACE-bd80d6be74","user_identifier":null}'
headers:
Connection:
- keep-alive
Content-Length:
- '515'
Content-Type:
- application/json; charset=utf-8
Date:
- Thu, 19 Feb 2026 17:24:41 GMT
cache-control:
- no-store
content-security-policy:
- CSP-FILTERED
etag:
- ETAG-XXX
expires:
- '0'
permissions-policy:
- PERMISSIONS-POLICY-XXX
pragma:
- no-cache
referrer-policy:
- REFERRER-POLICY-XXX
strict-transport-security:
- STS-XXX
vary:
- Accept
x-content-type-options:
- X-CONTENT-TYPE-XXX
x-frame-options:
- X-FRAME-OPTIONS-XXX
x-permitted-cross-domain-policies:
- X-PERMITTED-XXX
x-request-id:
- X-REQUEST-ID-XXX
x-runtime:
- X-RUNTIME-XXX
x-xss-protection:
- X-XSS-PROTECTION-XXX
status:
code: 201
message: Created
- request:
body: '{"messages":[{"role":"system","content":"You are Parallel Tool Agent. You
follow tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed"},{"role":"user","content":"\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."}],"model":"gpt-5-nano","temperature":1,"tool_choice":"auto","tools":[{"type":"function","function":{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '1929'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-DB23W8RBF6zlxweiHYGb6maVfyctt\",\n \"object\":
\"chat.completion\",\n \"created\": 1771521882,\n \"model\": \"gpt-5-nano-2025-08-07\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n
\ \"id\": \"call_sge1FXUkpmPEDe8nTOgn0tQG\",\n \"type\":
\"function\",\n \"function\": {\n \"name\": \"parallel_local_search_one\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest OpenAI model release
notes\\\"}\"\n }\n },\n {\n \"id\":
\"call_z5jRPH4DQ7Wp3HdDUlZe8gGh\",\n \"type\": \"function\",\n
\ \"function\": {\n \"name\": \"parallel_local_search_two\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest Anthropic model
release notes\\\"}\"\n }\n },\n {\n \"id\":
\"call_DNlgqnadODDsyQkSuLcXZCX2\",\n \"type\": \"function\",\n
\ \"function\": {\n \"name\": \"parallel_local_search_three\",\n
\ \"arguments\": \"{\\\"query\\\": \\\"latest Gemini model release
notes\\\"}\"\n }\n }\n ],\n \"refusal\":
null,\n \"annotations\": []\n },\n \"finish_reason\": \"tool_calls\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 378,\n \"completion_tokens\":
2456,\n \"total_tokens\": 2834,\n \"prompt_tokens_details\": {\n \"cached_tokens\":
0,\n \"audio_tokens\": 0\n },\n \"completion_tokens_details\":
{\n \"reasoning_tokens\": 2368,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\":
0,\n \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": null\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 17:25:02 GMT
Server:
- cloudflare
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '19582'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
set-cookie:
- SET-COOKIE-XXX
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
- request:
body: '{"messages":[{"role":"system","content":"You are Parallel Tool Agent. You
follow tool instructions precisely.\nYour personal goal is: Use both tools exactly
as instructed"},{"role":"user","content":"\nCurrent Task: This is a tool-calling
compliance test. In your next assistant turn, emit exactly 3 tool calls in the
same response (parallel tool calls), in this order: 1) parallel_local_search_one(query=''latest
OpenAI model release notes''), 2) parallel_local_search_two(query=''latest Anthropic
model release notes''), 3) parallel_local_search_three(query=''latest Gemini
model release notes''). Do not call any other tools and do not answer before
those 3 tool calls are emitted. After the tool results return, provide a one
paragraph summary.\n\nThis is the expected criteria for your final answer: A
one sentence summary of both tool outputs\nyou MUST return the actual complete
content as the final answer, not a summary."},{"role":"assistant","content":null,"tool_calls":[{"id":"call_sge1FXUkpmPEDe8nTOgn0tQG","type":"function","function":{"name":"parallel_local_search_one","arguments":"{\"query\":
\"latest OpenAI model release notes\"}"}},{"id":"call_z5jRPH4DQ7Wp3HdDUlZe8gGh","type":"function","function":{"name":"parallel_local_search_two","arguments":"{\"query\":
\"latest Anthropic model release notes\"}"}},{"id":"call_DNlgqnadODDsyQkSuLcXZCX2","type":"function","function":{"name":"parallel_local_search_three","arguments":"{\"query\":
\"latest Gemini model release notes\"}"}}]},{"role":"tool","tool_call_id":"call_sge1FXUkpmPEDe8nTOgn0tQG","name":"parallel_local_search_one","content":"[one]
latest OpenAI model release notes"},{"role":"tool","tool_call_id":"call_z5jRPH4DQ7Wp3HdDUlZe8gGh","name":"parallel_local_search_two","content":"[two]
latest Anthropic model release notes"},{"role":"tool","tool_call_id":"call_DNlgqnadODDsyQkSuLcXZCX2","name":"parallel_local_search_three","content":"[three]
latest Gemini model release notes"},{"role":"user","content":"Analyze the tool
result. If requirements are met, provide the Final Answer. Otherwise, call the
next tool. Deliver only the answer without meta-commentary."}],"model":"gpt-5-nano","temperature":1,"tool_choice":"auto","tools":[{"type":"function","function":{"name":"parallel_local_search_one","description":"Local
search tool #1 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_two","description":"Local
search tool #2 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}},{"type":"function","function":{"name":"parallel_local_search_three","description":"Local
search tool #3 for concurrency testing.","strict":true,"parameters":{"properties":{"query":{"description":"Search
query","title":"Query","type":"string"}},"required":["query"],"type":"object","additionalProperties":false}}}]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '3136'
content-type:
- application/json
cookie:
- COOKIE-XXX
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.13.3
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-DB23sY0Ahpd1yAgLZ882KkA50Zljx\",\n \"object\":
\"chat.completion\",\n \"created\": 1771521904,\n \"model\": \"gpt-5-nano-2025-08-07\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"Results returned three items: the latest
OpenAI model release notes, the latest Anthropic model release notes, and
the latest Gemini model release notes.\",\n \"refusal\": null,\n \"annotations\":
[]\n },\n \"finish_reason\": \"stop\"\n }\n ],\n \"usage\":
{\n \"prompt_tokens\": 537,\n \"completion_tokens\": 1383,\n \"total_tokens\":
1920,\n \"prompt_tokens_details\": {\n \"cached_tokens\": 0,\n \"audio_tokens\":
0\n },\n \"completion_tokens_details\": {\n \"reasoning_tokens\":
1344,\n \"audio_tokens\": 0,\n \"accepted_prediction_tokens\": 0,\n
\ \"rejected_prediction_tokens\": 0\n }\n },\n \"service_tier\":
\"default\",\n \"system_fingerprint\": null\n}\n"
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Thu, 19 Feb 2026 17:25:16 GMT
Server:
- cloudflare
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '12339'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
version: 1