Merge branch 'main' into gl/fix/ensure-complete-tool-signature

This commit is contained in:
Greyson LaLonde
2025-12-02 09:07:56 -05:00
committed by GitHub
73 changed files with 10348 additions and 1799 deletions

View File

@@ -96,6 +96,30 @@ HEADERS_TO_FILTER = {
"x-ratelimit-reset-requests": "X-RATELIMIT-RESET-REQUESTS-XXX",
"x-ratelimit-reset-tokens": "X-RATELIMIT-RESET-TOKENS-XXX",
"x-goog-api-key": "X-GOOG-API-KEY-XXX",
"api-key": "X-API-KEY-XXX",
"User-Agent": "X-USER-AGENT-XXX",
"apim-request-id:": "X-API-CLIENT-REQUEST-ID-XXX",
"azureml-model-session": "AZUREML-MODEL-SESSION-XXX",
"x-ms-client-request-id": "X-MS-CLIENT-REQUEST-ID-XXX",
"x-ms-region": "X-MS-REGION-XXX",
"apim-request-id": "APIM-REQUEST-ID-XXX",
"x-api-key": "X-API-KEY-XXX",
"anthropic-organization-id": "ANTHROPIC-ORGANIZATION-ID-XXX",
"request-id": "REQUEST-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-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",
"x-amz-date": "X-AMZ-DATE-XXX",
"amz-sdk-invocation-id": "AMZ-SDK-INVOCATION-ID-XXX",
"accept-encoding": "ACCEPT-ENCODING-XXX",
"x-amzn-requestid": "X-AMZN-REQUESTID-XXX",
"x-amzn-RequestId": "X-AMZN-REQUESTID-XXX",
}
@@ -105,6 +129,8 @@ def _filter_request_headers(request: Request) -> Request: # type: ignore[no-any
for variant in [header_name, header_name.upper(), header_name.title()]:
if variant in request.headers:
request.headers[variant] = [replacement]
request.method = request.method.upper()
return request
@@ -158,6 +184,7 @@ def vcr_config(vcr_cassette_dir: str) -> dict[str, Any]:
"before_record_request": _filter_request_headers,
"before_record_response": _filter_response_headers,
"filter_query_parameters": ["key"],
"match_on": ["method", "scheme", "host", "port", "path"],
}
if os.getenv("GITHUB_ACTIONS") == "true":

View File

@@ -1089,6 +1089,50 @@ CrewAI supports streaming responses from LLMs, allowing your application to rece
</Tab>
</Tabs>
## Async LLM Calls
CrewAI supports asynchronous LLM calls for improved performance and concurrency in your AI workflows. Async calls allow you to run multiple LLM requests concurrently without blocking, making them ideal for high-throughput applications and parallel agent operations.
<Tabs>
<Tab title="Basic Usage">
Use the `acall` method for asynchronous LLM requests:
```python
import asyncio
from crewai import LLM
async def main():
llm = LLM(model="openai/gpt-4o")
# Single async call
response = await llm.acall("What is the capital of France?")
print(response)
asyncio.run(main())
```
The `acall` method supports all the same parameters as the synchronous `call` method, including messages, tools, and callbacks.
</Tab>
<Tab title="With Streaming">
Combine async calls with streaming for real-time concurrent responses:
```python
import asyncio
from crewai import LLM
async def stream_async():
llm = LLM(model="openai/gpt-4o", stream=True)
response = await llm.acall("Write a short story about AI")
print(response)
asyncio.run(stream_async())
```
</Tab>
</Tabs>
## Structured LLM Calls
CrewAI supports structured responses from LLM calls by allowing you to define a `response_format` using a Pydantic model. This enables the framework to automatically parse and validate the output, making it easier to integrate the response into your application without manual post-processing.

View File

@@ -8,17 +8,17 @@ authors = [
]
requires-python = ">=3.10, <3.14"
dependencies = [
"lancedb>=0.5.4",
"pytube>=15.0.0",
"requests>=2.32.5",
"docker>=7.1.0",
"lancedb~=0.5.4",
"pytube~=15.0.0",
"requests~=2.32.5",
"docker~=7.1.0",
"crewai==1.6.1",
"lancedb>=0.5.4",
"tiktoken>=0.8.0",
"beautifulsoup4>=4.13.4",
"python-docx>=1.2.0",
"youtube-transcript-api>=1.2.2",
"pymupdf>=1.26.6",
"lancedb~=0.5.4",
"tiktoken~=0.8.0",
"beautifulsoup4~=4.13.4",
"python-docx~=1.2.0",
"youtube-transcript-api~=1.2.2",
"pymupdf~=1.26.6",
]

View File

@@ -9,35 +9,35 @@ authors = [
requires-python = ">=3.10, <3.14"
dependencies = [
# Core Dependencies
"pydantic>=2.11.9",
"openai>=1.13.3",
"pydantic~=2.11.9",
"openai~=1.83.0",
"instructor>=1.3.3",
# Text Processing
"pdfplumber>=0.11.4",
"regex>=2024.9.11",
"pdfplumber~=0.11.4",
"regex~=2024.9.11",
# Telemetry and Monitoring
"opentelemetry-api>=1.30.0",
"opentelemetry-sdk>=1.30.0",
"opentelemetry-exporter-otlp-proto-http>=1.30.0",
"opentelemetry-api~=1.34.0",
"opentelemetry-sdk~=1.34.0",
"opentelemetry-exporter-otlp-proto-http~=1.34.0",
# Data Handling
"chromadb~=1.1.0",
"tokenizers>=0.20.3",
"openpyxl>=3.1.5",
"tokenizers~=0.20.3",
"openpyxl~=3.1.5",
# Authentication and Security
"python-dotenv>=1.1.1",
"pyjwt>=2.9.0",
"python-dotenv~=1.1.1",
"pyjwt~=2.9.0",
# Configuration and Utils
"click>=8.1.7",
"appdirs>=1.4.4",
"jsonref>=1.1.0",
"json-repair==0.25.2",
"uv>=0.4.25",
"tomli-w>=1.1.0",
"tomli>=2.0.2",
"json5>=0.10.0",
"portalocker==2.7.0",
"pydantic-settings>=2.10.1",
"mcp>=1.16.0",
"click~=8.1.7",
"appdirs~=1.4.4",
"jsonref~=1.1.0",
"json-repair~=0.25.2",
"tomli-w~=1.1.0",
"tomli~=2.0.2",
"json5~=0.10.0",
"portalocker~=2.7.0",
"pydantic-settings~=2.10.1",
"mcp~=1.16.0",
"uv~=0.9.13",
]
[project.urls]
@@ -53,50 +53,48 @@ tools = [
embeddings = [
"tiktoken~=0.8.0"
]
pdfplumber = [
"pdfplumber>=0.11.4",
]
pandas = [
"pandas>=2.2.3",
"pandas~=2.2.3",
]
openpyxl = [
"openpyxl>=3.1.5",
"openpyxl~=3.1.5",
]
mem0 = ["mem0ai>=0.1.94"]
mem0 = ["mem0ai~=0.1.94"]
docling = [
"docling>=2.12.0",
"docling~=2.63.0",
]
qdrant = [
"qdrant-client[fastembed]>=1.14.3",
"qdrant-client[fastembed]~=1.14.3",
]
aws = [
"boto3>=1.40.38",
"boto3~=1.40.38",
"aiobotocore~=2.25.2",
]
watson = [
"ibm-watsonx-ai>=1.3.39",
"ibm-watsonx-ai~=1.3.39",
]
voyageai = [
"voyageai>=0.3.5",
"voyageai~=0.3.5",
]
litellm = [
"litellm>=1.74.9",
"litellm~=1.74.9",
]
bedrock = [
"boto3>=1.40.45",
"boto3~=1.40.45",
]
google-genai = [
"google-genai>=1.2.0",
"google-genai~=1.2.0",
]
azure-ai-inference = [
"azure-ai-inference>=1.0.0b9",
"azure-ai-inference~=1.0.0b9",
]
anthropic = [
"anthropic>=0.69.0",
"anthropic~=0.71.0",
]
a2a = [
a2a = [
"a2a-sdk~=0.3.10",
"httpx-auth>=0.23.1",
"httpx-sse>=0.4.0",
"httpx-auth~=0.23.1",
"httpx-sse~=0.4.0",
]

View File

@@ -57,7 +57,12 @@ if TYPE_CHECKING:
from litellm.litellm_core_utils.get_supported_openai_params import (
get_supported_openai_params,
)
from litellm.types.utils import ChatCompletionDeltaToolCall, Choices, ModelResponse
from litellm.types.utils import (
ChatCompletionDeltaToolCall,
Choices,
Function,
ModelResponse,
)
from litellm.utils import supports_response_schema
from crewai.agent.core import Agent
@@ -73,7 +78,12 @@ try:
from litellm.litellm_core_utils.get_supported_openai_params import (
get_supported_openai_params,
)
from litellm.types.utils import ChatCompletionDeltaToolCall, Choices, ModelResponse
from litellm.types.utils import (
ChatCompletionDeltaToolCall,
Choices,
Function,
ModelResponse,
)
from litellm.utils import supports_response_schema
LITELLM_AVAILABLE = True
@@ -84,6 +94,7 @@ except ImportError:
ContextWindowExceededError = Exception # type: ignore
get_supported_openai_params = None # type: ignore
ChatCompletionDeltaToolCall = None # type: ignore
Function = None # type: ignore
ModelResponse = None # type: ignore
supports_response_schema = None # type: ignore
CustomLogger = None # type: ignore
@@ -610,7 +621,9 @@ class LLM(BaseLLM):
self.callbacks = callbacks
self.context_window_size = 0
self.reasoning_effort = reasoning_effort
self.additional_params = kwargs
self.additional_params = {
k: v for k, v in kwargs.items() if k not in ("is_litellm", "provider")
}
self.is_anthropic = self._is_anthropic_model(model)
self.stream = stream
self.interceptor = interceptor
@@ -1204,6 +1217,281 @@ class LLM(BaseLLM):
)
return text_response
async def _ahandle_non_streaming_response(
self,
params: dict[str, Any],
callbacks: list[Any] | None = None,
available_functions: dict[str, Any] | None = None,
from_task: Task | None = None,
from_agent: Agent | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Handle an async non-streaming response from the LLM.
Args:
params: Parameters for the completion call
callbacks: Optional list of callback functions
available_functions: Dict of available functions
from_task: Optional Task that invoked the LLM
from_agent: Optional Agent that invoked the LLM
response_model: Optional Response model
Returns:
str: The response text
"""
if response_model and self.is_litellm:
from crewai.utilities.internal_instructor import InternalInstructor
messages = params.get("messages", [])
if not messages:
raise ValueError("Messages are required when using response_model")
combined_content = "\n\n".join(
f"{msg['role'].upper()}: {msg['content']}" for msg in messages
)
instructor_instance = InternalInstructor(
content=combined_content,
model=response_model,
llm=self,
)
result = instructor_instance.to_pydantic()
structured_response = result.model_dump_json()
self._handle_emit_call_events(
response=structured_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return structured_response
try:
if response_model:
params["response_model"] = response_model
response = await litellm.acompletion(**params)
except ContextWindowExceededError as e:
raise LLMContextLengthExceededError(str(e)) from e
if response_model is not None:
if isinstance(response, BaseModel):
structured_response = response.model_dump_json()
self._handle_emit_call_events(
response=structured_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return structured_response
response_message = cast(Choices, cast(ModelResponse, response).choices)[
0
].message
text_response = response_message.content or ""
if callbacks and len(callbacks) > 0:
for callback in callbacks:
if hasattr(callback, "log_success_event"):
usage_info = getattr(response, "usage", None)
if usage_info:
callback.log_success_event(
kwargs=params,
response_obj={"usage": usage_info},
start_time=0,
end_time=0,
)
tool_calls = getattr(response_message, "tool_calls", [])
if (not tool_calls or not available_functions) and text_response:
self._handle_emit_call_events(
response=text_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return text_response
if tool_calls and not available_functions and not text_response:
return tool_calls
tool_result = self._handle_tool_call(
tool_calls, available_functions, from_task, from_agent
)
if tool_result is not None:
return tool_result
self._handle_emit_call_events(
response=text_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return text_response
async def _ahandle_streaming_response(
self,
params: dict[str, Any],
callbacks: list[Any] | None = None,
available_functions: dict[str, Any] | None = None,
from_task: Task | None = None,
from_agent: Agent | None = None,
response_model: type[BaseModel] | None = None,
) -> Any:
"""Handle an async streaming response from the LLM.
Args:
params: Parameters for the completion call
callbacks: Optional list of callback functions
available_functions: Dict of available functions
from_task: Optional task object
from_agent: Optional agent object
response_model: Optional response model
Returns:
str: The complete response text
"""
full_response = ""
chunk_count = 0
usage_info = None
accumulated_tool_args: defaultdict[int, AccumulatedToolArgs] = defaultdict(
AccumulatedToolArgs
)
params["stream"] = True
params["stream_options"] = {"include_usage": True}
try:
async for chunk in await litellm.acompletion(**params):
chunk_count += 1
chunk_content = None
try:
choices = None
if isinstance(chunk, dict) and "choices" in chunk:
choices = chunk["choices"]
elif hasattr(chunk, "choices"):
if not isinstance(chunk.choices, type):
choices = chunk.choices
if hasattr(chunk, "usage") and chunk.usage is not None:
usage_info = chunk.usage
if choices and len(choices) > 0:
first_choice = choices[0]
delta = None
if isinstance(first_choice, dict):
delta = first_choice.get("delta", {})
elif hasattr(first_choice, "delta"):
delta = first_choice.delta
if delta:
if isinstance(delta, dict):
chunk_content = delta.get("content")
elif hasattr(delta, "content"):
chunk_content = delta.content
tool_calls: list[ChatCompletionDeltaToolCall] | None = None
if isinstance(delta, dict):
tool_calls = delta.get("tool_calls")
elif hasattr(delta, "tool_calls"):
tool_calls = delta.tool_calls
if tool_calls:
for tool_call in tool_calls:
idx = tool_call.index
if tool_call.function:
if tool_call.function.name:
accumulated_tool_args[
idx
].function.name = tool_call.function.name
if tool_call.function.arguments:
accumulated_tool_args[
idx
].function.arguments += (
tool_call.function.arguments
)
except (AttributeError, KeyError, IndexError, TypeError):
pass
if chunk_content:
full_response += chunk_content
crewai_event_bus.emit(
self,
event=LLMStreamChunkEvent(
chunk=chunk_content,
from_task=from_task,
from_agent=from_agent,
),
)
if callbacks and len(callbacks) > 0 and usage_info:
for callback in callbacks:
if hasattr(callback, "log_success_event"):
callback.log_success_event(
kwargs=params,
response_obj={"usage": usage_info},
start_time=0,
end_time=0,
)
if accumulated_tool_args and available_functions:
# Convert accumulated tool args to ChatCompletionDeltaToolCall objects
tool_calls_list: list[ChatCompletionDeltaToolCall] = [
ChatCompletionDeltaToolCall(
index=idx,
function=Function(
name=tool_arg.function.name,
arguments=tool_arg.function.arguments,
),
)
for idx, tool_arg in accumulated_tool_args.items()
if tool_arg.function.name
]
if tool_calls_list:
result = self._handle_streaming_tool_calls(
tool_calls=tool_calls_list,
accumulated_tool_args=accumulated_tool_args,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
if result is not None:
return result
self._handle_emit_call_events(
response=full_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params.get("messages"),
)
return full_response
except ContextWindowExceededError as e:
raise LLMContextLengthExceededError(str(e)) from e
except Exception:
if chunk_count == 0:
raise
if full_response:
self._handle_emit_call_events(
response=full_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params.get("messages"),
)
return full_response
raise
def _handle_tool_call(
self,
tool_calls: list[Any],
@@ -1421,6 +1709,128 @@ class LLM(BaseLLM):
)
raise
async def acall(
self,
messages: str | list[LLMMessage],
tools: list[dict[str, BaseTool]] | None = None,
callbacks: list[Any] | None = None,
available_functions: dict[str, Any] | None = None,
from_task: Task | None = None,
from_agent: Agent | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Async high-level LLM call method.
Args:
messages: Input messages for the LLM.
Can be a string or list of message dictionaries.
If string, it will be converted to a single user message.
If list, each dict must have 'role' and 'content' keys.
tools: Optional list of tool schemas for function calling.
Each tool should define its name, description, and parameters.
callbacks: Optional list of callback functions to be executed
during and after the LLM call.
available_functions: Optional dict mapping function names to callables
that can be invoked by the LLM.
from_task: Optional Task that invoked the LLM
from_agent: Optional Agent that invoked the LLM
response_model: Optional Model that contains a pydantic response model.
Returns:
Union[str, Any]: Either a text response from the LLM (str) or
the result of a tool function call (Any).
Raises:
TypeError: If messages format is invalid
ValueError: If response format is not supported
LLMContextLengthExceededError: If input exceeds model's context limit
"""
crewai_event_bus.emit(
self,
event=LLMCallStartedEvent(
messages=messages,
tools=tools,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
model=self.model,
),
)
self._validate_call_params()
if isinstance(messages, str):
messages = [{"role": "user", "content": messages}]
if "o1" in self.model.lower():
for message in messages:
if message.get("role") == "system":
msg_role: Literal["assistant"] = "assistant"
message["role"] = msg_role
with suppress_warnings():
if callbacks and len(callbacks) > 0:
self.set_callbacks(callbacks)
try:
params = self._prepare_completion_params(messages, tools)
if self.stream:
return await self._ahandle_streaming_response(
params=params,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
response_model=response_model,
)
return await self._ahandle_non_streaming_response(
params=params,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
response_model=response_model,
)
except LLMContextLengthExceededError:
raise
except Exception as e:
unsupported_stop = "Unsupported parameter" in str(
e
) and "'stop'" in str(e)
if unsupported_stop:
if (
"additional_drop_params" in self.additional_params
and isinstance(
self.additional_params["additional_drop_params"], list
)
):
self.additional_params["additional_drop_params"].append("stop")
else:
self.additional_params = {"additional_drop_params": ["stop"]}
logging.info("Retrying LLM call without the unsupported 'stop'")
return await self.acall(
messages,
tools=tools,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
response_model=response_model,
)
crewai_event_bus.emit(
self,
event=LLMCallFailedEvent(
error=str(e), from_task=from_task, from_agent=from_agent
),
)
raise
def _handle_emit_call_events(
self,
response: Any,

View File

@@ -158,6 +158,44 @@ class BaseLLM(ABC):
RuntimeError: If the LLM request fails for other reasons.
"""
async def acall(
self,
messages: str | list[LLMMessage],
tools: list[dict[str, BaseTool]] | None = None,
callbacks: list[Any] | None = None,
available_functions: dict[str, Any] | None = None,
from_task: Task | None = None,
from_agent: Agent | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Call the LLM with the given messages.
Args:
messages: Input messages for the LLM.
Can be a string or list of message dictionaries.
If string, it will be converted to a single user message.
If list, each dict must have 'role' and 'content' keys.
tools: Optional list of tool schemas for function calling.
Each tool should define its name, description, and parameters.
callbacks: Optional list of callback functions to be executed
during and after the LLM call.
available_functions: Optional dict mapping function names to callables
that can be invoked by the LLM.
from_task: Optional task caller to be used for the LLM call.
from_agent: Optional agent caller to be used for the LLM call.
response_model: Optional response model to be used for the LLM call.
Returns:
Either a text response from the LLM (str) or
the result of a tool function call (Any).
Raises:
ValueError: If the messages format is invalid.
TimeoutError: If the LLM request times out.
RuntimeError: If the LLM request fails for other reasons.
"""
raise NotImplementedError
def _convert_tools_for_interference(
self, tools: list[dict[str, BaseTool]]
) -> list[dict[str, BaseTool]]:

View File

@@ -9,7 +9,7 @@ from pydantic import BaseModel
from crewai.events.types.llm_events import LLMCallType
from crewai.llms.base_llm import BaseLLM
from crewai.llms.hooks.transport import HTTPTransport
from crewai.llms.hooks.transport import AsyncHTTPTransport, HTTPTransport
from crewai.utilities.agent_utils import is_context_length_exceeded
from crewai.utilities.exceptions.context_window_exceeding_exception import (
LLMContextLengthExceededError,
@@ -21,7 +21,7 @@ if TYPE_CHECKING:
from crewai.llms.hooks.base import BaseInterceptor
try:
from anthropic import Anthropic
from anthropic import Anthropic, AsyncAnthropic
from anthropic.types import Message
from anthropic.types.tool_use_block import ToolUseBlock
import httpx
@@ -84,15 +84,20 @@ class AnthropicCompletion(BaseLLM):
self.client = Anthropic(**self._get_client_params())
async_client_params = self._get_client_params()
if self.interceptor:
async_transport = AsyncHTTPTransport(interceptor=self.interceptor)
async_http_client = httpx.AsyncClient(transport=async_transport)
async_client_params["http_client"] = async_http_client
self.async_client = AsyncAnthropic(**async_client_params)
# Store completion parameters
self.max_tokens = max_tokens
self.top_p = top_p
self.stream = stream
self.stop_sequences = stop_sequences or []
# Model-specific settings
self.is_claude_3 = "claude-3" in model.lower()
self.supports_tools = self.is_claude_3 # Claude 3+ supports tool use
self.supports_tools = True
@property
def stop(self) -> list[str]:
@@ -213,6 +218,72 @@ class AnthropicCompletion(BaseLLM):
)
raise
async def acall(
self,
messages: str | list[LLMMessage],
tools: list[dict[str, Any]] | None = None,
callbacks: list[Any] | None = None,
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Async call to Anthropic messages API.
Args:
messages: Input messages for the chat completion
tools: List of tool/function definitions
callbacks: Callback functions (not used in native implementation)
available_functions: Available functions for tool calling
from_task: Task that initiated the call
from_agent: Agent that initiated the call
Returns:
Chat completion response or tool call result
"""
try:
self._emit_call_started_event(
messages=messages,
tools=tools,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
formatted_messages, system_message = self._format_messages_for_anthropic(
messages
)
completion_params = self._prepare_completion_params(
formatted_messages, system_message, tools
)
if self.stream:
return await self._ahandle_streaming_completion(
completion_params,
available_functions,
from_task,
from_agent,
response_model,
)
return await self._ahandle_completion(
completion_params,
available_functions,
from_task,
from_agent,
response_model,
)
except Exception as e:
error_msg = f"Anthropic API call failed: {e!s}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise
def _prepare_completion_params(
self,
messages: list[LLMMessage],
@@ -546,7 +617,7 @@ class AnthropicCompletion(BaseLLM):
# Execute the tool
result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args, # type: ignore
function_args=function_args,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
@@ -626,6 +697,275 @@ class AnthropicCompletion(BaseLLM):
return tool_results[0]["content"]
raise e
async def _ahandle_completion(
self,
params: dict[str, Any],
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Handle non-streaming async message completion."""
if response_model:
structured_tool = {
"name": "structured_output",
"description": "Returns structured data according to the schema",
"input_schema": response_model.model_json_schema(),
}
params["tools"] = [structured_tool]
params["tool_choice"] = {"type": "tool", "name": "structured_output"}
try:
response: Message = await self.async_client.messages.create(**params)
except Exception as e:
if is_context_length_exceeded(e):
logging.error(f"Context window exceeded: {e}")
raise LLMContextLengthExceededError(str(e)) from e
raise e from e
usage = self._extract_anthropic_token_usage(response)
self._track_token_usage_internal(usage)
if response_model and response.content:
tool_uses = [
block for block in response.content if isinstance(block, ToolUseBlock)
]
if tool_uses and tool_uses[0].name == "structured_output":
structured_data = tool_uses[0].input
structured_json = json.dumps(structured_data)
self._emit_call_completed_event(
response=structured_json,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return structured_json
if response.content and available_functions:
tool_uses = [
block for block in response.content if isinstance(block, ToolUseBlock)
]
if tool_uses:
return await self._ahandle_tool_use_conversation(
response,
tool_uses,
params,
available_functions,
from_task,
from_agent,
)
content = ""
if response.content:
for content_block in response.content:
if hasattr(content_block, "text"):
content += content_block.text
content = self._apply_stop_words(content)
self._emit_call_completed_event(
response=content,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
if usage.get("total_tokens", 0) > 0:
logging.info(f"Anthropic API usage: {usage}")
return content
async def _ahandle_streaming_completion(
self,
params: dict[str, Any],
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str:
"""Handle async streaming message completion."""
if response_model:
structured_tool = {
"name": "structured_output",
"description": "Returns structured data according to the schema",
"input_schema": response_model.model_json_schema(),
}
params["tools"] = [structured_tool]
params["tool_choice"] = {"type": "tool", "name": "structured_output"}
full_response = ""
stream_params = {k: v for k, v in params.items() if k != "stream"}
async with self.async_client.messages.stream(**stream_params) as stream:
async for event in stream:
if hasattr(event, "delta") and hasattr(event.delta, "text"):
text_delta = event.delta.text
full_response += text_delta
self._emit_stream_chunk_event(
chunk=text_delta,
from_task=from_task,
from_agent=from_agent,
)
final_message: Message = await stream.get_final_message()
usage = self._extract_anthropic_token_usage(final_message)
self._track_token_usage_internal(usage)
if response_model and final_message.content:
tool_uses = [
block
for block in final_message.content
if isinstance(block, ToolUseBlock)
]
if tool_uses and tool_uses[0].name == "structured_output":
structured_data = tool_uses[0].input
structured_json = json.dumps(structured_data)
self._emit_call_completed_event(
response=structured_json,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return structured_json
if final_message.content and available_functions:
tool_uses = [
block
for block in final_message.content
if isinstance(block, ToolUseBlock)
]
if tool_uses:
return await self._ahandle_tool_use_conversation(
final_message,
tool_uses,
params,
available_functions,
from_task,
from_agent,
)
full_response = self._apply_stop_words(full_response)
self._emit_call_completed_event(
response=full_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return full_response
async def _ahandle_tool_use_conversation(
self,
initial_response: Message,
tool_uses: list[ToolUseBlock],
params: dict[str, Any],
available_functions: dict[str, Any],
from_task: Any | None = None,
from_agent: Any | None = None,
) -> str:
"""Handle the complete async tool use conversation flow.
This implements the proper Anthropic tool use pattern:
1. Claude requests tool use
2. We execute the tools
3. We send tool results back to Claude
4. Claude processes results and generates final response
"""
tool_results = []
for tool_use in tool_uses:
function_name = tool_use.name
function_args = tool_use.input
result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
tool_result = {
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": str(result)
if result is not None
else "Tool execution completed",
}
tool_results.append(tool_result)
follow_up_params = params.copy()
assistant_message = {"role": "assistant", "content": initial_response.content}
user_message = {"role": "user", "content": tool_results}
follow_up_params["messages"] = params["messages"] + [
assistant_message,
user_message,
]
try:
final_response: Message = await self.async_client.messages.create(
**follow_up_params
)
follow_up_usage = self._extract_anthropic_token_usage(final_response)
self._track_token_usage_internal(follow_up_usage)
final_content = ""
if final_response.content:
for content_block in final_response.content:
if hasattr(content_block, "text"):
final_content += content_block.text
final_content = self._apply_stop_words(final_content)
self._emit_call_completed_event(
response=final_content,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=follow_up_params["messages"],
)
total_usage = {
"input_tokens": follow_up_usage.get("input_tokens", 0),
"output_tokens": follow_up_usage.get("output_tokens", 0),
"total_tokens": follow_up_usage.get("total_tokens", 0),
}
if total_usage.get("total_tokens", 0) > 0:
logging.info(f"Anthropic API tool conversation usage: {total_usage}")
return final_content
except Exception as e:
if is_context_length_exceeded(e):
logging.error(f"Context window exceeded in tool follow-up: {e}")
raise LLMContextLengthExceededError(str(e)) from e
logging.error(f"Tool follow-up conversation failed: {e}")
if tool_results:
return tool_results[0]["content"]
raise e
def supports_function_calling(self) -> bool:
"""Check if the model supports function calling."""
return self.supports_tools

View File

@@ -6,6 +6,7 @@ import os
from typing import TYPE_CHECKING, Any
from pydantic import BaseModel
from typing_extensions import Self
from crewai.utilities.agent_utils import is_context_length_exceeded
from crewai.utilities.converter import generate_model_description
@@ -24,6 +25,9 @@ try:
from azure.ai.inference import (
ChatCompletionsClient,
)
from azure.ai.inference.aio import (
ChatCompletionsClient as AsyncChatCompletionsClient,
)
from azure.ai.inference.models import (
ChatCompletions,
ChatCompletionsToolCall,
@@ -135,6 +139,8 @@ class AzureCompletion(BaseLLM):
self.client = ChatCompletionsClient(**client_kwargs) # type: ignore[arg-type]
self.async_client = AsyncChatCompletionsClient(**client_kwargs) # type: ignore[arg-type]
self.top_p = top_p
self.frequency_penalty = frequency_penalty
self.presence_penalty = presence_penalty
@@ -258,6 +264,88 @@ class AzureCompletion(BaseLLM):
)
raise
async def acall(
self,
messages: str | list[LLMMessage],
tools: list[dict[str, BaseTool]] | None = None,
callbacks: list[Any] | None = None,
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Call Azure AI Inference chat completions API asynchronously.
Args:
messages: Input messages for the chat completion
tools: List of tool/function definitions
callbacks: Callback functions (not used in native implementation)
available_functions: Available functions for tool calling
from_task: Task that initiated the call
from_agent: Agent that initiated the call
response_model: Pydantic model for structured output
Returns:
Chat completion response or tool call result
"""
try:
self._emit_call_started_event(
messages=messages,
tools=tools,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
formatted_messages = self._format_messages_for_azure(messages)
completion_params = self._prepare_completion_params(
formatted_messages, tools, response_model
)
if self.stream:
return await self._ahandle_streaming_completion(
completion_params,
available_functions,
from_task,
from_agent,
response_model,
)
return await self._ahandle_completion(
completion_params,
available_functions,
from_task,
from_agent,
response_model,
)
except HttpResponseError as e:
if e.status_code == 401:
error_msg = "Azure authentication failed. Check your API key."
elif e.status_code == 404:
error_msg = (
f"Azure endpoint not found. Check endpoint URL: {self.endpoint}"
)
elif e.status_code == 429:
error_msg = "Azure API rate limit exceeded. Please retry later."
else:
error_msg = f"Azure API HTTP error: {e.status_code} - {e.message}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise
except Exception as e:
error_msg = f"Azure API call failed: {e!s}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise
def _prepare_completion_params(
self,
messages: list[LLMMessage],
@@ -556,6 +644,170 @@ class AzureCompletion(BaseLLM):
return full_response
async def _ahandle_completion(
self,
params: dict[str, Any],
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Handle non-streaming chat completion asynchronously."""
try:
response: ChatCompletions = await self.async_client.complete(**params)
if not response.choices:
raise ValueError("No choices returned from Azure API")
choice = response.choices[0]
message = choice.message
usage = self._extract_azure_token_usage(response)
self._track_token_usage_internal(usage)
if response_model and self.is_openai_model:
content = message.content or ""
try:
structured_data = response_model.model_validate_json(content)
structured_json = structured_data.model_dump_json()
self._emit_call_completed_event(
response=structured_json,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return structured_json
except Exception as e:
error_msg = f"Failed to validate structured output with model {response_model.__name__}: {e}"
logging.error(error_msg)
raise ValueError(error_msg) from e
if message.tool_calls and available_functions:
tool_call = message.tool_calls[0] # Handle first tool call
if isinstance(tool_call, ChatCompletionsToolCall):
function_name = tool_call.function.name
try:
function_args = json.loads(tool_call.function.arguments)
except json.JSONDecodeError as e:
logging.error(f"Failed to parse tool arguments: {e}")
function_args = {}
result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
if result is not None:
return result
content = message.content or ""
content = self._apply_stop_words(content)
self._emit_call_completed_event(
response=content,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
except Exception as e:
if is_context_length_exceeded(e):
logging.error(f"Context window exceeded: {e}")
raise LLMContextLengthExceededError(str(e)) from e
error_msg = f"Azure API call failed: {e!s}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise e
return content
async def _ahandle_streaming_completion(
self,
params: dict[str, Any],
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str:
"""Handle streaming chat completion asynchronously."""
full_response = ""
tool_calls = {}
stream = await self.async_client.complete(**params)
async for update in stream:
if isinstance(update, StreamingChatCompletionsUpdate):
if update.choices:
choice = update.choices[0]
if choice.delta and choice.delta.content:
content_delta = choice.delta.content
full_response += content_delta
self._emit_stream_chunk_event(
chunk=content_delta,
from_task=from_task,
from_agent=from_agent,
)
if choice.delta and choice.delta.tool_calls:
for tool_call in choice.delta.tool_calls:
call_id = tool_call.id or "default"
if call_id not in tool_calls:
tool_calls[call_id] = {
"name": "",
"arguments": "",
}
if tool_call.function and tool_call.function.name:
tool_calls[call_id]["name"] = tool_call.function.name
if tool_call.function and tool_call.function.arguments:
tool_calls[call_id]["arguments"] += (
tool_call.function.arguments
)
if tool_calls and available_functions:
for call_data in tool_calls.values():
function_name = call_data["name"]
try:
function_args = json.loads(call_data["arguments"])
except json.JSONDecodeError as e:
logging.error(f"Failed to parse streamed tool arguments: {e}")
continue
result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
if result is not None:
return result
full_response = self._apply_stop_words(full_response)
self._emit_call_completed_event(
response=full_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return full_response
def supports_function_calling(self) -> bool:
"""Check if the model supports function calling."""
# Azure OpenAI models support function calling
@@ -609,3 +861,20 @@ class AzureCompletion(BaseLLM):
"total_tokens": getattr(usage, "total_tokens", 0),
}
return {"total_tokens": 0}
async def aclose(self) -> None:
"""Close the async client and clean up resources.
This ensures proper cleanup of the underlying aiohttp session
to avoid unclosed connector warnings.
"""
if hasattr(self.async_client, "close"):
await self.async_client.close()
async def __aenter__(self) -> Self:
"""Async context manager entry."""
return self
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
"""Async context manager exit."""
await self.aclose()

View File

@@ -1,6 +1,8 @@
from __future__ import annotations
from collections.abc import Mapping, Sequence
from contextlib import AsyncExitStack
import json
import logging
import os
from typing import TYPE_CHECKING, Any, TypedDict, cast
@@ -42,6 +44,16 @@ except ImportError:
'AWS Bedrock native provider not available, to install: uv add "crewai[bedrock]"'
) from None
try:
from aiobotocore.session import ( # type: ignore[import-untyped]
get_session as get_aiobotocore_session,
)
AIOBOTOCORE_AVAILABLE = True
except ImportError:
AIOBOTOCORE_AVAILABLE = False
get_aiobotocore_session = None
if TYPE_CHECKING:
@@ -221,6 +233,15 @@ class BedrockCompletion(BaseLLM):
self.client = session.client("bedrock-runtime", config=config)
self.region_name = region_name
self.aws_access_key_id = aws_access_key_id or os.getenv("AWS_ACCESS_KEY_ID")
self.aws_secret_access_key = aws_secret_access_key or os.getenv(
"AWS_SECRET_ACCESS_KEY"
)
self.aws_session_token = aws_session_token or os.getenv("AWS_SESSION_TOKEN")
self._async_exit_stack = AsyncExitStack() if AIOBOTOCORE_AVAILABLE else None
self._async_client_initialized = False
# Store completion parameters
self.max_tokens = max_tokens
self.top_p = top_p
@@ -354,6 +375,110 @@ class BedrockCompletion(BaseLLM):
)
raise
async def acall(
self,
messages: str | list[LLMMessage],
tools: list[dict[Any, Any]] | None = None,
callbacks: list[Any] | None = None,
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Async call to AWS Bedrock Converse API.
Args:
messages: Input messages as string or list of message dicts.
tools: Optional list of tool definitions.
callbacks: Optional list of callback handlers.
available_functions: Optional dict mapping function names to callables.
from_task: Optional task context for events.
from_agent: Optional agent context for events.
response_model: Optional Pydantic model for structured output.
Returns:
Generated text response or structured output.
Raises:
NotImplementedError: If aiobotocore is not installed.
LLMContextLengthExceededError: If context window is exceeded.
"""
if not AIOBOTOCORE_AVAILABLE:
raise NotImplementedError(
"Async support for AWS Bedrock requires aiobotocore. "
'Install with: uv add "crewai[bedrock-async]"'
)
try:
self._emit_call_started_event(
messages=messages,
tools=tools,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
formatted_messages, system_message = self._format_messages_for_converse(
messages # type: ignore[arg-type]
)
body: BedrockConverseRequestBody = {
"inferenceConfig": self._get_inference_config(),
}
if system_message:
body["system"] = cast(
"list[SystemContentBlockTypeDef]",
cast(object, [{"text": system_message}]),
)
if tools:
tool_config: ToolConfigurationTypeDef = {
"tools": cast(
"Sequence[ToolTypeDef]",
cast(object, self._format_tools_for_converse(tools)),
)
}
body["toolConfig"] = tool_config
if self.guardrail_config:
guardrail_config: GuardrailConfigurationTypeDef = cast(
"GuardrailConfigurationTypeDef", cast(object, self.guardrail_config)
)
body["guardrailConfig"] = guardrail_config
if self.additional_model_request_fields:
body["additionalModelRequestFields"] = (
self.additional_model_request_fields
)
if self.additional_model_response_field_paths:
body["additionalModelResponseFieldPaths"] = (
self.additional_model_response_field_paths
)
if self.stream:
return await self._ahandle_streaming_converse(
formatted_messages, body, available_functions, from_task, from_agent
)
return await self._ahandle_converse(
formatted_messages, body, available_functions, from_task, from_agent
)
except Exception as e:
if is_context_length_exceeded(e):
logging.error(f"Context window exceeded: {e}")
raise LLMContextLengthExceededError(str(e)) from e
error_msg = f"AWS Bedrock API call failed: {e!s}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise
def _handle_converse(
self,
messages: list[dict[str, Any]],
@@ -565,6 +690,341 @@ class BedrockCompletion(BaseLLM):
role = event["messageStart"].get("role")
logging.debug(f"Streaming message started with role: {role}")
elif "contentBlockStart" in event:
start = event["contentBlockStart"].get("start", {})
if "toolUse" in start:
current_tool_use = start["toolUse"]
tool_use_id = current_tool_use.get("toolUseId")
logging.debug(
f"Tool use started in stream: {json.dumps(current_tool_use)} (ID: {tool_use_id})"
)
elif "contentBlockDelta" in event:
delta = event["contentBlockDelta"]["delta"]
if "text" in delta:
text_chunk = delta["text"]
logging.debug(f"Streaming text chunk: {text_chunk[:50]}...")
full_response += text_chunk
self._emit_stream_chunk_event(
chunk=text_chunk,
from_task=from_task,
from_agent=from_agent,
)
elif "toolUse" in delta and current_tool_use:
tool_input = delta["toolUse"].get("input", "")
if tool_input:
logging.debug(f"Tool input delta: {tool_input}")
elif "contentBlockStop" in event:
logging.debug("Content block stopped in stream")
if current_tool_use and available_functions:
function_name = current_tool_use["name"]
function_args = cast(
dict[str, Any], current_tool_use.get("input", {})
)
tool_result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
if tool_result is not None and tool_use_id:
messages.append(
{
"role": "assistant",
"content": [{"toolUse": current_tool_use}],
}
)
messages.append(
{
"role": "user",
"content": [
{
"toolResult": {
"toolUseId": tool_use_id,
"content": [
{"text": str(tool_result)}
],
}
}
],
}
)
return self._handle_converse(
messages,
body,
available_functions,
from_task,
from_agent,
)
current_tool_use = None
tool_use_id = None
elif "messageStop" in event:
stop_reason = event["messageStop"].get("stopReason")
logging.debug(f"Streaming message stopped: {stop_reason}")
if stop_reason == "max_tokens":
logging.warning(
"Streaming response truncated due to max_tokens"
)
elif stop_reason == "content_filtered":
logging.warning(
"Streaming response filtered due to content policy"
)
break
elif "metadata" in event:
metadata = event["metadata"]
if "usage" in metadata:
usage_metrics = metadata["usage"]
self._track_token_usage_internal(usage_metrics)
logging.debug(f"Token usage: {usage_metrics}")
if "trace" in metadata:
logging.debug(
f"Trace information available: {metadata['trace']}"
)
except ClientError as e:
error_msg = self._handle_client_error(e)
raise RuntimeError(error_msg) from e
except BotoCoreError as e:
error_msg = f"Bedrock streaming connection error: {e}"
logging.error(error_msg)
raise ConnectionError(error_msg) from e
full_response = self._apply_stop_words(full_response)
if not full_response or full_response.strip() == "":
logging.warning("Bedrock streaming returned empty content, using fallback")
full_response = (
"I apologize, but I couldn't generate a response. Please try again."
)
self._emit_call_completed_event(
response=full_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=messages,
)
return full_response
async def _ensure_async_client(self) -> Any:
"""Ensure async client is initialized and return it."""
if not self._async_client_initialized and get_aiobotocore_session:
if self._async_exit_stack is None:
raise RuntimeError(
"Async exit stack not initialized - aiobotocore not available"
)
session = get_aiobotocore_session()
client = await self._async_exit_stack.enter_async_context(
session.create_client(
"bedrock-runtime",
region_name=self.region_name,
aws_access_key_id=self.aws_access_key_id,
aws_secret_access_key=self.aws_secret_access_key,
aws_session_token=self.aws_session_token,
)
)
self._async_client = client
self._async_client_initialized = True
return self._async_client
async def _ahandle_converse(
self,
messages: list[dict[str, Any]],
body: BedrockConverseRequestBody,
available_functions: Mapping[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
) -> str:
"""Handle async non-streaming converse API call."""
try:
if not messages:
raise ValueError("Messages cannot be empty")
for i, msg in enumerate(messages):
if (
not isinstance(msg, dict)
or "role" not in msg
or "content" not in msg
):
raise ValueError(f"Invalid message format at index {i}")
async_client = await self._ensure_async_client()
response = await async_client.converse(
modelId=self.model_id,
messages=cast(
"Sequence[MessageTypeDef | MessageOutputTypeDef]",
cast(object, messages),
),
**body,
)
if "usage" in response:
self._track_token_usage_internal(response["usage"])
stop_reason = response.get("stopReason")
if stop_reason:
logging.debug(f"Response stop reason: {stop_reason}")
if stop_reason == "max_tokens":
logging.warning("Response truncated due to max_tokens limit")
elif stop_reason == "content_filtered":
logging.warning("Response was filtered due to content policy")
output = response.get("output", {})
message = output.get("message", {})
content = message.get("content", [])
if not content:
logging.warning("No content in Bedrock response")
return (
"I apologize, but I received an empty response. Please try again."
)
text_content = ""
for content_block in content:
if "text" in content_block:
text_content += content_block["text"]
elif "toolUse" in content_block and available_functions:
tool_use_block = content_block["toolUse"]
tool_use_id = tool_use_block.get("toolUseId")
function_name = tool_use_block["name"]
function_args = tool_use_block.get("input", {})
logging.debug(
f"Tool use requested: {function_name} with ID {tool_use_id}"
)
tool_result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=dict(available_functions),
from_task=from_task,
from_agent=from_agent,
)
if tool_result is not None:
messages.append(
{
"role": "assistant",
"content": [{"toolUse": tool_use_block}],
}
)
messages.append(
{
"role": "user",
"content": [
{
"toolResult": {
"toolUseId": tool_use_id,
"content": [{"text": str(tool_result)}],
}
}
],
}
)
return await self._ahandle_converse(
messages, body, available_functions, from_task, from_agent
)
text_content = self._apply_stop_words(text_content)
if not text_content or text_content.strip() == "":
logging.warning("Extracted empty text content from Bedrock response")
text_content = "I apologize, but I couldn't generate a proper response. Please try again."
self._emit_call_completed_event(
response=text_content,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=messages,
)
return text_content
except ClientError as e:
error_code = e.response.get("Error", {}).get("Code", "Unknown")
error_msg = e.response.get("Error", {}).get("Message", str(e))
logging.error(f"AWS Bedrock ClientError ({error_code}): {error_msg}")
if error_code == "ValidationException":
if "last turn" in error_msg and "user message" in error_msg:
raise ValueError(
f"Conversation format error: {error_msg}. Check message alternation."
) from e
raise ValueError(f"Request validation failed: {error_msg}") from e
if error_code == "AccessDeniedException":
raise PermissionError(
f"Access denied to model {self.model_id}: {error_msg}"
) from e
if error_code == "ResourceNotFoundException":
raise ValueError(f"Model {self.model_id} not found: {error_msg}") from e
if error_code == "ThrottlingException":
raise RuntimeError(
f"API throttled, please retry later: {error_msg}"
) from e
if error_code == "ModelTimeoutException":
raise TimeoutError(f"Model request timed out: {error_msg}") from e
if error_code == "ServiceQuotaExceededException":
raise RuntimeError(f"Service quota exceeded: {error_msg}") from e
if error_code == "ModelNotReadyException":
raise RuntimeError(
f"Model {self.model_id} not ready: {error_msg}"
) from e
if error_code == "ModelErrorException":
raise RuntimeError(f"Model error: {error_msg}") from e
if error_code == "InternalServerException":
raise RuntimeError(f"Internal server error: {error_msg}") from e
if error_code == "ServiceUnavailableException":
raise RuntimeError(f"Service unavailable: {error_msg}") from e
raise RuntimeError(f"Bedrock API error ({error_code}): {error_msg}") from e
except BotoCoreError as e:
error_msg = f"Bedrock connection error: {e}"
logging.error(error_msg)
raise ConnectionError(error_msg) from e
except Exception as e:
error_msg = f"Unexpected error in Bedrock converse call: {e}"
logging.error(error_msg)
raise RuntimeError(error_msg) from e
async def _ahandle_streaming_converse(
self,
messages: list[dict[str, Any]],
body: BedrockConverseRequestBody,
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
) -> str:
"""Handle async streaming converse API call."""
full_response = ""
current_tool_use = None
tool_use_id = None
try:
async_client = await self._ensure_async_client()
response = await async_client.converse_stream(
modelId=self.model_id,
messages=cast(
"Sequence[MessageTypeDef | MessageOutputTypeDef]",
cast(object, messages),
),
**body,
)
stream = response.get("stream")
if stream:
async for event in stream:
if "messageStart" in event:
role = event["messageStart"].get("role")
logging.debug(f"Streaming message started with role: {role}")
elif "contentBlockStart" in event:
start = event["contentBlockStart"].get("start", {})
if "toolUse" in start:
@@ -590,17 +1050,14 @@ class BedrockCompletion(BaseLLM):
if tool_input:
logging.debug(f"Tool input delta: {tool_input}")
# Content block stop - end of a content block
elif "contentBlockStop" in event:
logging.debug("Content block stopped in stream")
# If we were accumulating a tool use, it's now complete
if current_tool_use and available_functions:
function_name = current_tool_use["name"]
function_args = cast(
dict[str, Any], current_tool_use.get("input", {})
)
# Execute tool
tool_result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
@@ -610,7 +1067,6 @@ class BedrockCompletion(BaseLLM):
)
if tool_result is not None and tool_use_id:
# Continue conversation with tool result
messages.append(
{
"role": "assistant",
@@ -634,8 +1090,7 @@ class BedrockCompletion(BaseLLM):
}
)
# Recursive call - note this switches to non-streaming
return self._handle_converse(
return await self._ahandle_converse(
messages,
body,
available_functions,
@@ -643,10 +1098,9 @@ class BedrockCompletion(BaseLLM):
from_agent,
)
current_tool_use = None
tool_use_id = None
current_tool_use = None
tool_use_id = None
# Message stop - end of entire message
elif "messageStop" in event:
stop_reason = event["messageStop"].get("stopReason")
logging.debug(f"Streaming message stopped: {stop_reason}")
@@ -660,7 +1114,6 @@ class BedrockCompletion(BaseLLM):
)
break
# Metadata - contains usage information and trace details
elif "metadata" in event:
metadata = event["metadata"]
if "usage" in metadata:
@@ -680,17 +1133,14 @@ class BedrockCompletion(BaseLLM):
logging.error(error_msg)
raise ConnectionError(error_msg) from e
# Apply stop words to full response
full_response = self._apply_stop_words(full_response)
# Ensure we don't return empty content
if not full_response or full_response.strip() == "":
logging.warning("Bedrock streaming returned empty content, using fallback")
full_response = (
"I apologize, but I couldn't generate a response. Please try again."
)
# Emit completion event
self._emit_call_completed_event(
response=full_response,
call_type=LLMCallType.LLM_CALL,

View File

@@ -1,13 +1,14 @@
from __future__ import annotations
import logging
import os
import re
from typing import Any, cast
from typing import TYPE_CHECKING, Any
from pydantic import BaseModel
from crewai.events.types.llm_events import LLMCallType
from crewai.llms.base_llm import BaseLLM
from crewai.llms.hooks.base import BaseInterceptor
from crewai.utilities.agent_utils import is_context_length_exceeded
from crewai.utilities.exceptions.context_window_exceeding_exception import (
LLMContextLengthExceededError,
@@ -15,10 +16,15 @@ from crewai.utilities.exceptions.context_window_exceeding_exception import (
from crewai.utilities.types import LLMMessage
if TYPE_CHECKING:
from crewai.llms.hooks.base import BaseInterceptor
try:
from google import genai # type: ignore[import-untyped]
from google.genai import types # type: ignore[import-untyped]
from google.genai.errors import APIError # type: ignore[import-untyped]
from google import genai
from google.genai import types
from google.genai.errors import APIError
from google.genai.types import GenerateContentResponse, Schema
except ImportError:
raise ImportError(
'Google Gen AI native provider not available, to install: uv add "crewai[google-genai]"'
@@ -102,7 +108,9 @@ class GeminiCompletion(BaseLLM):
# Model-specific settings
version_match = re.search(r"gemini-(\d+(?:\.\d+)?)", model.lower())
self.supports_tools = bool(version_match and float(version_match.group(1)) >= 1.5)
self.supports_tools = bool(
version_match and float(version_match.group(1)) >= 1.5
)
@property
def stop(self) -> list[str]:
@@ -128,7 +136,7 @@ class GeminiCompletion(BaseLLM):
else:
self.stop_sequences = []
def _initialize_client(self, use_vertexai: bool = False) -> genai.Client: # type: ignore[no-any-unimported]
def _initialize_client(self, use_vertexai: bool = False) -> genai.Client:
"""Initialize the Google Gen AI client with proper parameter handling.
Args:
@@ -277,7 +285,84 @@ class GeminiCompletion(BaseLLM):
)
raise
def _prepare_generation_config( # type: ignore[no-any-unimported]
async def acall(
self,
messages: str | list[LLMMessage],
tools: list[dict[str, Any]] | None = None,
callbacks: list[Any] | None = None,
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Async call to Google Gemini generate content API.
Args:
messages: Input messages for the chat completion
tools: List of tool/function definitions
callbacks: Callback functions (not used as token counts are handled by the response)
available_functions: Available functions for tool calling
from_task: Task that initiated the call
from_agent: Agent that initiated the call
Returns:
Chat completion response or tool call result
"""
try:
self._emit_call_started_event(
messages=messages,
tools=tools,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
self.tools = tools
formatted_content, system_instruction = self._format_messages_for_gemini(
messages
)
config = self._prepare_generation_config(
system_instruction, tools, response_model
)
if self.stream:
return await self._ahandle_streaming_completion(
formatted_content,
config,
available_functions,
from_task,
from_agent,
response_model,
)
return await self._ahandle_completion(
formatted_content,
system_instruction,
config,
available_functions,
from_task,
from_agent,
response_model,
)
except APIError as e:
error_msg = f"Google Gemini API error: {e.code} - {e.message}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise
except Exception as e:
error_msg = f"Google Gemini API call failed: {e!s}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise
def _prepare_generation_config(
self,
system_instruction: str | None = None,
tools: list[dict[str, Any]] | None = None,
@@ -294,7 +379,7 @@ class GeminiCompletion(BaseLLM):
GenerateContentConfig object for Gemini API
"""
self.tools = tools
config_params = {}
config_params: dict[str, Any] = {}
# Add system instruction if present
if system_instruction:
@@ -329,7 +414,7 @@ class GeminiCompletion(BaseLLM):
return types.GenerateContentConfig(**config_params)
def _convert_tools_for_interference( # type: ignore[no-any-unimported]
def _convert_tools_for_interference( # type: ignore[override]
self, tools: list[dict[str, Any]]
) -> list[types.Tool]:
"""Convert CrewAI tool format to Gemini function declaration format."""
@@ -346,7 +431,7 @@ class GeminiCompletion(BaseLLM):
)
# Add parameters if present - ensure parameters is a dict
if parameters and isinstance(parameters, dict):
if parameters and isinstance(parameters, Schema):
function_declaration.parameters = parameters
gemini_tool = types.Tool(function_declarations=[function_declaration])
@@ -354,7 +439,7 @@ class GeminiCompletion(BaseLLM):
return gemini_tools
def _format_messages_for_gemini( # type: ignore[no-any-unimported]
def _format_messages_for_gemini(
self, messages: str | list[LLMMessage]
) -> tuple[list[types.Content], str | None]:
"""Format messages for Gemini API.
@@ -373,32 +458,41 @@ class GeminiCompletion(BaseLLM):
# Use base class formatting first
base_formatted = super()._format_messages(messages)
contents = []
contents: list[types.Content] = []
system_instruction: str | None = None
for message in base_formatted:
role = message.get("role")
content = message.get("content", "")
role = message["role"]
content = message["content"]
# Convert content to string if it's a list
if isinstance(content, list):
text_content = " ".join(
str(item.get("text", "")) if isinstance(item, dict) else str(item)
for item in content
)
else:
text_content = str(content) if content else ""
if role == "system":
# Extract system instruction - Gemini handles it separately
if system_instruction:
system_instruction += f"\n\n{content}"
system_instruction += f"\n\n{text_content}"
else:
system_instruction = cast(str, content)
system_instruction = text_content
else:
# Convert role for Gemini (assistant -> model)
gemini_role = "model" if role == "assistant" else "user"
# Create Content object
gemini_content = types.Content(
role=gemini_role, parts=[types.Part.from_text(text=content)]
role=gemini_role, parts=[types.Part.from_text(text=text_content)]
)
contents.append(gemini_content)
return contents, system_instruction
def _handle_completion( # type: ignore[no-any-unimported]
def _handle_completion(
self,
contents: list[types.Content],
system_instruction: str | None,
@@ -409,14 +503,14 @@ class GeminiCompletion(BaseLLM):
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Handle non-streaming content generation."""
api_params = {
"model": self.model,
"contents": contents,
"config": config,
}
try:
response = self.client.models.generate_content(**api_params)
# The API accepts list[Content] but mypy is overly strict about variance
contents_for_api: Any = contents
response = self.client.models.generate_content(
model=self.model,
contents=contents_for_api,
config=config,
)
usage = self._extract_token_usage(response)
except Exception as e:
@@ -433,6 +527,8 @@ class GeminiCompletion(BaseLLM):
for part in candidate.content.parts:
if hasattr(part, "function_call") and part.function_call:
function_name = part.function_call.name
if function_name is None:
continue
function_args = (
dict(part.function_call.args)
if part.function_call.args
@@ -442,7 +538,7 @@ class GeminiCompletion(BaseLLM):
result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=available_functions, # type: ignore
available_functions=available_functions or {},
from_task=from_task,
from_agent=from_agent,
)
@@ -450,7 +546,7 @@ class GeminiCompletion(BaseLLM):
if result is not None:
return result
content = response.text if hasattr(response, "text") else ""
content = response.text or ""
content = self._apply_stop_words(content)
messages_for_event = self._convert_contents_to_dict(contents)
@@ -465,7 +561,7 @@ class GeminiCompletion(BaseLLM):
return content
def _handle_streaming_completion( # type: ignore[no-any-unimported]
def _handle_streaming_completion(
self,
contents: list[types.Content],
config: types.GenerateContentConfig,
@@ -476,16 +572,16 @@ class GeminiCompletion(BaseLLM):
) -> str:
"""Handle streaming content generation."""
full_response = ""
function_calls = {}
function_calls: dict[str, dict[str, Any]] = {}
api_params = {
"model": self.model,
"contents": contents,
"config": config,
}
for chunk in self.client.models.generate_content_stream(**api_params):
if hasattr(chunk, "text") and chunk.text:
# The API accepts list[Content] but mypy is overly strict about variance
contents_for_api: Any = contents
for chunk in self.client.models.generate_content_stream(
model=self.model,
contents=contents_for_api,
config=config,
):
if chunk.text:
full_response += chunk.text
self._emit_stream_chunk_event(
chunk=chunk.text,
@@ -493,7 +589,7 @@ class GeminiCompletion(BaseLLM):
from_agent=from_agent,
)
if hasattr(chunk, "candidates") and chunk.candidates:
if chunk.candidates:
candidate = chunk.candidates[0]
if candidate.content and candidate.content.parts:
for part in candidate.content.parts:
@@ -513,6 +609,14 @@ class GeminiCompletion(BaseLLM):
function_name = call_data["name"]
function_args = call_data["args"]
# Skip if function_name is None
if not isinstance(function_name, str):
continue
# Ensure function_args is a dict
if not isinstance(function_args, dict):
function_args = {}
# Execute tool
result = self._handle_tool_execution(
function_name=function_name,
@@ -537,6 +641,154 @@ class GeminiCompletion(BaseLLM):
return full_response
async def _ahandle_completion(
self,
contents: list[types.Content],
system_instruction: str | None,
config: types.GenerateContentConfig,
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Handle async non-streaming content generation."""
try:
# The API accepts list[Content] but mypy is overly strict about variance
contents_for_api: Any = contents
response = await self.client.aio.models.generate_content(
model=self.model,
contents=contents_for_api,
config=config,
)
usage = self._extract_token_usage(response)
except Exception as e:
if is_context_length_exceeded(e):
logging.error(f"Context window exceeded: {e}")
raise LLMContextLengthExceededError(str(e)) from e
raise e from e
self._track_token_usage_internal(usage)
if response.candidates and (self.tools or available_functions):
candidate = response.candidates[0]
if candidate.content and candidate.content.parts:
for part in candidate.content.parts:
if hasattr(part, "function_call") and part.function_call:
function_name = part.function_call.name
if function_name is None:
continue
function_args = (
dict(part.function_call.args)
if part.function_call.args
else {}
)
result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=available_functions or {},
from_task=from_task,
from_agent=from_agent,
)
if result is not None:
return result
content = response.text or ""
content = self._apply_stop_words(content)
messages_for_event = self._convert_contents_to_dict(contents)
self._emit_call_completed_event(
response=content,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=messages_for_event,
)
return content
async def _ahandle_streaming_completion(
self,
contents: list[types.Content],
config: types.GenerateContentConfig,
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str:
"""Handle async streaming content generation."""
full_response = ""
function_calls: dict[str, dict[str, Any]] = {}
# The API accepts list[Content] but mypy is overly strict about variance
contents_for_api: Any = contents
stream = await self.client.aio.models.generate_content_stream(
model=self.model,
contents=contents_for_api,
config=config,
)
async for chunk in stream:
if chunk.text:
full_response += chunk.text
self._emit_stream_chunk_event(
chunk=chunk.text,
from_task=from_task,
from_agent=from_agent,
)
if chunk.candidates:
candidate = chunk.candidates[0]
if candidate.content and candidate.content.parts:
for part in candidate.content.parts:
if hasattr(part, "function_call") and part.function_call:
call_id = part.function_call.name or "default"
if call_id not in function_calls:
function_calls[call_id] = {
"name": part.function_call.name,
"args": dict(part.function_call.args)
if part.function_call.args
else {},
}
if function_calls and available_functions:
for call_data in function_calls.values():
function_name = call_data["name"]
function_args = call_data["args"]
# Skip if function_name is None
if not isinstance(function_name, str):
continue
# Ensure function_args is a dict
if not isinstance(function_args, dict):
function_args = {}
result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
if result is not None:
return result
messages_for_event = self._convert_contents_to_dict(contents)
self._emit_call_completed_event(
response=full_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=messages_for_event,
)
return full_response
def supports_function_calling(self) -> bool:
"""Check if the model supports function calling."""
return self.supports_tools
@@ -583,9 +835,10 @@ class GeminiCompletion(BaseLLM):
# Default context window size for Gemini models
return int(1048576 * CONTEXT_WINDOW_USAGE_RATIO) # 1M tokens
def _extract_token_usage(self, response: dict[str, Any]) -> dict[str, Any]:
@staticmethod
def _extract_token_usage(response: GenerateContentResponse) -> dict[str, Any]:
"""Extract token usage from Gemini response."""
if hasattr(response, "usage_metadata"):
if response.usage_metadata:
usage = response.usage_metadata
return {
"prompt_token_count": getattr(usage, "prompt_token_count", 0),
@@ -595,21 +848,23 @@ class GeminiCompletion(BaseLLM):
}
return {"total_tokens": 0}
def _convert_contents_to_dict( # type: ignore[no-any-unimported]
def _convert_contents_to_dict(
self,
contents: list[types.Content],
) -> list[dict[str, str]]:
"""Convert contents to dict format."""
return [
{
"role": "assistant"
if content_obj.role == "model"
else content_obj.role,
"content": " ".join(
part.text
for part in content_obj.parts
if hasattr(part, "text") and part.text
),
}
for content_obj in contents
]
result: list[dict[str, str]] = []
for content_obj in contents:
role = content_obj.role
if role == "model":
role = "assistant"
elif role is None:
role = "user"
parts = content_obj.parts or []
content = " ".join(
part.text for part in parts if hasattr(part, "text") and part.text
)
result.append({"role": role, "content": content})
return result

View File

@@ -1,13 +1,13 @@
from __future__ import annotations
from collections.abc import Iterator
from collections.abc import AsyncIterator, Iterator
import json
import logging
import os
from typing import TYPE_CHECKING, Any
import httpx
from openai import APIConnectionError, NotFoundError, OpenAI
from openai import APIConnectionError, AsyncOpenAI, NotFoundError, OpenAI
from openai.types.chat import ChatCompletion, ChatCompletionChunk
from openai.types.chat.chat_completion import Choice
from openai.types.chat.chat_completion_chunk import ChoiceDelta
@@ -15,7 +15,7 @@ from pydantic import BaseModel
from crewai.events.types.llm_events import LLMCallType
from crewai.llms.base_llm import BaseLLM
from crewai.llms.hooks.transport import HTTPTransport
from crewai.llms.hooks.transport import AsyncHTTPTransport, HTTPTransport
from crewai.utilities.agent_utils import is_context_length_exceeded
from crewai.utilities.converter import generate_model_description
from crewai.utilities.exceptions.context_window_exceeding_exception import (
@@ -101,6 +101,14 @@ class OpenAICompletion(BaseLLM):
self.client = OpenAI(**client_config)
async_client_config = self._get_client_params()
if self.interceptor:
async_transport = AsyncHTTPTransport(interceptor=self.interceptor)
async_http_client = httpx.AsyncClient(transport=async_transport)
async_client_config["http_client"] = async_http_client
self.async_client = AsyncOpenAI(**async_client_config)
# Completion parameters
self.top_p = top_p
self.frequency_penalty = frequency_penalty
@@ -210,6 +218,71 @@ class OpenAICompletion(BaseLLM):
)
raise
async def acall(
self,
messages: str | list[LLMMessage],
tools: list[dict[str, BaseTool]] | None = None,
callbacks: list[Any] | None = None,
available_functions: dict[str, Any] | None = None,
from_task: Task | None = None,
from_agent: Agent | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Async call to OpenAI chat completion API.
Args:
messages: Input messages for the chat completion
tools: list of tool/function definitions
callbacks: Callback functions (not used in native implementation)
available_functions: Available functions for tool calling
from_task: Task that initiated the call
from_agent: Agent that initiated the call
response_model: Response model for structured output.
Returns:
Chat completion response or tool call result
"""
try:
self._emit_call_started_event(
messages=messages,
tools=tools,
callbacks=callbacks,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
formatted_messages = self._format_messages(messages)
completion_params = self._prepare_completion_params(
messages=formatted_messages, tools=tools
)
if self.stream:
return await self._ahandle_streaming_completion(
params=completion_params,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
response_model=response_model,
)
return await self._ahandle_completion(
params=completion_params,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
response_model=response_model,
)
except Exception as e:
error_msg = f"OpenAI API call failed: {e!s}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise
def _prepare_completion_params(
self, messages: list[LLMMessage], tools: list[dict[str, BaseTool]] | None = None
) -> dict[str, Any]:
@@ -352,10 +425,10 @@ class OpenAICompletion(BaseLLM):
if message.tool_calls and available_functions:
tool_call = message.tool_calls[0]
function_name = tool_call.function.name # type: ignore[union-attr]
function_name = tool_call.function.name
try:
function_args = json.loads(tool_call.function.arguments) # type: ignore[union-attr]
function_args = json.loads(tool_call.function.arguments)
except json.JSONDecodeError as e:
logging.error(f"Failed to parse tool arguments: {e}")
function_args = {}
@@ -564,6 +637,266 @@ class OpenAICompletion(BaseLLM):
return full_response
async def _ahandle_completion(
self,
params: dict[str, Any],
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str | Any:
"""Handle non-streaming async chat completion."""
try:
if response_model:
parse_params = {
k: v for k, v in params.items() if k != "response_format"
}
parsed_response = await self.async_client.beta.chat.completions.parse(
**parse_params,
response_format=response_model,
)
math_reasoning = parsed_response.choices[0].message
if math_reasoning.refusal:
pass
usage = self._extract_openai_token_usage(parsed_response)
self._track_token_usage_internal(usage)
parsed_object = parsed_response.choices[0].message.parsed
if parsed_object:
structured_json = parsed_object.model_dump_json()
self._emit_call_completed_event(
response=structured_json,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return structured_json
response: ChatCompletion = await self.async_client.chat.completions.create(
**params
)
usage = self._extract_openai_token_usage(response)
self._track_token_usage_internal(usage)
choice: Choice = response.choices[0]
message = choice.message
if message.tool_calls and available_functions:
tool_call = message.tool_calls[0]
function_name = tool_call.function.name
try:
function_args = json.loads(tool_call.function.arguments)
except json.JSONDecodeError as e:
logging.error(f"Failed to parse tool arguments: {e}")
function_args = {}
result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
if result is not None:
return result
content = message.content or ""
content = self._apply_stop_words(content)
if self.response_format and isinstance(self.response_format, type):
try:
structured_result = self._validate_structured_output(
content, self.response_format
)
self._emit_call_completed_event(
response=structured_result,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return structured_result
except ValueError as e:
logging.warning(f"Structured output validation failed: {e}")
self._emit_call_completed_event(
response=content,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
if usage.get("total_tokens", 0) > 0:
logging.info(f"OpenAI API usage: {usage}")
except NotFoundError as e:
error_msg = f"Model {self.model} not found: {e}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise ValueError(error_msg) from e
except APIConnectionError as e:
error_msg = f"Failed to connect to OpenAI API: {e}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise ConnectionError(error_msg) from e
except Exception as e:
if is_context_length_exceeded(e):
logging.error(f"Context window exceeded: {e}")
raise LLMContextLengthExceededError(str(e)) from e
error_msg = f"OpenAI API call failed: {e!s}"
logging.error(error_msg)
self._emit_call_failed_event(
error=error_msg, from_task=from_task, from_agent=from_agent
)
raise e from e
return content
async def _ahandle_streaming_completion(
self,
params: dict[str, Any],
available_functions: dict[str, Any] | None = None,
from_task: Any | None = None,
from_agent: Any | None = None,
response_model: type[BaseModel] | None = None,
) -> str:
"""Handle async streaming chat completion."""
full_response = ""
tool_calls = {}
if response_model:
completion_stream: AsyncIterator[
ChatCompletionChunk
] = await self.async_client.chat.completions.create(**params)
accumulated_content = ""
async for chunk in completion_stream:
if not chunk.choices:
continue
choice = chunk.choices[0]
delta: ChoiceDelta = choice.delta
if delta.content:
accumulated_content += delta.content
self._emit_stream_chunk_event(
chunk=delta.content,
from_task=from_task,
from_agent=from_agent,
)
try:
parsed_object = response_model.model_validate_json(accumulated_content)
structured_json = parsed_object.model_dump_json()
self._emit_call_completed_event(
response=structured_json,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return structured_json
except Exception as e:
logging.error(f"Failed to parse structured output from stream: {e}")
self._emit_call_completed_event(
response=accumulated_content,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return accumulated_content
stream: AsyncIterator[
ChatCompletionChunk
] = await self.async_client.chat.completions.create(**params)
async for chunk in stream:
if not chunk.choices:
continue
choice = chunk.choices[0]
chunk_delta: ChoiceDelta = choice.delta
if chunk_delta.content:
full_response += chunk_delta.content
self._emit_stream_chunk_event(
chunk=chunk_delta.content,
from_task=from_task,
from_agent=from_agent,
)
if chunk_delta.tool_calls:
for tool_call in chunk_delta.tool_calls:
call_id = tool_call.id or "default"
if call_id not in tool_calls:
tool_calls[call_id] = {
"name": "",
"arguments": "",
}
if tool_call.function and tool_call.function.name:
tool_calls[call_id]["name"] = tool_call.function.name
if tool_call.function and tool_call.function.arguments:
tool_calls[call_id]["arguments"] += tool_call.function.arguments
if tool_calls and available_functions:
for call_data in tool_calls.values():
function_name = call_data["name"]
arguments = call_data["arguments"]
if not function_name or not arguments:
continue
if function_name not in available_functions:
logging.warning(
f"Function '{function_name}' not found in available functions"
)
continue
try:
function_args = json.loads(arguments)
except json.JSONDecodeError as e:
logging.error(f"Failed to parse streamed tool arguments: {e}")
continue
result = self._handle_tool_execution(
function_name=function_name,
function_args=function_args,
available_functions=available_functions,
from_task=from_task,
from_agent=from_agent,
)
if result is not None:
return result
full_response = self._apply_stop_words(full_response)
self._emit_call_completed_event(
response=full_response,
call_type=LLMCallType.LLM_CALL,
from_task=from_task,
from_agent=from_agent,
messages=params["messages"],
)
return full_response
def supports_function_calling(self) -> bool:
"""Check if the model supports function calling."""
return not self.is_o1_model

View File

@@ -0,0 +1,202 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Say hello"}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '113'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAA3SQTUsDMRCG/0qci5dUdmsLNhdP0uqpCIJFJIRk2C7NzqzJpLaU/nfZYvELT8O8
zzPDMAfoOGAEAz66EnCUmQhlNBmNq/G0mtYT0NAGMNDlxlb19bLfuFVDT/P54zatHmbPd7slgwbZ
9zhYmLNrEDQkjkPgcm6zOBLQ4JkEScC8HM6+4G4gp2JggTHyhbqXy6yo9aiEVYcoas/lSi34XbmE
Q6MCt9Qo4eD2t3B81ZCFe5vQZSYwgBSslETwCTK+FSSPYKjEqKGcjjQHaKkvYoU3SBnMTIN3fo3W
J3TSMtmfvDrzhC78x86zw3rs19hhctFOu7/+F63Xv+lRAxf5HtU3GjKmbevRSosJDAyPDS4FOB4/
AAAA//8DAOKqeZbJAQAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:05:47 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-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
retry-after:
- '13'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '3942'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Say hello"}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '113'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAA3TQTUsDMRAG4L8S55zC7tKi5lL01IInEYuIhJBMu8HsZE0mtkvZ/y5bLH7haWCe
d4ZhjtBFhwEU2GCKw1mORMiz+aypmkW1qOcgwTtQ0OWdruqrwpu7x277VC4fOn9obra39f0GJPDQ
45TCnM0OQUKKYWqYnH1mQwwSbCRGYlDPx3Oe8TDJqShYYQjxQqziXpiEYohFuOhpJzg6MyzFOgtu
MaEwNHA7wVpYQ6LF0J/Se8/tEsYXCZljrxOaHAkUIDnNJRF8Qsa3gmQRFJUQJJTT0eoInvrCmuMr
UgZ1LcEa26K2CQ37SPqnV2dPaNx/dp6d1mPfYofJBL3o/ua/tG5/6yghFv7eaioJGdO7t6jZYwIF
06OdSQ7G8QMAAP//AwATs5vC2QEAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:07:23 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-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
retry-after:
- '37'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '3783'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,203 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"My name is Alice."},{"role":"assistant","content":"Hello
Alice! Nice to meet you."},{"role":"user","content":"What is my name?"}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '230'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJBbSwMxEIX/SjnPqez2Apq3vqv4oIKKhJAM3WB2siaTYi3732WLxRs+
DZzvm2E4B/TJU4SGi7Z6mpfETDJfzRfNYt2s2xUUgodGX7amaW+X7dXd+83qMd9vNmlfLy/y7rqD
guwHmiwqxW4JCjnFKbClhCKWBQousRAL9NPh5Au9TeQ4NB5SzTO2Pc1CmW1icHSG8VmhSBpMJlsS
Q4PYG6mZ8QkKvVZiR9BcY1Soxw/0AYGHKkbSC3GBXrYKzrqOjMtkJSQ2P4XmxDNZ/x877U73aeio
p2yjWfd//S/adr/pqJCqfI/OFQrlXXBkJFCGxtSat9ljHD8AAAD//wMAr8g7PaYBAAA=
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:05:52 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-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
retry-after:
- '9'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2159'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"My name is Alice."},{"role":"assistant","content":"Hello
Alice! Nice to meet you."},{"role":"user","content":"What is my name?"}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '230'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJBLa8MwDID/itHZHUnXsM63nrfjVjbGMMYWjZkjZ5ZcVkr++0hp2Yud
hPR9eqAjDDlgAgM+uRpwwZkIZbFaLJtl13TtCjTEAAYG3tmmXT3ddfdr3qJ7GLebtS/5Nh4eQYMc
RpwtZHY7BA0lp7ngmCOLIwENPpMgCZiX48UX/JjJKRh4zrUocgOqyGqToketHKtDrkpyCmoGNKdF
jQX3MVdW541XML1qYMmjLeg4ExhAClZqITgDxveK5BEM1ZQ01NOp5giRxipW8hsSg7luNXjne7S+
oJOYyf4Umgsv6MJ/7NI7z8exxwGLS7Yb/vpftO1/00lDrvK91N5oYCz76NFKxAIG5v8GVwJM0ycA
AAD//wMAqvdgpNABAAA=
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:07:37 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-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
retry-after:
- '25'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2275'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,398 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"What is 1+1?"}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '116'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAA3SQTUvDQBCG/0p4r24hqa2HBQ8iiiBCBfUisiy7QxtMZuPOrLSU/HdJsUgVTwPz
PPPBu0efInWwCJ0vkWaSmElni9m8ni/rZbOAQRth0cva1c3V/eolXq/87epRLoaHm7B9ftrdwUB3
A00Wifg1wSCnbmp4kVbUs8IgJFZihX3dH32l7UQOxaKpzqqmuqzmGN8MRNPgMnlJDAvi6LRkxjcQ
+ijEgWC5dJ1BOdy1e7Q8FHWa3okFtlkYBB825EImr21idyrUR57Jx//YcXbaT8OGesq+c8v+r/9D
m81vOhqkoiffnRsI5c82kNOWMiymsKLPEeP4BQAA//8DAAkpexydAQAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:05:58 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-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
retry-after:
- '3'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2286'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"What is 2+2?"}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '116'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAA3SQTUvEMBCG/0p5r2ahre0l4EUPXjyIrCCIhJAM27DtpCYTWVn636WLi6ziaWCe
Zz54j5iipxEabrTF0yZHZpJNt2nrtq/7poNC8NCY8s7UTX/b3w2BD/4pvtw/Pm/dw3TYWijI50yr
RTnbHUEhxXFt2JxDFssCBRdZiAX69Xj2hQ4rORWNtrqq2uqm6rC8KWSJs0lkc2RoEHsjJTG+Qab3
QuwImss4KpTTXX1E4LmIkbgnztBNp+CsG8i4RFZCZHMp1GeeyPr/2Hl23U/zQBMlO5p++uv/0Gb4
TReFWOTiu2uFTOkjODISKEFjDcvb5LEsXwAAAP//AwDa2+/dnQEAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:06:02 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-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
retry-after:
- '63'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '3909'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"What is 1+1?"}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '116'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJBNS8QwEIb/yvJezUKztJeAF8XVi0cPKhJCMrbFdtJNJrK69L9LFxdZ
xdPAPM988B4wxkADDPzgSqB1jswk63q9qTZN1egaCn2AwZhbW+nt9un+avf5+lCnm9C2d41cP97u
oSAfEy0W5exagkKKw9JwOfdZHAsUfGQhFpjnw8kX2i/kWAz0hV5drjaYXxSyxMkmcjkyDIiDlZIY
3yDTrhB7guEyDArleNUc0PNUxEp8I84wulbwzndkfSInfWR7LlQnnsiF/9hpdtlPU0cjJTfYZvzr
/1Dd/aazQixy9p1WyJTee09WekowWKIKLgXM8xcAAAD//wMApv4OQJsBAAA=
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:07:27 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-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
retry-after:
- '33'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2192'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"What is 2+2?"}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '116'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJBNS8QwEIb/SnmvZqGt3VUCHtYPFNSbFxUJIRm2xXZSk4koS/+7dHGR
VTwNzPPMB+8WQ/DUQ8P1NntapMBMsmgWdVkvy2XVQKHz0BjSxpRV9Xiyulpf3zyE+8vbVXUXTp/O
1xdQkM+RZotSshuCQgz93LApdUksCxRcYCEW6Oft3hf6mMmuaNTFUVEXZ0WD6UUhSRhNJJsCQ4PY
G8mR8Q0SvWViR9Cc+14h7+7qLToesxgJr8QJumoUnHUtGRfJShfYHArlnkey/j+2n53309jSQNH2
Zjn89X9o1f6mk0LIcvDdsUKi+N45MtJRhMYclrfRY5q+AAAA//8DAIkh+sidAQAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:07:32 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-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
retry-after:
- '31'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '4067'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,102 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Count from 1 to
10"}],"model":"claude-sonnet-4-0","stop_sequences":["END","STOP"],"stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '154'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAA3SQy2rDMBBFf0Xc9QRsJ+5DH1BKyaJ000UpQshDI2KPHD1MSvC/F4eGvuhq4J4z
w3BPGELHPTRcb0vHqxREOK82q6Zq2qqtNyD4DhpDejNV/fw0iR2OzaM8HO6aaesnu9/eg5DfR14s
Tsm+MQgx9EtgU/IpW8kguCCZJUO/nC5+5uNCzkOjJtWQWpPakGpJXZG6JnVD6pZUXWF+JaQcRhPZ
piDQYOlMLlHwCRIfCotjaCl9TyjnX/QJXsaSTQ57lgRdtwRn3Y6Ni2yzD2J+CtWFR7bdf+yyu9zn
cccDR9ubdvjrf9F695vOhFDy92jdEBLHyTs22XOExlJgZ2OHef4AAAD//wMAnJDpxrEBAAA=
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:07:25 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-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
retry-after:
- '36'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '1793'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,202 @@
interactions:
- request:
body: '{"max_tokens":10,"messages":[{"role":"user","content":"Write a very long
story about a dragon."}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '141'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJBNS8RADIb/SonXKbRLu8ic/TjoTRFBZBin2e3gNFMnqbvL0v8us1hk
FU+BPE+SlxxhiB0G0OCCnTosORKhlE25qlZt1dYNKPAdaBh4a6r6chfp+vnmdnfl67f1MDR37aEX
UCCHEbOFzHaLoCDFkBuW2bNYyo6LJEgC+uW4+IL703QuGi6Kxx6Le8tSPETaFnFTPFkM0h8Y5lcF
LHE0CS1Hyrfs3kh8R2L4RowfE5JD0DSFoGA6ZdFH8DROssi6Xitw1vVoXEIrPpI5F6qFJ7Tdf2yZ
zftx7HHAZINph7/+D63733RWECc5S1cpYEyf3qERjwk05Ad2NnUwz18AAAD//wMAo6EHIbEBAAA=
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:05: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-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
retry-after:
- '17'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2220'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":10,"messages":[{"role":"user","content":"Write a very long
story about a dragon."}],"model":"claude-sonnet-4-0","stream":false}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '141'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJDBasMwDIZfJWhXF5LS9uDboLeFXdatgzGMcbTE1JEzSxntSt59uCyM
buwk0PdJ+tEZ+thgAA0u2LHBBUcilMVqsSyX63JdrUCBb0BDz60pq9u7z229ve9P6B/r/ap7ftrU
ewEFchowW8hsWwQFKYbcsMyexVJ2XCRBEtAv59kXPF6mc9FwU+w6LGrLUjxEaov4Vuw6G/KOSDC9
KmCJg0loOVK+Zo9G4gGJ4Rsxvo9IDkHTGIKC8ZJGn8HTMMos62qjwFnXoXEJrfhI5looZ57QNv+x
eTbvx6HDHpMNZt3/9X9o1f2mk4I4ylW6UgFj+vAOjXhMoCG/sLGpgWn6AgAA//8DANbGCpGzAQAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:07:19 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-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
retry-after:
- '44'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '1085'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,104 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Return a JSON
object devoid of ```json{x}```, where x is the json object, with a ''greeting''
field"}],"model":"claude-sonnet-4-0","stream":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:
- '201'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAA3SQW0vEMBCF/0o8z1noXoqQF0FxXcUXQUSwEkI6dIPtpOairqX/Xaou3vBp4Hzf
HIYZ0PmaWijY1uSaZtEzU5qtZotiURblfAUJV0Ohi40u5ic3V4dntjy+dOuL29Nled2/rrslJNKu
p8miGE1DkAi+nQITo4vJcIKE9ZyIE9TdsPcTvUzkfSgMFQtRoQlEyXFTQYkKG2pbfyA2/llYw+Jc
fFSKnc8i+drsjipUPGK8l4jJ9zqQiZ6hQFzrlAPjE0R6zMSWoDi3rUR+P1UNcNznpJN/II5Qy1LC
GrslbQOZ5Dzrn0Kx54FM/R/b70791G+po2BaXXZ//S863/6mo4TP6Xu0mEtECk/Okk6OAhSm/9Ym
1BjHNwAAAP//AwCUmUxv0AEAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 11:25:56 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-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
retry-after:
- '5'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2611'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,104 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Tell me a short
fact"}],"model":"claude-sonnet-4-0","stream":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:
- '124'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJHBahtBDIZfZapLLuOwXtsE5uZDSa5toQ0pYZFnVO+QWWk70poa43cv
a2LSpvQk+L/vFwidYJBEBQLEglOihQoz2WK9aJt202yWa/CQEwQYdN81y7vP2yFvvn19+jJqu2sJ
P90rP4IHO440W6SKewIPVcocoGpWQzbwEIWN2CB8P119o18zuYwAD8J0dEwHqk5HyUU/uG2NPZIU
2Wc1dT0eyP2QiZOjlHeFXH8pZXbIMROb+7g/jpaRncmwU2c92o06mZeufNM07khY1UlJt3B+9qAm
Y1cJVRgCEKfOpsrwCpR+TsSRIPBUiofpcl84QeZxss7khVghLFsPEWNPXayEloW7v4Xmyith+h+7
duf9NPY0UMXSbYZ//Te67N/TsweZ7M9otfKgVA85UmeZKgSYn5KwJjiffwMAAP//AwA7i2ObBQIA
AA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 12:31:27 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-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
retry-after:
- '34'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2144'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,104 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Say hello in French"}],"model":"claude-sonnet-4-0","stream":false,"tool_choice":{"type":"tool","name":"structured_output"},"tools":[{"name":"structured_output","description":"Returns
structured data according to the schema","input_schema":{"description":"Response
model for greeting test.","properties":{"greeting":{"title":"Greeting","type":"string"},"language":{"title":"Language","type":"string"}},"required":["greeting","language"],"title":"GreetingResponse","type":"object"}}]}'
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:
- '539'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJBNT8MwDIb/i8+Z1JZViBxXBAeEhIDDJISiLDFtttQp+dg0Vf3vKJsK
GoiTZT+v/doeoXcaLXBQViaNi+CIMC6Wi6qo6qIul8DAaODQh1YU5Xq7X1fUdK7cUUpqczi0zXAA
BvE4YFZhCLJFYOCdzQUZgglRUgQGylFEisDfxlkfnbMiBZxdcp5EUd74j6fnl9t+tblujs2rvn/c
1/4BGJDsc1+IPqmYPGrhUhxSHm8oRz5C6xGjoRY4rBxtXfLAwEpqU16Nw51HUh1M0zuDEN0gPMrg
6HKdEwj4mZAUAqdkLYN0Oo6PZy8R3Q4pAF9eVQyUVB0K5VFG40hcKoqZe5T6Pzb3ZgMcOuzRSyvq
/q/+h5bdbzoxOL/ku1RfMQjo90ahiAb96X+StPQapukLAAD//wMAoHQshQMCAAA=
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 11:19:38 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-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
retry-after:
- '24'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2101'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,202 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"What is 2+2?"}],"model":"claude-sonnet-4-0","stream":false,"system":"You
are a helpful assistant."}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '156'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJBdS8QwEEX/SrmvZqHttggBXxZkffJBRESREJNhm7VNajIRdel/ly6u
X4tPA/ecmYG7wxAs9ZAwvc6WFil4T7xoFnVZt2VbNRBwFhJD2qiyurwYV9vl7dVN+35+d908bten
brWGAL+NNFuUkt4QBGLo50Cn5BJrzxAwwTN5hrzfHXym15nsh0RdnBR1cVY0mB4EEodRRdIpeEiQ
t4pz9PgEiZ4zeUOQPve9QN7/lTs4P2ZWHJ7IJ8i6FDDadKRMJM0uePVb+OKRtP2PHXbn+zR2NFDU
vWqHY/+bVt1fOgmEzD+jaimQKL44Q4odRUjMZVkdLabpAwAA//8DAJXQ8cKdAQAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:05: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-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
retry-after:
- '6'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '3195'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"What is 2+2?"}],"model":"claude-sonnet-4-0","stream":false,"system":"You
are a helpful assistant."}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '156'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJDLasMwEEV/xdxtZbBdeyPoIpu2dNduSxFCGhITe6RIoz4I/vfi0PRJ
VwP3nJmBe8QcPE3QcJMtnuocmEnqvu6abmiGtofC6KEx561p2k33ch1vStzEu+Gwf9jc93SbPBTk
LdJqUc52S1BIYVoDm/OYxbJAwQUWYoF+PJ59odeVnIZGV11UXXVV9VieFLKEaBLZHBgaxN5ISYwP
kOlQiB1Bc5kmhXL6q48YORYxEvbEGbprFJx1OzIukZUxsPkpfPJE1v/HzrvrfYo7minZyQzzX/+L
trvfdFEIRb5H7aVCpvQ8OjIyUoLGWpa3yWNZ3gEAAP//AwAKNgjwnQEAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:07:35 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-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
retry-after:
- '26'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2929'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,202 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Say the word ''test''
once"}],"model":"claude-sonnet-4-0","stream":false,"temperature":0.1}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '146'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAA3SQTUsDQQyG/8t7nsJu2bUyR8UeKp4EPYgMw0xol+5mtpOMqGX/u2yx+IWnkPd5
kkCOGFKkHhah9yXSQhIz6aJZLKtlW7V1A4MuwmKQravq9R1f3K5uNs3VZnu9uX982L8fLlcw0LeR
ZotE/JZgkFM/B16kE/WsMAiJlVhhn45nX+l1Jqcyd6KYng1E0+gyeUkMC+LotGTGJxA6FOJAsFz6
3qCcTtojOh6LOk17YoGtW4Pgw45cyOS1S+x+CtWZZ/LxP3aenffTuKOBsu9dO/z1v2i9+00ng1T0
e9QYCOWXLpDTjjIs5jdFnyOm6QMAAP//AwBU2mqKlwEAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:05: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-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
retry-after:
- '11'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '1875'
status:
code: 200
message: OK
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Say the word ''test''
once"}],"model":"claude-sonnet-4-0","stream":false,"temperature":0.1}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
anthropic-version:
- '2023-06-01'
connection:
- keep-alive
content-length:
- '146'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJBNa8MwDIb/y3t2ISnNxT9g9DB26qUbw7i21pglcmbJ20rJfx8pK/ti
J6H3eSSBzhhzpAEWYfA10koyM+lqs1o3667p2g0MUoTFKEfXtPvb8anttndpd3N4Ox267bg/7e5h
oKeJFotE/JFgUPKwBF4kiXpWGITMSqywD+err/S+kEtZOlHMjwaieXKFvGSGBXF0WgvjEwi9VOJA
sFyHwaBeTtozEk9VneZnYoFtO4PgQ08uFPKaMrufQnPlhXz8j11nl/009TRS8YPrxr/+F23733Q2
yFW/RxsDofKaAjlNVGCxvCn6EjHPHwAAAP//AwC0fV1qlwEAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:07:39 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-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
retry-after:
- '22'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '2032'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,106 @@
interactions:
- request:
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"What''s the weather
in San Francisco?"}],"model":"claude-sonnet-4-0","stream":false,"tools":[{"name":"get_weather","description":"Get
the current weather for a location","input_schema":{"type":"object","properties":{"location":{"type":"string","description":"The
city and state, e.g. San Francisco, CA"}},"required":["location"]}}]}'
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:
- '388'
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:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 0.75.0
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
x-stainless-timeout:
- NOT_GIVEN
method: POST
uri: https://api.anthropic.com/v1/messages
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//dJFLSyQxFIX/SjgbN2mp6odidiot2CroqLgYhhBT166iU0mb3PiYpv67
VDmNOuIq5H7n5AvJBm2oyEHBOpMrGqXgPfFoOhoX41kxK6eQaCootGmpi/Jo/8Kf/zqaXezP8+Fk
vrj9y0/tBBL8uqY+RSmZJUEiBtcPTEpNYuMZEjZ4Js9QvzfbPNNLT4ZF4XTHOWFrsivBNQmbYyTP
4pkM1xRF48W18eIkGm+bZIN4CFG8hryLTn6cGILTOdH23v0+66KcTPjuxt6Vq+fz8RlXi6v7S1Pf
QsKbtu8tifU/UV/168xQG7hgDTfBQ+GLW4rjQ3TdH4nEYa0jmTSEPukHkOgxk7cE5bNzEnl4HrV5
N2gOK/IJalqUEtbYmrSNNBj110Sx5ZFM9RPbdnsBrWtqKRqnZ+33/Act6/9pJxEyfx7tHUgkik+N
Jc0NRSj0n1qZWKHr3gAAAP//AwBJY3XJRQIAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 11:36:45 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-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
retry-after:
- '16'
strict-transport-security:
- STS-XXX
x-envoy-upstream-service-time:
- '1491'
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,67 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": "My name is Alice."}, {"role":
"assistant", "content": "Hello Alice! Nice to meet you."}, {"role": "user",
"content": "What is my name?"}], "stream": false}'
headers:
Accept:
- application/json
Content-Length:
- '198'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-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-4o-mini/chat/completions?api-version=2024-08-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":"Your
name is Alice.","refusal":null,"role":"assistant"}}],"created":1764567850,"id":"chatcmpl-ChqziTSL6LARm8AI85vLZFOoMTM1K","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_efad92c60b","usage":{"completion_tokens":6,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":33,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":39}}
'
headers:
Content-Length:
- '1229'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 05:44:10 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-4o-mini
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,128 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": "What is 1+1?"}], "stream": false}'
headers:
Accept:
- application/json
Content-Length:
- '76'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-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-4o-mini/chat/completions?api-version=2024-08-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":"1
+ 1 equals 2.","refusal":null,"role":"assistant"}}],"created":1764567853,"id":"chatcmpl-ChqzlM6m1r8ArJ1YkgNe1OS0in7Ln","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_efad92c60b","usage":{"completion_tokens":9,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":14,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":23}}
'
headers:
Content-Length:
- '1225'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 05:44:13 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-4o-mini
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": "user", "content": "What is 2+2?"}], "stream": false}'
headers:
Accept:
- application/json
Content-Length:
- '76'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-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-4o-mini/chat/completions?api-version=2024-08-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":"2
+ 2 equals 4.","refusal":null,"role":"assistant"}}],"created":1764567853,"id":"chatcmpl-ChqzlKZGfvbsPi7z77civqMvNjNIJ","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_efad92c60b","usage":{"completion_tokens":9,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":14,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":23}}
'
headers:
Content-Length:
- '1225'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 05:44:13 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-4o-mini
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,65 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": "Say hello"}], "stream": false}'
headers:
Accept:
- application/json
Content-Length:
- '73'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-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-4o-mini/chat/completions?api-version=2024-08-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":"Hello!
How can I assist you today?","refusal":null,"role":"assistant"}}],"created":1764567851,"id":"chatcmpl-ChqzjZ0Xva3tyU2En6zq99QbWb6aZ","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_efad92c60b","usage":{"completion_tokens":10,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":9,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":19}}
'
headers:
Content-Length:
- '1244'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 05:44:12 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-4o-mini
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,66 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": "Write a very long story about
a dragon."}], "stream": false, "max_tokens": 10}'
headers:
Accept:
- application/json
Content-Length:
- '121'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-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-4o-mini/chat/completions?api-version=2024-08-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":"length","index":0,"logprobs":null,"message":{"annotations":[],"content":"In
a time long forgotten, when the great mountains","refusal":null,"role":"assistant"}}],"created":1764567851,"id":"chatcmpl-ChqzjjWOdxGije5zYNJClj8VPhGlW","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_efad92c60b","usage":{"completion_tokens":10,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":16,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":26}}
'
headers:
Content-Length:
- '1263'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 05:44:11 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-4o-mini
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,68 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": "Tell me a short fact"}], "stream":
false, "frequency_penalty": 0.5, "max_tokens": 100, "presence_penalty": 0.3,
"temperature": 0.7, "top_p": 0.9}'
headers:
Accept:
- application/json
Content-Length:
- '188'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-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-4o-mini/chat/completions?api-version=2024-08-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":"Honey
never spoils. Archaeologists have found pots of honey in ancient Egyptian
tombs that are over 3,000 years old and still perfectly edible.","refusal":null,"role":"assistant"}}],"created":1764567852,"id":"chatcmpl-ChqzkjWzsgk3Yk7YabNlSOIcjCnVy","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_efad92c60b","usage":{"completion_tokens":32,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":12,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":44}}
'
headers:
Content-Length:
- '1354'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 05:44:12 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-4o-mini
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,66 @@
interactions:
- request:
body: '{"messages": [{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"}], "stream": false}'
headers:
Accept:
- application/json
Content-Length:
- '139'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-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-4o-mini/chat/completions?api-version=2024-08-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":"2
+ 2 equals 4.","refusal":null,"role":"assistant"}}],"created":1764567849,"id":"chatcmpl-ChqzhZ4kPyYsbIzliT8LwPq813yzl","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_efad92c60b","usage":{"completion_tokens":9,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":24,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":33}}
'
headers:
Content-Length:
- '1225'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 05:44:09 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-4o-mini
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,65 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": "Say the word ''test'' once"}],
"stream": false, "temperature": 0.1}'
headers:
Accept:
- application/json
Content-Length:
- '108'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-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-4o-mini/chat/completions?api-version=2024-08-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":"Test.","refusal":null,"role":"assistant"}}],"created":1764567850,"id":"chatcmpl-ChqzirfVOr3nrKLU8GVAevABV5Vz7","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_efad92c60b","usage":{"completion_tokens":3,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens":14,"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0},"total_tokens":17}}
'
headers:
Content-Length:
- '1215'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 05:44:11 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-4o-mini
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,42 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "Say hello"}]}], "inferenceConfig":
{}}'
headers:
Content-Length:
- '91'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- attempt=1
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse
response:
body:
string: '{"metrics":{"latencyMs":776},"output":{"message":{"content":[{"text":"Hello!
How are you today?"}],"role":"assistant"}},"stopReason":"end_turn","usage":{"inputTokens":9,"outputTokens":10,"serverToolUsage":{},"totalTokens":19}}'
headers:
Connection:
- keep-alive
Content-Length:
- '226'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 08:50:59 GMT
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,44 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "My name is Alice."}]},
{"role": "assistant", "content": [{"text": "Hello Alice! Nice to meet you."}]},
{"role": "user", "content": [{"text": "What is my name?"}]}], "inferenceConfig":
{}}'
headers:
Content-Length:
- '240'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- attempt=1
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse
response:
body:
string: '{"metrics":{"latencyMs":622},"output":{"message":{"content":[{"text":"Your
name is Alice."}],"role":"assistant"}},"stopReason":"end_turn","usage":{"cacheReadInputTokenCount":0,"cacheReadInputTokens":0,"cacheWriteInputTokenCount":0,"cacheWriteInputTokens":0,"inputTokens":31,"outputTokens":8,"serverToolUsage":{},"totalTokens":39}}'
headers:
Connection:
- keep-alive
Content-Length:
- '330'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 08:51:04 GMT
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,80 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "What is 1+1?"}]}],
"inferenceConfig": {}}'
headers:
Content-Length:
- '94'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- attempt=1
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse
response:
body:
string: '{"metrics":{"latencyMs":583},"output":{"message":{"content":[{"text":"1+1=2"}],"role":"assistant"}},"stopReason":"end_turn","usage":{"inputTokens":14,"outputTokens":9,"serverToolUsage":{},"totalTokens":23}}'
headers:
Connection:
- keep-alive
Content-Length:
- '206'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 08:51:00 GMT
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 200
message: OK
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "What is 2+2?"}]}],
"inferenceConfig": {}}'
headers:
Content-Length:
- '94'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- attempt=1
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse
response:
body:
string: '{"metrics":{"latencyMs":869},"output":{"message":{"content":[{"text":"2+2=4"}],"role":"assistant"}},"stopReason":"end_turn","usage":{"inputTokens":14,"outputTokens":9,"serverToolUsage":{},"totalTokens":23}}'
headers:
Connection:
- keep-alive
Content-Length:
- '206'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 08:51:01 GMT
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,42 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "Write a very long
story about a dragon."}]}], "inferenceConfig": {"maxTokens": 10}}'
headers:
Content-Length:
- '136'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- attempt=1
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse
response:
body:
string: '{"metrics":{"latencyMs":966},"output":{"message":{"content":[{"text":"Here''s
a long story about a dragon:"}],"role":"assistant"}},"stopReason":"max_tokens","usage":{"inputTokens":16,"outputTokens":10,"serverToolUsage":{},"totalTokens":26}}'
headers:
Connection:
- keep-alive
Content-Length:
- '239'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 08:50:58 GMT
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,43 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "Tell me a short fact"}]}],
"inferenceConfig": {"maxTokens": 100, "temperature": 0.7, "topP": 0.9}}'
headers:
Content-Length:
- '151'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- attempt=1
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse
response:
body:
string: '{"metrics":{"latencyMs":1360},"output":{"message":{"content":[{"text":"Here''s
a short fact: Honeybees can recognize human faces by learning and remembering
facial features, similar to how we do."}],"role":"assistant"}},"stopReason":"end_turn","usage":{"cacheReadInputTokenCount":0,"cacheReadInputTokens":0,"cacheWriteInputTokenCount":0,"cacheWriteInputTokens":0,"inputTokens":12,"outputTokens":31,"serverToolUsage":{},"totalTokens":43}}'
headers:
Connection:
- keep-alive
Content-Length:
- '436'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 08:50:57 GMT
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,42 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "What is 2+2?"}]}],
"inferenceConfig": {}, "system": [{"text": "You are a helpful assistant."}]}'
headers:
Content-Length:
- '148'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- attempt=1
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse
response:
body:
string: '{"metrics":{"latencyMs":677},"output":{"message":{"content":[{"text":"2
+ 2 = 4"}],"role":"assistant"}},"stopReason":"end_turn","usage":{"inputTokens":20,"outputTokens":13,"serverToolUsage":{},"totalTokens":33}}'
headers:
Connection:
- keep-alive
Content-Length:
- '211'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 08:51:03 GMT
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,41 @@
interactions:
- request:
body: '{"messages": [{"role": "user", "content": [{"text": "Say the word ''test''
once"}]}], "inferenceConfig": {"temperature": 0.1}}'
headers:
Content-Length:
- '124'
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
accept-encoding:
- ACCEPT-ENCODING-XXX
amz-sdk-invocation-id:
- AMZ-SDK-INVOCATION-ID-XXX
amz-sdk-request:
- attempt=1
authorization:
- AUTHORIZATION-XXX
x-amz-date:
- X-AMZ-DATE-XXX
method: POST
uri: https://bedrock-runtime.us-east-1.amazonaws.com/model/us.anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse
response:
body:
string: '{"metrics":{"latencyMs":654},"output":{"message":{"content":[{"text":"test"}],"role":"assistant"}},"stopReason":"end_turn","usage":{"inputTokens":15,"outputTokens":4,"serverToolUsage":{},"totalTokens":19}}'
headers:
Connection:
- keep-alive
Content-Length:
- '205'
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 08:51:02 GMT
x-amzn-RequestId:
- X-AMZN-REQUESTID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,55 @@
interactions:
- request:
body: '{"contents": [{"parts": [{"text": "Say hello"}], "role": "user"}], "generationConfig":
{}}'
headers:
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
x-goog-api-client:
- google-genai-sdk/1.52.0 gl-python/3.12.10
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"Hello! How can I help you today?\",\n
\ \"thoughtSignature\": \"EpAGCo0GAXLI2nw2xvVyzr95+urxcoYOhQMTr9wHqICIX6y/0C2VZcW2R+uewNc0N8SSvWRFsEwhjKJ+NUkp37i09ONgypuHQu2gPVIlL1trMAEFbZlaPc0wcwOomXRvo6uOXKfVDSIobfVI+MSkrXQUliBjgJGPvHr0H19udYoMcOrLdRSNGAP+TbkthO4htXJ++cLfgjlzBEHwVC+cKtztTG1nYbNWCyIvo6EG6RIB3+wGm1X1ur8XQT7uPevTL7sAwJE9/3WjM5fLrHMM+lOju5CKdE8PsvXbPcBbILleTHH52PvppeFOLjU7B0f4K2MDx9qcbNCk0xvdEbXCSHuZKKZC+LTvP4d8UJjH/Ri15HFcPNdvkxfauBTJcB6pONfVb0OcK3aBC7TbWGYaIb/fXvOUbGQbsMWz/gLtYXJ04KUPoV4V5h2Iyyu/3UCw6JsZFCvGX7dUojVtEQPEdFC4RgZ4o0EC2tZxj77HiTqgWNO7J5u9CWlCSPsDJ8ASCFpOgRFB0k152CKcdRbVrs/UBbF4Iwy9CDxFERppt+cgKI045tLZKG3btCces0KNKdHqxFM/vOWF34e22V0ilnftafIlWAV9+Ysxwxr2VrSFpeBnFIu+dW4V6WWSOnMvruPGvwP+Prxhyf9dkb/FjEwvg9MImxUk/UC12biBQI8ScDuTE8/lRFV+OG2yPVrBfgEiu+Bkw24yWNSdv/Qecvget85KAtB/YKwEvjmaHsiqBaVBH/QMOZg/H8TaZEf0U2Jz8eBmjXawgkTItJ4R7E70BSkL0RF9Jgic5mD4gcMIScI14Pwa6v/b+cYCmABtE82NhxLQthv5GdvjpbLfRVu59jvtvcPc5wZlSOeha31vGjT61UCv41D2oem2eOqAGplTo5AdpAdYzQLu595g3t62W4wnA5NFG3HQieL2TyaUX7nMmYEdonjrZimLVSQXEbX+rsXdizVU/Lhzw7RGWmT7IeuulECz0y/n8s7kBZs/HBRJB81vci1W6lpusjw4N/ndD1DEMOGsI21JPt1qQDSK7w==\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
3,\n \"candidatesTokenCount\": 9,\n \"totalTokenCount\": 216,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 3\n }\n
\ ],\n \"thoughtsTokenCount\": 204\n },\n \"modelVersion\": \"gemini-3-pro-preview\",\n
\ \"responseId\": \"kTgtafe4Fabn_uMPzdzJkAM\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Date:
- Mon, 01 Dec 2025 06:41:21 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=3689
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,56 @@
interactions:
- request:
body: '{"contents": [{"parts": [{"text": "My name is Alice."}], "role": "user"},
{"parts": [{"text": "Hello Alice! Nice to meet you."}], "role": "model"}, {"parts":
[{"text": "What is my name?"}], "role": "user"}], "generationConfig": {}}'
headers:
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
x-goog-api-client:
- google-genai-sdk/1.52.0 gl-python/3.12.10
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"Your name is Alice.\",\n \"thoughtSignature\":
\"EvQDCvEDAXLI2nz9GP8047tG13f7ZOzI0XMZ3OCm0YSr6D74+bQrUQBrSezrbyjd+tYgOUGPWLtHGI43kn4/PAFjDr32i4r3BXjcw4m5lSGmP/jvtr9a0pI88Nkvh+ZDkhpqjDOAv5phyuDpMGODSnCvMjew45y0zbGF4LREolbFqcm8BSRJ91/lDMBLjO7QlH+q5Afcpgxx3TGMioHXl2A9gC3RP5Q04IE5cSPT9kAe3/w08IB5y1l5yjUZX0mONzcrS3218rXp/vadmXsZrz8RNWsI3369myVPstP/9k4VX0BaXCMDQTtpj4eDPnBO9yxSh7/zaXYn/hrhzpx8H7bfW6nN5Uvt6/95YEzUXo38u+nrD1XWVHAPxJWziA/+7xwkz/b5SweQtMmOJ7R+aesHOMSD1h71awHQNS21rmIEJ5CxERJ0e310mRiu3MVWV5PxGqCXH15pAtRclAmJ6AslX1IzSmWrY+xb650g6YCAVEntULL78LR05A6MNJa7zBQ5Jc/BvRnqIKpF/AQwTaJTELGolL5HLp0lmvK4fwLHCYHyjUeFMfPFfmkqbMhVlTCPIsWF/UasgTUJe4hyRkA3M5Ri2ddmgrkpIi8HmdpaLjDB3Z2anTbiwrXSBVLQxrEmq/VipqCrD0TTGJBbs11YLcBBMDw=\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
21,\n \"candidatesTokenCount\": 5,\n \"totalTokenCount\": 140,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 21\n
\ }\n ],\n \"thoughtsTokenCount\": 114\n },\n \"modelVersion\":
\"gemini-3-pro-preview\",\n \"responseId\": \"jTgtac76H9Th_uMP6MTF-QY\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Date:
- Mon, 01 Dec 2025 06:41:17 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=10711
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,108 @@
interactions:
- request:
body: '{"contents": [{"parts": [{"text": "What is 1+1?"}], "role": "user"}], "generationConfig":
{}}'
headers:
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
x-goog-api-client:
- google-genai-sdk/1.52.0 gl-python/3.12.10
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"1 + 1 = **2**\",\n \"thoughtSignature\":
\"EoYFCoMFAXLI2nwVxrNDd3DRwzAjd01XsZh5B+Z3MCDHsmcZfdRbTPXQn6bXtY3CHVVFqZFTtcLGOV51/1PXoemWzgTZ/Ct9dHeznjy25gmMk8A9Mj8cBFafKX9FoJqIsGxHrojFz7ciT4YkmSsb9HMGKLqpRXKjS/daSsOFxkwTtn7jfY0xse/40+pfZ49K9FURkwwXPDiR+5jvktDxXV4oIs7db4HokZsLKBAhycq2nE9kEcsh8Frb56Jb8SF43JXVyp3pHm0LuwSJ01/NDgGiU5ouAfY9M5P5dBaI2u4tXedvnVPrJ6UQEhzHy84M1xt9EBxZciPPQM1auBIWBAyLdQ7h7s5XYMUVqNgmKoSvBisUdTLFSN8mgrxJauRDA+InCNQnaHCWRxpNa7bhX4W1yHRbwn1Rt6XPN1RhkC/Srp2TNDbsIc0SIPwwR8jPKHLVN1gvV+axeaKjPwaSzj4yRDMAFXnvAWssnNvoYrwrznZAcW9uBsqYQbzaWgc0NOL0FJZ6eM6W/ejAp+sBKHMRgAb8rn3cloORiZ2RHB6+8n4ZyxvnGFgZrQBVJ4oitgL3w07fmob/3moVAzxvA290cJ1HVPsKsBFPD2ljPDu1b9kvUESlAe+iKQ9v9/pAaIieER7/ehd8cJUTRrVvx2zCVn71Op4cXxbJp0K6R2sTjy//oHEbiHdjoZFbhJh1YXfMDzJldh9TnlMN1wAQ2c13UHAIPj1yj1Wooq57W/jGrPIwacKsoHTTNjxKr6hPCrdvOEz+fd8ikrCqrFr7pHHI2Ca+PsWMKmsphRNzpY8FZs83PDRfuAgnB/Zzdv3d6/D7Qf3otaXBPL6DruaIcdfQfwrPD3GqAQ==\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
8,\n \"candidatesTokenCount\": 8,\n \"totalTokenCount\": 191,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 8\n }\n
\ ],\n \"thoughtsTokenCount\": 175\n },\n \"modelVersion\": \"gemini-3-pro-preview\",\n
\ \"responseId\": \"mTgtaZOwMLri_uMPnobOkQQ\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Date:
- Mon, 01 Dec 2025 06:41:29 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=5483
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": "What is 2+2?"}], "role": "user"}], "generationConfig":
{}}'
headers:
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
x-goog-api-client:
- google-genai-sdk/1.52.0 gl-python/3.12.10
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"2 + 2 = 4\",\n \"thoughtSignature\":
\"ErkCCrYCAXLI2nxSSxutVTQ2B2ibaJOBO+cZwS6qr5Y3p++to48i3SXfXLHOH0CjME5g6mzPPblyU0W1u3ZmQ9MU75Zcr0XXhqG0d3vQpzjSbZz00b9PuAClqvjnLNW75Lle8FiyX+oVChVMdVzSGCM+qOHdSPD0JMS54MYwiki5WyRKrRiBqsA1LPazBAUX2SK/4VazJABhbFL5lazUdVAgPGQtuwWCQjoFniMZ3EDXSrDoVrlrwTyYHtbqTy0pnseR+8LwyCJBJ9cdBoPNa1ZN6g/IvceX4TFmjgM7f9n/ef9LUnkdui2XcTdtHeGQZRJV2HLS2wHHqKZqBkqvIR8qNz5lnNcSP47+Jw13amrC7k/aDRmxvsZ0lOzgxCUK/K2WUdjaP8f6az1Th6J0LXaOA6D61o9d84qgfA==\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
8,\n \"candidatesTokenCount\": 7,\n \"totalTokenCount\": 96,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 8\n }\n
\ ],\n \"thoughtsTokenCount\": 81\n },\n \"modelVersion\": \"gemini-3-pro-preview\",\n
\ \"responseId\": \"mzgtadDoPNq7jrEPsYmsiQ0\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Date:
- Mon, 01 Dec 2025 06:41:32 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=2112
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,61 @@
interactions:
- request:
body: '{"contents": [{"parts": [{"text": "Write a very short story about a dragon."}],
"role": "user"}], "generationConfig": {"maxOutputTokens": 1000}}'
headers:
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
x-goog-api-client:
- google-genai-sdk/1.52.0 gl-python/3.12.10
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"Cinder was the size of a cathedral,
with scales like obsidian and breath that could melt iron. The villagers below
feared his roar, but they misunderstood his groan of concentration.\\n\\nHigh
in his mountain keep, Cinder squinted, holding a single marshmallow on a twig
between two razor-sharp talons. He exhaled\u2014not a torrent of flame, but
a tiny, controlled hiccup of heat.\\n\\nThe marshmallow turned a perfect golden
brown. Cinder smiled. Being a monster was easy; getting the s'mores right
took finesse.\",\n \"thoughtSignature\": \"EsQYCsEYAXLI2ny2hAZSa4V7zmiNbExCfxgcWPZgFQWizigjz2y7NDn1K4cGwH+UPYBISvR8B+GShFLHM7SKTFYZGRdRoiQHcYcpFzPdCaC3C5cydk7fHB/kWp3pRb8HSpPI3YAM7/kglg7mvRqjHgctOwJvAIaEBJYCGxhb0ZM25aB4GqNNqk7gt3btC9lMvpuX4fYQXqhAF720uO8Ui338CnnvHresWHS09JNfY5/0hic0fVrL48kKujsud2pTs7aa5uLrCW/5DHHqsnBg2qgCSilXuhscWvm11niXTssfVYnkJZWxb0tbZIXBVbTr/UZNZQBJIhdWdGu5SU1GiKMlRYIQ0Xs9VrsqdG9q8uU3VaajsUxmVxO7cXU9OLjfXDojk89KUthWEB1YEkJPsCa81i+pTrCyvxFmrxo2TSgf9cOC9kjjMo5ScpTivunZ7cSDpchVkhsyE/uZCiz6USCWojN/MYLWOJo+4oj6FWpUZ4U2/++38Jj7eyXjp9GCIi7pHEvQ7c6wO2Onpe4hM0DQk0/KU3pWFaY89WvgWpzSX3eaPU1ji1Sj3GTnrtp0pj5a9ibmXFJXQ8AjWxAulIyVEeCqHUsVAMpZ56PwLL2Wptlsoz8LmD9Od7j8mM9M1IT4Po6pFrywTT8XqYMljrPiQsKdYPpQAclqMSlkGXHj8Q90/fgwAbjA68ccuXQeIqEvX2Iv45ObFEeZLnFChDnQtutP5BKM2Iqbix6zoLisKS5a4KPprtk6gECgtc3I64d8/0aTAJb7o/Mt4QTDp3drETXZu0/x9hLUvS/YKIiuLzo75pOaTK2ZilZo6zfuUlpwD1bURSa/3glpGnkkFJbrrYLREgXDUYPZhc77IuOccxjkSv203fIGLxPdml0d+kSRpJmkBricnn5Wx8cBZA8O2QPoJbGqXvgFx5fbgBILCCL5Unwj5UXZfCKiF2zMpQm/qmShtrzn+rhSFvBAN6izD1YDTrNZB4c7Sws03X1vbcR/VGrzHPcHb08LK9dEpjZEzpV1GN17W4lPLV7dHfSz58xze6chbjariuh4VkKNx/9QpWjBek3S3ySPz6+ptBF7uAyzdnuSDkrDAal2zhvl6OgwXf9uv7ko3f6RzvL3bMLuWTWcSgOb73B+rWl6wQeAKxHYoJqE3uXyND3h1GDo0jp/g+rLAwV56FVV8U50cRbB/Of2M0WU5970ACh5NTlHGD9/z/dKl8dXKW1ExuCN2hIns62Vmln9It7rXFTvRYd5T0HPZyWaenG4E3X0yvTkJL5Lrg4aGVOepvB2WbmRQUT0dzK1mc0V1sLt2fYVZvQ8m8Cae+Ra9GayPPVF8b7HUC+vtYHSDsJvT9kedgJeqjeQWeKoza1wgTQBvogq62IEygQIMfZI9Gr/GUqU6GvqTFAEzaNdqEM55bIeU9iUefChKK6I8JYeAxK8CLMFRHNg6FFBv4WA1bDxq29gwlqt9bHbQokDjDRNOK5ctYIiPsGrImD/wFQtlZBMVHyruX/ZImEg1iIE0BmDod4TvjSqqTDYPMmtDDfmrBgz6L53LIs3+XZOnvYA5SFmz8FQhK5qRPDjpU4LTnN2tiyrMNg9wEG1a24wykhhJPVY1g9c6Wnegyh6gOfEcoAndtXbZH7NGuJVQX+hcfENA52pMZA1i4nqzT8tQy9i15A6w8ousfb21vpOFswbK+n0ut2/r0fAsFDCXeR1VsAekdsjwFUQC6rjU1AeZpn/gLNa1lVv76Dl1VAnSoNOHKBI4nnmBiESwQ2OXT+ksFFKLYzwfeBXwFmrIaCQtp05IkOots89PDsCm1TPKYryiW49QYyYi/ICT4PBtYScLmV/2vZtFJiQqkJgMZ7olZ8spfdsx633OkHyehqdAeZVtddW6JLzcptDTMjYX0pouxjDgaskVgn1n5z55dzfbWU9wvTITH+2HKrMAJfUAMF9q2j55WhYFY/nZ8yiKdsn+hMpFm+oHyM+pyDIaDpHb5qbahG+oFlCDdryRyS0KXe2YgE+fwUzqsrrUoEKWCkkQEObnMNgYVox5x5KEOpMV6hD5QCpIlEdPFl9bZbJxqGEX+yihnhurO713cFZCv/0eEKTVW/0NqoLboQGNPtUY41i6t4CqWwGlm0URD4fWI8CSMgDBfb7EdcjgdSG7nRJfC6L4vkwWRxKZwPPlpwtR+HRUtDqiV6jYo6CQTmNuNGUItN49RjpPmObS0Z51840j112spzgkX8hWoqm817yRQa+TzcJQfG+SkapGOyhoZHNjLjGCQtDzR66kzjfxa7R50k0CMwRbfhPHAmqo8o/jWai8M/u8P1YMV9nJEBkRLIUS7PDL6c1w8UHLdThxrSF2AGK7ifVVYl4IwW/9gcZf0XCl7K9UcGoT6tCctRkic6VIu+Np+0AosonGySbf1xqfiYPa76gWk/dvMzPqLp4lPHwfNcu43+fAXqZ8owl5UE++5DiDcJIP8/X9/e26tGJt93gd6lLdbvKJko6Dir9YzHhOKeu+28yEosp9ZnePXDV9vOxsh2NBrB6dbgZcN6a488FssLLHHJzqr2negXugLhhIP2KA4VVdIom1O6uAXuuqGUJRhJtfIzxbdhBhd3AuEPC1qc9qQLuHArcgzN2myc7q1oYv+ajcjc6l40qeRxWbJYTWcVc99laXjG4ajbMwe+HpfZHtuE3ryVY13MaBvpKxPg935TwG8xCARFiudNS64qb/P9XA/SuTHSyijDG0+9Xk+f3S8A0fORuFFdiMxqaxRPN03LjqnHr/OCElpGGgiBKSBTi8/Xnw8sH72nU0q0hnLfF5WMKVPIT0bJUGLSXgjPcSu+DXPiv2vk6FX5it0jihNE6mJyNKVYig/C84qF9IaH8IjDXsV6jsS4JuPkgAo8lTDS9Gix8yJXbbKiIjMklwKmqp+3PS1euZlV6/Y0fg+WGBuN7SkylaCH4dP743xiitPLKX0wQVHpMpCSEWfQSYsTz3xcLeIzjIzUA4WWrwxXj1YRtqU72EpQ2Hol8EIixfM7Btc+D3i8kXc6d8DgJYxZ4aemuGnZYhEhF3RkDaxW3CCZwwuhP2rLOeKnmJUxtTuAh0CI19UmdRRcZYOmwcp2OCD75Xby+2SK9P19jCYLY+P3srm56IPvJ4Yk1EJmdRBMHAQuUZtLiRmIi1iQvmNwoLiws3QBZV8P/OvgvT4NJahWjOZvbQaoiWtj4j12Wu3jmZtybxJQUH6jHpn9xW9lvS2fsckiBHavHh9/+UhGlLH4WvlBX2Vn93/MiCWLO90Tsj1bYjRM3N3+3ZRGTvGHWdPnSDxmJ/LBnDV5aq+x/OEL+1+Cjx5g87Q4QcekCTLYYITCKAmZ2660YU8cP84Ci14DtpZXypB2kHbaQH/s4PGr9p0lQk+Dy+bl2maba5E+Konz8UQIw3GElXdbCT4I8DRvKpfO0W40GtX4AZ7uBArpGogaqiof3CRU5t34V415nC1XWWZ6CizzvtrAMzam4OaX8QHqRilxqFTlCTQuoKYclikQtxHUAz/F8zC7MRUYandUVnPzrp7A8qFxIR0S8Omh35q9x2ZYaTjqRWNxVnEZkKIZsO9OTdO4TVQ2LR+kvkiL7pvoIWkd39zLmfKNODDry1pJaikIUGiw/WN3mPZf1g8927xRzcSs+11ARGG8v+nVppH0L+SyJ6PZM+3SchNBs+rQeE27Z+NJw/xlW1Ezuveay6DJMpGve/vQZbomg0Q+izjCmqrUiIzEJp3gZWHmRXSN/L12wjHmESahkx2FNvqD8O03rpGmvNiBC4hE/Xf3RDGqV0VwSN0mmJPvM/P28+XDwo58TrPfV8Q/WAgfWmq9iW9l5qF+2ggOB6zt6S3wGw5MH/f9kd28/KvIX2eu6ExIGWsm4JzCVUNTx49st6of8Yjz10t2pDUQ72x+dVb18f3EoGsLrGVaDqPDBDDm+d0mRdHNjG37uxvotfIjXv/3UQgVce+ouJZN807uKutyRD6tObkdz3Wc22tcLX7BVgBV07AAUcvEYrmmW92sBqttiLNSLtPMyikb448kyz+Wkx2/jFbSTkfKphJfkoKcOjsqbqQk60Cr6I8O5+1k4w7TVSJOgfUtDuB0IQ1sYYcPlJgbn5DI880dzO5k6QQ9Oe2wprDumThB3t0+ocSSmO+X0xeZTUQeUUp6u28ZRMJGzrUo=\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
10,\n \"candidatesTokenCount\": 110,\n \"totalTokenCount\": 940,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 10\n
\ }\n ],\n \"thoughtsTokenCount\": 820\n },\n \"modelVersion\":
\"gemini-3-pro-preview\",\n \"responseId\": \"0kEtabSvAZzg_uMPjb7OwAs\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Date:
- Mon, 01 Dec 2025 07:20:50 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=30099
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,56 @@
interactions:
- request:
body: '{"contents": [{"parts": [{"text": "Tell me a short fact"}], "role": "user"}],
"generationConfig": {"temperature": 0.7, "topP": 0.9, "maxOutputTokens": 1000}}'
headers:
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
x-goog-api-client:
- google-genai-sdk/1.52.0 gl-python/3.12.10
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"Botanically speaking, **bananas are
berries**, but strawberries are not.\",\n \"thoughtSignature\":
\"Er0VCroVAXLI2nxQTzMflG9Mo/d+oJQwHRElsQ4D5yXMb70r7s4VJDOf72zdb41Q+FiEfihwsTO+VVfasC1NDDeegXfQxrAN+/EsR54ZxtKHeDNsncLSL3aZC1jQQre6GD405NEASWEhpG6wLE6b6naOSqZHv3EDFk2DkDrrU/GX2MkCGChteqCxhVPdp8a+Tg8DZiH3ixJaG9y1/Yl6ew403PksUeukTcCXqM64/kwZxhgXbsw43CqIY9t3oXAq7a8cJ/0IMa4o5dBAN/FjfYUwYeAlOB4HeLv4+WdS3kHDsQQBNSYiqUqMaOGl3BFEeX+zEenlLjrGjZcxjpPWF+DIFteq28zHymY6gb+EAPP4ZjWnwkswzkvx3uG7n4DSK+29cmn6kBsOXvmuVZDd17EB552dV5bFhe5jqEmQsHgEVVYfmMRcweLihkdmOFw2t/88O7kH0GQVlO/tfsYNupgALtEcy20aF5efb4j/NAguNfM9LHtvhEfRCWIc5OmpobNeuI05EmdBBITfR0dLCzF1pP60m6ViI2AVaSma5gR2stlqG2rXO10NMBWD9XBQXSM9pSS8QdutwQPjxPn/TNH802WgxAegP+OiB9yhBrtsmz8+m3FnNYQ7C8+dIXfUQV5aL4L1dCkckv5YsJ/pKo8VNODAosC2NuasPSuI6IkXdMcDLiZ9kGq4Yv+udCImVKeehvSH+96PoBPDsoqwik2akUky5FGVKEhqrOJ79cZxUqdy/RwKVfkR+0dUH63n9T9mgp9ncNVR+XMbmeTAHA1VHSxkDz06ize6WCtlaQQ7+6VF3H2PU+X8m69y87CuInhKkdqANrkCs2z/GrCO7tEyMw2xfRmZkZVTCXG2p5CyXiAfy5Vfm8VHn6mWG1bFYSkh4BipjB3HvHwBGBThLGDbscJUszbrFpJ3dm4QIKpfCJk2NIgro/mVpMYloGVzvpMhNDQeMZK/mDOSf8pmAGTNj7Aqs6d/YSspFH5V3Zt5a5ahiaWvqQyeE5Rgs0HUrWxjBSBBVg4q1otgwhHklqbUps3P97I07FtBTbA8BzM5cgeJDyVhUa58e03fHvaM9txBbC4c/w+KYJ2E+YymxQSFW+W8TSamTWm/t7PkvcDQ5Z0eIYspS+3gyOxrC8urIK4k1IdDw1G8i+ebdu7UX/VW0tHpsrLXQZLyW8TmuEBS7NBHB+0GwZ/MSjFjSNi5tYS78hJzThR77VZzKxTTZDrzlDIwK0WSx5sPuOqa384gz+Jb5uogUYX8OhvgvBOkAggLe8vDelDrKR7CW8B3qwgYpWj2UwzMCaKk6Irr36TPh9f6po8uQuJ2rFsq7qzSCMy765MglDzA2SeBwSGDFr8II9NcmixsLmyRlLjBDI/qu9JCWkwZ/MH2wfHIxZp04wp9P4DzqgC4Kcy49S1r23Olq2Ji4uQ595P5Xwv/Oh5oD//8sdVlanywjFhuqet4dgZ+mkVRM64q6ERQyBbMLYsm9qKuL31nmTH8v65sQ+HBQExdSkVjp4TKK3IYpRDl1wE6i0BmLEhvGB/KYpYIhn6PUjWRB2gTf3I7E0r50CWq/PisfmtroRtaoeuDTZ6x4BcxR0k0eCwjJT5wxNqpazqfkzhSSFkn/XA4TatFtpASDDOhHyqI1YMpYPCzv96aCPK1NPYIORj2qwkCcPTP6oMvA8KHwuna8Mfy7HhDLSZOXH07wJo5khk0LJ53rVbhM6GhfUrDylP13zgYY0YYMjeA0kkHPknzh2N9OfPTKacI4Cu0VaXtZJDE8Z38+azNLBi1ww/JH80lKqoVJgUU69W34opmFR/E6Ub6GRI8CmttnbGlv1LAEBd0u8BOqrbJ0FZIcSDvJClJcDZtWryKoLckgkrZxGqmXAISNOGwh57lIbMxDvxOERXlKxRsOp8hfG+HcaifuGwAxMeqB3bUg3DRph0UCfPKfK55HGPkMRZvrARbzj3Ire6k1Fol3i0pL+/HTziy1zh7Bb6l3a7Xyzt+dLNd+GZFoHquV2jLc0AKxDUdr3jVkACi6WEsnFw+TucOiHQfxetFkl+mUtXfHNNAIr1NpmZtJ1zNs3HNBkjhodgHGHDBKpJ8o7yademxtqN/3PuWeRRDrQ9+EXovfW6FTe1Ubp1pp1vo+KOOVtnDW8ygE/+ts6twOomNn9snBBaQ+KD8NLoCVWcv2g3u5HdtabB4J+mZYpbGw/WDPZLxqxNDNEyFwhOZCrTF6IPNYpz5MXphYNeqpjmuF3ywDI/vUcy/D+njjx1l/UfrWGGYlHDxUly0W2418plH7DL+Enq/hEbzlHqPvz7TztBovUQ1NIHo7hMoVbq+/hBJlXppnKL9yXFLM5KK5siOh7818Ll2328CpjIXbxXWG+IXrUQbxbRgVz2Z0jP+LbFBNQGl59MLJUUUjZTPWb/qYhafQ9YD9Z/M31DW1JuCyB0ROt5IH2gG7I/MFHyIRESbzjwnsEPAEg6m1XU6Dn1EiGVQ9yslEb/uw40TxTMHrnwtTxdUAZXAxdJWWB6e3x77spExSA80dHe4Y3vcYKQiijS0aSH6LdCT5RgUBAllMuwmEm126yTEvPYjo9vfkxuywRerdDirjA2P1QrbKdAQAplJexyU2WgIoSdBfhYGmBe5RdiZjbjFIvKEHDUkQxEsgzZkB1AiN3YcALtNlQI9M1wxyBx90lPUqQyFY0I2GMBCWhn3k9mRYIwpt2BNoKZSLaz525BOlT3pZelVz0N3O0JGU29zWmJ+O6t8GtXX1Z6xsnryXs/tnxTz9BGSW0thedicmtuRgavVH/gICRhGMY1+11htdD7WiY+PWdgtQLJZArod4JoVmtsucbNRslikKR2whpvK4vaqK6gIZL7cKA2UH3p8CXYPcjDjm0a310lfMLKVtpwMWg69SExkOryEdo/673oS4cOGqq7TidHdRqrwaRwGRQCvAGJkCPdCryqPHzaIx26SLxk3MqfrzAVqh+UzM2/7DRB2r8UT1hnnY4A8T1Exv1LOgjw8Arj3i9GoOCamVmPRAPcYjsP2BmITwP2mXUaIng8rrMJcBZmbYhJGfpFPXhXckosw9KGu4Ip4+y72bJgxhVFvenUdgkxuSiOcuciGHDD3iqd/CsiOsaaEqNmhVNuj/iRPgdwWVIoVrs33iWEZCgzyR1xgYZkUbHd21TbjSlXSfbZcnAkmK1HKj7vpLmR03zgEcohurqXTowk5xpj/PBvHwVksM3gsnVxN/bO4h8rTk7g/pdF5Rf/Fb1nDnKjX/i8z4t1LiE6RohlydHVNBd6XCNyVB1+YBX1PQUIxcOzOeXl2bKKryD2sgHrFHNYe9kSoxGyPZ8/+xymhXZGXHdEStEcXC7bEmN+n4BbLPCt7/6poVcq4wZknOqy+78wCLVLDsPLGUGWAMpDl3pM9ad/gfI99blVxtPFOsp6ladGpVEJM+UzKkhCaeKyHAe3Q3eSeUgIR6ijB+hAhuskqklEDrIaxk7S/rjk/+5O+beSZaNfKrnHTE1Ee7nX6eP0XOKKsGzwgoxdgeDuybFl6GT0BlRIYFVDuomjD76Ykoeyt5lodcPS53mkqCbWVFJPpxjbGMDGG8FnmfYdyO6xxpD4lnSEAXVieWOmNOTJtJ7fwp1zXaF+XPEk46EusTElcvpQcMbeAAewj8w==\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
6,\n \"candidatesTokenCount\": 15,\n \"totalTokenCount\": 750,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 6\n }\n
\ ],\n \"thoughtsTokenCount\": 729\n },\n \"modelVersion\": \"gemini-3-pro-preview\",\n
\ \"responseId\": \"O0ItacH2H4Xa_uMP1LLs8Qg\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Date:
- Mon, 01 Dec 2025 07:22:35 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=10635
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,56 @@
interactions:
- request:
body: '{"contents": [{"parts": [{"text": "What is 2+2?"}], "role": "user"}], "systemInstruction":
{"parts": [{"text": "You are a helpful assistant."}], "role": "user"}, "generationConfig":
{}}'
headers:
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
x-goog-api-client:
- google-genai-sdk/1.52.0 gl-python/3.12.10
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"2 + 2 is 4.\",\n \"thoughtSignature\":
\"ErUDCrIDAXLI2nyBnHKB7Zg0BoHU3HOlqCL8LaZOucy0BoGvQi5n7cYc88DBaiFNRDt/Oqn+vzs+S8CHTbkn0MoeJ056rT9AAsZlPIhhHdpgyjpq7YUYzl0o5/QienwcVSA2scWPUDc12KJdk2u6KGm1Te/8aOSRfohS+i8bQEY9FVe3uobWRQDO9cf58RFzQoRYcC8kLsAh1sxGKt64mSQYJuSZdSGlha1fFhWWMBYd84a1ajgW6JRA9qMmiZ6JHJE3ACtIf1b5MPXHQABXQZWv0SckI11H626F7yaLZHPSOQF0xMkwMex6ccDlHgaWqVLqEGu2Pdaln3GgCTB6OygIlOwUQNaLQzHz4vUc0/QJ7G8rEGx5Zqz0StcgfZ9y2uHKGXmiI+X0LeDNJUZ5iwQ+7GmkiCwaiIYjpozveNLyYdoLP4SBcTosAqDObPMAecmK/N8bysDeVEr267NV+323akyOrlkRpkqEzKMiLac1i/tkD+yGfrqfv3ug/JobvOyWoUNDMWajwRY2uqydGmym47k0A0Dsbe2qEjsF6L/DfvZWgvzvq5OLYlIRvqQy6arKr+IbyBw=\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
15,\n \"candidatesTokenCount\": 8,\n \"totalTokenCount\": 129,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 15\n
\ }\n ],\n \"thoughtsTokenCount\": 106\n },\n \"modelVersion\":
\"gemini-3-pro-preview\",\n \"responseId\": \"fDgtaaDNHvze_uMP_svB8QM\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Date:
- Mon, 01 Dec 2025 06:41:00 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=4014
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,55 @@
interactions:
- request:
body: '{"contents": [{"parts": [{"text": "Say the word ''test'' once"}], "role":
"user"}], "generationConfig": {"temperature": 0.1}}'
headers:
Content-Type:
- application/json
User-Agent:
- X-USER-AGENT-XXX
x-goog-api-client:
- google-genai-sdk/1.52.0 gl-python/3.12.10
x-goog-api-key:
- X-GOOG-API-KEY-XXX
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
response:
body:
string: "{\n \"candidates\": [\n {\n \"content\": {\n \"parts\":
[\n {\n \"text\": \"Test\",\n \"thoughtSignature\":
\"EswDCskDAXLI2nwfgOUguqJVjh+Kph8BTi55recWVrGhP1HtU3yZPiUY+Hkduy95XluHk7iuvRMYx8ghtnNreGkDs85mjUnxZ+BGR78BAevHszR/9wARWYT2jf2RMAenQw46R1TXuQfaRW+h7BYAbEI76VcxI0fJt13zz5b9UPj6ciM4es2hKxHGMGst/BuAD6XR0JqQ5bw5izPwnD2i+xQ64DQKt+tXnVkpJYmyYnNP68Nf/mZYFprbJYrsbhBLsxHgnUEGD/qmVJSz2zCAIUN+8lZ3xzPX3/Dp4Rau8LBj0kCDTvmk133OTeWQGs11rT3DOxpy/PmbUZ5+LFMe3t9Pf45Dx9WvHndcd8YZ8xFXGICVi45RzOc1z+j4XYG84SXU3fJoG30W4OLA239Y3oqjjXCRIUJWScIe2mBe8dK0qnnDFIyHUzZkT44woGB9O5LCeVC8JVnUrs+zEU4xqIpDG1m+wFe/flpMLQ5OX7wIJ/4qxWLDLslu/VL+Uf31Dx09tmPdR92gPfaMWU3YSk9LRlTMoPMrRzQBG8wnq5lxVHcNbblYSSR+VE/vR74dzOHHlYMBRp8eTZGTlZiP8zhUUq6TgyKoO608obBFMQ==\"\n
\ }\n ],\n \"role\": \"model\"\n },\n \"finishReason\":
\"STOP\",\n \"index\": 0\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\":
8,\n \"candidatesTokenCount\": 1,\n \"totalTokenCount\": 113,\n \"promptTokensDetails\":
[\n {\n \"modality\": \"TEXT\",\n \"tokenCount\": 8\n }\n
\ ],\n \"thoughtsTokenCount\": 104\n },\n \"modelVersion\": \"gemini-3-pro-preview\",\n
\ \"responseId\": \"kzgtacSlO_fc_uMPp-69kQM\"\n}\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Content-Encoding:
- gzip
Content-Type:
- application/json; charset=UTF-8
Date:
- Mon, 01 Dec 2025 06:41:23 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=2450
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,112 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Say hello"}],"model":"gpt-4o-mini","stop":[]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '84'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-raw-response:
- 'true'
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-Chun7BIjxigZRHcVrQXrQrMyfPKhC\",\n \"object\":
\"chat.completion\",\n \"created\": 1764582445,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"Hello! How can I assist you today?\",\n
\ \"refusal\": null,\n \"annotations\": []\n },\n \"logprobs\":
null,\n \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
9,\n \"completion_tokens\": 9,\n \"total_tokens\": 18,\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_b547601dbd\"\n}\n"
headers:
Access-Control-Expose-Headers:
- ACCESS-CONTROL-XXX
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 09:47:25 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
content-length:
- '839'
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '303'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '318'
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,113 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"My name is Alice."},{"role":"assistant","content":"Hello
Alice! Nice to meet you."},{"role":"user","content":"What is my name?"}],"model":"gpt-4o-mini","stop":[]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '201'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-raw-response:
- 'true'
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-Chun4rXh76uIHJSZaRLBRTzAecN8R\",\n \"object\":
\"chat.completion\",\n \"created\": 1764582442,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"Your name is Alice.\",\n \"refusal\":
null,\n \"annotations\": []\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
33,\n \"completion_tokens\": 5,\n \"total_tokens\": 38,\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_b547601dbd\"\n}\n"
headers:
Access-Control-Expose-Headers:
- ACCESS-CONTROL-XXX
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 09:47:22 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
content-length:
- '825'
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '351'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '364'
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,112 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"What is 1+1?"}],"model":"gpt-4o-mini","stop":[]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '87'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-raw-response:
- 'true'
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-Chun4Qx1OMzZZqkzYDS55ExxexGkB\",\n \"object\":
\"chat.completion\",\n \"created\": 1764582442,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"1 + 1 equals 2.\",\n \"refusal\":
null,\n \"annotations\": []\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
14,\n \"completion_tokens\": 8,\n \"total_tokens\": 22,\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_b547601dbd\"\n}\n"
headers:
Access-Control-Expose-Headers:
- ACCESS-CONTROL-XXX
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 09:47:23 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
content-length:
- '821'
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '295'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '321'
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,125 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Say hello world"}],"model":"gpt-4o-mini","stop":[],"stream":true,"stream_options":{"include_usage":true}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '144'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-raw-response:
- 'true'
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: 'data: {"id":"chatcmpl-Chun1541wO9KsnA1AzuzKcefqabeE","object":"chat.completion.chunk","created":1764582439,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Uz2DY2OFR"}
data: {"id":"chatcmpl-Chun1541wO9KsnA1AzuzKcefqabeE","object":"chat.completion.chunk","created":1764582439,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"Hello"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"pmqxUY"}
data: {"id":"chatcmpl-Chun1541wO9KsnA1AzuzKcefqabeE","object":"chat.completion.chunk","created":1764582439,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"58oyjxCxJ2"}
data: {"id":"chatcmpl-Chun1541wO9KsnA1AzuzKcefqabeE","object":"chat.completion.chunk","created":1764582439,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"
world"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MC1si"}
data: {"id":"chatcmpl-Chun1541wO9KsnA1AzuzKcefqabeE","object":"chat.completion.chunk","created":1764582439,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"8HDdp9DvCl"}
data: {"id":"chatcmpl-Chun1541wO9KsnA1AzuzKcefqabeE","object":"chat.completion.chunk","created":1764582439,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"X52pC"}
data: {"id":"chatcmpl-Chun1541wO9KsnA1AzuzKcefqabeE","object":"chat.completion.chunk","created":1764582439,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[],"usage":{"prompt_tokens":10,"completion_tokens":4,"total_tokens":14,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"3v1FDDYoIkY"}
data: [DONE]
'
headers:
Access-Control-Expose-Headers:
- ACCESS-CONTROL-XXX
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- text/event-stream; charset=utf-8
Date:
- Mon, 01 Dec 2025 09:47:19 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '249'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '406'
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,158 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Count from 1 to 5"}],"model":"gpt-4o-mini","max_tokens":50,"stop":[],"stream":true,"stream_options":{"include_usage":true},"temperature":0.5}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '180'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-raw-response:
- 'true'
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: 'data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"mGTNZ0zsF"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"8dqmaEzjQn"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"tecyX1f5Vi"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"
"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GzCKEJ807W"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"2"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"qUBVkHkap9"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZpWDm7Y9aH"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"
"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"cx4Revcc26"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"3"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"BIlsyg14TN"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZItBbf19Mp"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"
"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"e6X5CCcnOr"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"4"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"z2eemwmsTb"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GmVBGeFnA7"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"
"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"zFcUhBcDAo"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"5"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"G9hJLBqJmy"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"qO39pCnctF"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"nHvY5"}
data: {"id":"chatcmpl-Chun6sX8dB2bz1tacUmNcYtbKlHt2","object":"chat.completion.chunk","created":1764582444,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_b547601dbd","choices":[],"usage":{"prompt_tokens":14,"completion_tokens":14,"total_tokens":28,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"aPpeboMxC1"}
data: [DONE]
'
headers:
Access-Control-Expose-Headers:
- ACCESS-CONTROL-XXX
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- text/event-stream; charset=utf-8
Date:
- Mon, 01 Dec 2025 09:47:24 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '153'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '169'
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,114 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Write a very long story about a
dragon."}],"model":"gpt-4o-mini","max_tokens":10,"stop":[]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '130'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-raw-response:
- 'true'
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-Chun6OMSoP0Ykq3p5gBfxoHsWR5Kb\",\n \"object\":
\"chat.completion\",\n \"created\": 1764582444,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"### The Tale of Elowen, the Emerald\",\n
\ \"refusal\": null,\n \"annotations\": []\n },\n \"logprobs\":
null,\n \"finish_reason\": \"length\"\n }\n ],\n \"usage\": {\n
\ \"prompt_tokens\": 16,\n \"completion_tokens\": 10,\n \"total_tokens\":
26,\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_51db84afab\"\n}\n"
headers:
Access-Control-Expose-Headers:
- ACCESS-CONTROL-XXX
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 09:47:25 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
content-length:
- '844'
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '517'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '563'
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,114 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Tell me a short fact"}],"model":"gpt-4o-mini","frequency_penalty":0.5,"max_tokens":100,"presence_penalty":0.3,"stop":[],"temperature":0.7,"top_p":0.9}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '189'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-raw-response:
- 'true'
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-Chun1iUVcMDGX4PUn6i55iuj2M9hG\",\n \"object\":
\"chat.completion\",\n \"created\": 1764582439,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"Honey never spoils. Archaeologists
have found pots of honey in ancient Egyptian tombs that are over 3,000 years
old and still perfectly edible!\",\n \"refusal\": null,\n \"annotations\":
[]\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n
\ }\n ],\n \"usage\": {\n \"prompt_tokens\": 12,\n \"completion_tokens\":
31,\n \"total_tokens\": 43,\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_b547601dbd\"\n}\n"
headers:
Access-Control-Expose-Headers:
- ACCESS-CONTROL-XXX
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 09:47:20 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
content-length:
- '950'
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '817'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '855'
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,113 @@
interactions:
- request:
body: '{"messages":[{"role":"system","content":"You are a helpful assistant."},{"role":"user","content":"What
is 2+2?"}],"model":"gpt-4o-mini","stop":[]}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '146'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-raw-response:
- 'true'
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-Chun3rNZ2eWzO9CwVqm5yiUosVIUG\",\n \"object\":
\"chat.completion\",\n \"created\": 1764582441,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"2 + 2 equals 4.\",\n \"refusal\":
null,\n \"annotations\": []\n },\n \"logprobs\": null,\n
\ \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\":
24,\n \"completion_tokens\": 8,\n \"total_tokens\": 32,\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_b547601dbd\"\n}\n"
headers:
Access-Control-Expose-Headers:
- ACCESS-CONTROL-XXX
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 09:47:21 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
content-length:
- '821'
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '498'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '512'
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,112 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Say the word ''test'' once"}],"model":"gpt-4o-mini","stop":[],"temperature":0.1}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- ACCEPT-ENCODING-XXX
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '117'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.83.0
x-stainless-raw-response:
- 'true'
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: "{\n \"id\": \"chatcmpl-Chun59gINKMUmWS5cXrpCbkTyvkub\",\n \"object\":
\"chat.completion\",\n \"created\": 1764582443,\n \"model\": \"gpt-4o-mini-2024-07-18\",\n
\ \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\":
\"assistant\",\n \"content\": \"Test.\",\n \"refusal\": null,\n
\ \"annotations\": []\n },\n \"logprobs\": null,\n \"finish_reason\":
\"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\": 14,\n \"completion_tokens\":
2,\n \"total_tokens\": 16,\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_b547601dbd\"\n}\n"
headers:
Access-Control-Expose-Headers:
- ACCESS-CONTROL-XXX
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 09:47:23 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
content-length:
- '811'
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '195'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '208'
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,108 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Say hello"}],"model":"gpt-4o-mini"}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '74'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jFK7btwwEOz1FRvWp0A66B6+JjAOCOzOTYogMASKXElMKC5BUk4uxv17
QMo5yS/ADYudneHM7j5mAExJdgAmeh7EYHV+7N23Y7Uu7vBvi5u74brZl1+v8bvAjTiyVWRQ8xNF
+M/6LGiwGoMiM8HCIQ8YVcvdttpsr3ZVkYCBJOpI62zIK8oHZVS+LtZVXuzycv/E7kkJ9OwAPzIA
gMf0Rp9G4h92gKSVKgN6zztkh0sTAHOkY4Vx75UP3AS2mkFBJqBJ1m9Qa/oEN/QbBDdwCxMBTjRC
IMlPX5ZEh+3oeTRvRq0XADeGAo/hk+X7J+R8Mamps44a/4LKWmWU72uH3JOJhnwgyxJ6zgDu0zDG
Z/mYdTTYUAf6hem7q0mNzRt4jQUKXM/lcr96Q6uWGLjSfjFKJrjoUc7Mee58lIoWQLZI/NrLW9pT
amW6j8jPgBBoA8raOpRKPM87tzmM5/le22XCyTDz6B6UwDoodHELEls+6ulomD/5gEPdKtOhs05N
l9PautlUu21Rykay7Jz9AwAA//8DAOrvWDNHAwAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:40 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:
- '373'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '387'
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,109 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"My name is Alice."},{"role":"assistant","content":"Hello
Alice! Nice to meet you."},{"role":"user","content":"What is my name?"}],"model":"gpt-4o-mini"}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '191'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jJJBa9wwEIXv/hVC53XwJrvrdG8hhUBoD6HkUEowsjS2p5U0QpJLQtj/
HiTvrp02hV500Ddv9N5oXgvGOCq+Z1wOIkrjdHk7+Mdt/QU+Iz3v7h76l1u6cV/vH6q1+dbyVVJQ
+xNkPKkuJBmnISLZCUsPIkLquq53m+3uU311lYEhBTrJehfLDZUGLZaX1eWmrOpyfX1UD4QSAt+z
HwVjjL3mM/m0Cp75nlWr042BEEQPfH8uYox70umGixAwRGEjX81Qko1gs/XvNHpmhQGGgd1olHCx
rPTQjUEkt3bUegGEtRRFSps9Ph3J4exKU+88teEPKe/QYhgaDyKQTQ5CJMczPRSMPeX047tA3Hky
LjaRfkF+bhpkDnKa+Qy3RxYpCr3QXK8+aNYoiAJ1WAyPSyEHULNynrQYFdICFIvIf3v5qPcUG23/
P+1nICW4CKpxHhTK93nnMg9pIf9Vdh5xNswD+N8ooYkIPn2Dgk6MeloTHl5CBNN0aHvwzuO0K51r
2u2m3lVr1SpeHIo3AAAA//8DAFvbNx85AwAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:34 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:
- '300'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '316'
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,214 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"What is 1+1?"}],"model":"gpt-4o-mini"}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '77'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jJJPb5wwEMXvfAprrl2ihZIl2Wu06qFSD4mqSq0iZOwB3BrbtYe22Wi/
e2XYXcg/KRcO85s3fm+Yx4QxUBK2DETHSfROpzed/3pd31Hx7WHv938/7b74z3vd0O5W7L7DKips
/RMFnVQXwvZOIylrJiw8csI4NSs3xeXmuvxYjqC3EnWUtY7Swqa9MirN13mRrss0uzqqO6sEBtiy
HwljjD2O3+jTSPwHW7ZenSo9hsBbhO25iTHwVscK8BBUIG4IVjMU1hCa0XrGPrCM4e+B68Dyi2WX
x2YIPDo1g9YLwI2xxGPS0d/9kRzOjrRtnbd1eCaFRhkVusojD9bE1wNZByM9JIzdj8mHJ2HAeds7
qsj+wvG5rJjGwbzvGV4dGVniei7n+eqVYZVE4kqHxeJAcNGhnJXzlvkglV2AZBH5pZfXZk+xlWnf
M34GQqAjlJXzKJV4mndu8xiP8a2284pHwxDQ/1ECK1Lo42+Q2PBBTycC4SEQ9lWjTIveeTXdSeOq
+rIoN+tM1hKSQ/IfAAD//wMA1MCJGjUDAAA=
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:37 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:
- '352'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '614'
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":"user","content":"What is 2+2?"}],"model":"gpt-4o-mini"}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '77'
content-type:
- application/json
cookie:
- COOKIE-XXX
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jJJBb9QwEIXv+RXWXLupdkO6WfZWVUICceBAhRCqIq89Sdw6HmNPEFDt
f0dOtpu0FIlLDvPNG783mcdMCDAa9gJUJ1n13uY3Xbi9vvn4ubr9+nv35aEoP7zj5n2M92Q/NbBK
Cjrco+In1aWi3ltkQ27CKqBkTFM31ba82r6t3uxG0JNGm2St57ykvDfO5MW6KPN1lW92J3VHRmGE
vfiWCSHE4/hNPp3Gn7AX69VTpccYZYuwPzcJAYFsqoCM0USWjmE1Q0WO0Y3WC3EhCoHfB2mjKC+X
XQGbIcrk1A3WLoB0jlimpKO/uxM5nh1Zan2gQ3whhcY4E7s6oIzk0uuRycNIj5kQd2Py4VkY8IF6
zzXTA47PbcppHMz7nuHuxJhY2rlcFKtXhtUaWRobF4sDJVWHelbOW5aDNrQA2SLy315emz3FNq79
n/EzUAo9o659QG3U87xzW8B0jP9qO694NAwRww+jsGaDIf0GjY0c7HQiEH9Fxr5ujGsx+GCmO2l8
fbgqq+16ow8asmP2BwAA//8DAFoTX/E1AwAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:38 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:
- '390'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '542'
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,109 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Write a very long story about a
dragon."}],"model":"gpt-4o-mini","max_tokens":10}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '120'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jFLLbtswELzrKwgeDauQXUdKdGzgW3sp3AJtEwgUuZLYUlyCXKU1Av97
QfkhOW2AXHjY2VnOzO5zwhjXipeMy06Q7J1J7zv/5fbzB/H72377ae+fzPdd+HqX7bEY7g1fRgbW
P0HSmfVOYu8MkEZ7hKUHQRCnrop8c5PfFe/zEehRgYm01lG6wbTXVqfrbL1JsyJd3Z7YHWoJgZfs
R8IYY8/jG3VaBX94ybLludJDCKIFXl6aGOMeTaxwEYIOJCzx5QRKtAR2lL5Y7DQZKNmuA/ZRBGLb
vgbPsGFbo9BrsVg82Ac7p3tohiCiBTsYMwOEtUgiRjAKfzwhh4tUg63zWIcXVN5oq0NXeRABbZRl
wLbU8RE/JIw9jqEMVz6589g7qgh/wfjhKj8O5NMqZuApME5Iwkz19Zl0Na1SQEKbMAuVSyE7UBNz
2oAYlMYZkMxc/yvmf7OPzrVt3zJ+AqQER6Aq50FpeW14avMQD/W1tkvGo2AewD9pCRVp8HETChox
mOP58LAPBH3VaNuCd14fb6hxVX2zKfJspWrFk0PyFwAA//8DALc9uHlRAwAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:36 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:
- '383'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '398'
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,109 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Tell me a short fact"}],"model":"gpt-4o-mini","frequency_penalty":0.5,"max_tokens":100,"presence_penalty":0.3,"temperature":0.7,"top_p":0.9}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '179'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jFJNa9wwEL37Vww6r8N+O9lrIBS6tKdeWoKRpbGlVNYIaZw0hP3vxdoP
b9oUejFm3szTe2/mrQAQVosdCGUkqz648t7Eb9V6+7nSqZPYPOyt/vJ9/2n/YFbdrZiNE9Q8oeLz
1I2iPjhkS/4Iq4iScWRdVNv1ZntXrTYZ6EmjG8e6wOWayt56Wy7ny3U5r8rFiVwZsgqT2MGPAgDg
LX9HnV7jL7GD+exc6TEl2aHYXZoARCQ3VoRMySaWnsVsAhV5Rp+lf1VMYUiYwMhnBDYREQzKyGkH
/EIQhj5A44g0MAEbhM46l2bwYqzDXGBjo86NCSyf2yImBmrzf0P69eZaQcR2SHJMwQ/OXQHSe2I5
ppi9P56Qw8Wtoy5EatIfo6K13iZTR5SJ/OgsMQWR0UMB8JhTHd4FJUKkPnDN9BPzc4vlkU5Mu5zA
ZXUCmVi6qb66m33AVmtkaV262opQUhnU0+S0QjloS1dAceX5bzEfcR99W9/9D/0EKIWBUdchorbq
veGpLeJ46f9qu2ScBYuE8dkqrNliHPegsZWDO96fSK+Jsa9b6zuMIdrjEbah3ix0c7uWrWxEcSh+
AwAA//8DAGYleMGSAwAA
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:35 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:
- '656'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '918'
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,109 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Return a JSON object with a ''greeting''
field"}],"model":"gpt-4o-mini","response_format":{"type":"json_object"}}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '150'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jFK7jtswEOz1FczWViD7dNadyqQJ0iQpAgQXHQSaXFHMUSRBrvIy/O8B
JZ8l5wGkUbGzM5oZ7jFjDLSEmoHoOYnBm/x1Hz6+ethp9VBW/md8Vwjx/kP1lj5prp5gkxju8AUF
PbNeCjd4g6SdnWERkBMm1W21L2/399XN/QQMTqJJNOUpL10+aKvzXbEr86LKt3dndu+0wAg1+5wx
xthx+iafVuJ3qFmxeZ4MGCNXCPVliTEIzqQJ8Bh1JG4JNgsonCW0k/VjYxlrQAVE0lY1ULMG3qAx
bsO+uWDkiwYae1qzA3Zj5CmBHY1ZAdxaRzw1MPl+PCOni1PjlA/uEH+jQqetjn0bkEdnk6tIzsOE
njLGHqdGxquQ4IMbPLXknnD63fZuloPlHVbg7gySI26W+c25xWu1ViJxbeKqURBc9CgX5lI/H6V2
KyBbZf7TzN+059zaqv+RXwAh0BPK1geUWlwHXtYCpiv919ql48kwRAxftcCWNIb0DhI7Ppr5diD+
iIRD22mrMPig5wPqfHu4Lat9sZUHCdkp+wUAAP//AwDTbYBuTgMAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:39 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:
- '560'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '587'
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,109 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Tell me a short fact"}],"model":"gpt-4o-mini"}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '85'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jJNNb9swDIbv/hWEznGQpE7S5VYs2GWHXbZdhsKQJdpSK4uaRLcNivz3
wXYSJ/sAdjEMPuRr8iX9ngEIq8UOhDKSVRtc/tHEb/v0yX9+kD/3dv29MQ/Fpg537Wr/ZMSsr6Dq
CRWfq+aK2uCQLfkRq4iSsVddbjfFevNhWywH0JJG15c1gfOC8tZ6m68WqyJfbPPl/anakFWYxA5+
ZAAA78Oz79NrfBM7WMzOkRZTkg2K3SUJQERyfUTIlGxi6VnMJqjIM/qh9S+KKXQJExj5gsAmIoJB
GTmB9Boq1yFUjkjP4esrnVHo2jCGgQnYIDTWuTSDV4MRwTIEq54TdAHo7dCg74l1OKSysVGPSoNQ
6vNPMhETA9XDe0X6ML/uO2LdJdl75zvnroD0nlj23g+OPZ7I8eKRoyZEqtJvpaK23iZTRpSJfO9H
YgpioMcM4HHYRXdjrwiR2sAl0zMOn1uuRjkxXcAE7+5PkImlm+Lr0/5u1UqNLK1LV7sUSiqDeqqc
Fi87bekKZFcz/9nM37THua1v/kd+AkphYNRliKituh14SovY/x//Srt4PDQsEsYXq7Bki7Hfg8Za
dm68WpEOibEta+sbjCHa8XTrUFbrYrtZLHWlRXbMfgEAAP//AwBdcCb6yAMAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:43 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:
- '1535'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '1697'
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,109 @@
interactions:
- request:
body: '{"messages":[{"role":"system","content":"You are a helpful assistant."},{"role":"user","content":"What
is 2+2?"}],"model":"gpt-4o-mini"}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '136'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jFLLbtswELzrK4i91gpsWZZdX40e2mOb9FIEAk2uJDYUyZKrpEXgfy9I
uZacB9ALDzs7szPLfc4YAyVhz0B0nETvdH7o/N1h/XmzrtzhYffFf3281U9tJYZv390nWESGPf5E
Qf9YN8L2TiMpa0ZYeOSEUXW1rcpN9XFbLhPQW4k60lpHeWnzXhmVF8uizJfbfLU7szurBAbYsx8Z
Y4w9pzf6NBJ/w54lrVTpMQTeIuwvTYyBtzpWgIegAnFDsJhAYQ2hSdYL9oEVDH8NXAdW3sy7PDZD
4NGpGbSeAdwYSzwmTf7uz8jp4kjb1nl7DC+o0CijQld75MGaOD2QdZDQU8bYfUo+XIUB523vqCb7
gGlcUY5yMO17AndnjCxxPZXXxeINsVoicaXDbHEguOhQTsxpy3yQys6AbBb5tZe3tMfYyrT/Iz8B
QqAjlLXzKJW4zju1eYzH+F7bZcXJMAT0j0pgTQp9/AaJDR/0eCIQ/gTCvm6UadE7r8Y7aVx93JTb
armSRwnZKfsLAAD//wMAA+EJCDUDAAA=
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:41 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:
- '320'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '334'
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,108 @@
interactions:
- request:
body: '{"messages":[{"role":"user","content":"Say the word ''test'' once"}],"model":"gpt-4o-mini","temperature":0.1}'
headers:
User-Agent:
- X-USER-AGENT-XXX
accept:
- application/json
accept-encoding:
- gzip, deflate
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '107'
content-type:
- application/json
host:
- api.openai.com
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- async:asyncio
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.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jJJBT+MwEIXv+RXWnBvUltBCr0iAVisth+WEUOTak8TU8XjtCbBC/e/I
SWnCLkhcfPA3b/zeeF4zIcBo2AhQjWTVeptfNuHuavfY7upaXnU/fv55vnn6tcT6xdxe38EsKWj7
iIrfVSeKWm+RDbkBq4CSMXVdrFfF2epiXZz2oCWNNslqz3lBeWucyZfzZZHP1/ni/KBuyCiMsBH3
mRBCvPZn8uk0vsBGzGfvNy3GKGuEzbFICAhk0w3IGE1k6RhmI1TkGF1v/TdGPpmygFUXZfLnOmsn
QDpHLFO+3tXDgeyPPizVPtA2/iOFyjgTmzKgjOTSm5HJQ0/3mRAPfd7uQwTwgVrPJdMO++cWxdAO
ximPcHlgTCztRLOafdKs1MjS2DgZFyipGtSjcpyt7LShCcgmkf/38lnvIbZx9Xfaj0Ap9Iy69AG1
UR/zjmUB0wp+VXYccW8YIoYno7BkgyF9g8ZKdnZYDIh/I2NbVsbVGHwww3ZUvjxb6O15ISu5hWyf
vQEAAP//AwDSVh+sKwMAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Mon, 01 Dec 2025 06:15:43 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:
- '308'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '339'
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,199 @@
"""Tests for Anthropic async completion functionality."""
import json
import logging
import pytest
import tiktoken
from pydantic import BaseModel
from crewai.llm import LLM
from crewai.llms.providers.anthropic.completion import AnthropicCompletion
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_basic_call():
"""Test basic async call with Anthropic."""
llm = LLM(model="anthropic/claude-sonnet-4-0")
result = await llm.acall("Say hello")
assert result is not None
assert isinstance(result, str)
assert len(result) > 0
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_with_temperature():
"""Test async call with temperature parameter."""
llm = LLM(model="anthropic/claude-sonnet-4-0", temperature=0.1)
result = await llm.acall("Say the word 'test' once")
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_with_max_tokens():
"""Test async call with max_tokens parameter."""
llm = LLM(model="anthropic/claude-sonnet-4-0", max_tokens=10)
result = await llm.acall("Write a very long story about a dragon.")
assert result is not None
assert isinstance(result, str)
encoder = tiktoken.get_encoding("cl100k_base")
token_count = len(encoder.encode(result))
assert token_count <= 10
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_with_system_message():
"""Test async call with system message."""
llm = LLM(model="anthropic/claude-sonnet-4-0")
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_conversation():
"""Test async call with conversation history."""
llm = LLM(model="anthropic/claude-sonnet-4-0")
messages = [
{"role": "user", "content": "My name is Alice."},
{"role": "assistant", "content": "Hello Alice! Nice to meet you."},
{"role": "user", "content": "What is my name?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_stop_sequences():
"""Test async call with stop sequences."""
llm = LLM(
model="anthropic/claude-sonnet-4-0",
stop_sequences=["END", "STOP"]
)
result = await llm.acall("Count from 1 to 10")
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_multiple_calls():
"""Test making multiple async calls in sequence."""
llm = LLM(model="anthropic/claude-sonnet-4-0")
result1 = await llm.acall("What is 1+1?")
result2 = await llm.acall("What is 2+2?")
assert result1 is not None
assert result2 is not None
assert isinstance(result1, str)
assert isinstance(result2, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_with_response_format_none():
"""Test async call with response_format set to None."""
llm = LLM(model="anthropic/claude-sonnet-4-0", response_format=None)
result = await llm.acall("Tell me a short fact")
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_with_response_format_json():
"""Test async call with JSON response format."""
llm = LLM(model="anthropic/claude-sonnet-4-0", response_format={"type": "json_object"})
result = await llm.acall("Return a JSON object devoid of ```json{x}```, where x is the json object, with a 'greeting' field")
assert isinstance(result, str)
deserialized_result = json.loads(result)
assert isinstance(deserialized_result, dict)
assert isinstance(deserialized_result["greeting"], str)
class GreetingResponse(BaseModel):
"""Response model for greeting test."""
greeting: str
language: str
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_with_response_model():
"""Test async call with Pydantic response_model for structured output."""
llm = LLM(model="anthropic/claude-sonnet-4-0")
result = await llm.acall(
"Say hello in French",
response_model=GreetingResponse
)
model = GreetingResponse.model_validate_json(result)
assert isinstance(model, GreetingResponse)
assert isinstance(model.greeting, str)
assert isinstance(model.language, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_anthropic_async_with_tools():
"""Test async call with tools."""
llm = AnthropicCompletion(model="claude-sonnet-4-0")
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
}
},
"required": ["location"]
}
}
}
]
result = await llm.acall(
"What's the weather in San Francisco?",
tools=tools
)
logging.debug("result: %s", result)
assert result is not None
assert isinstance(result, str)

View File

@@ -0,0 +1,116 @@
"""Tests for Azure async completion functionality."""
import pytest
import tiktoken
from crewai.llm import LLM
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_azure_async_non_streaming():
"""Test basic async non-streaming call."""
llm = LLM(model="azure/gpt-4o-mini", stream=False)
result = await llm.acall("Say hello")
assert result is not None
assert isinstance(result, str)
assert len(result) > 0
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_azure_async_multiple_calls():
"""Test making multiple async calls in sequence."""
llm = LLM(model="azure/gpt-4o-mini", stream=False)
result1 = await llm.acall("What is 1+1?")
result2 = await llm.acall("What is 2+2?")
assert result1 is not None
assert result2 is not None
assert isinstance(result1, str)
assert isinstance(result2, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_azure_async_with_temperature():
"""Test async call with temperature parameter."""
llm = LLM(model="azure/gpt-4o-mini", temperature=0.1, stream=False)
result = await llm.acall("Say the word 'test' once")
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_azure_async_with_max_tokens():
"""Test async call with max_tokens parameter."""
llm = LLM(model="azure/gpt-4o-mini", max_tokens=10, stream=False)
result = await llm.acall("Write a very long story about a dragon.")
assert result is not None
assert isinstance(result, str)
encoder = tiktoken.get_encoding("cl100k_base")
token_count = len(encoder.encode(result))
assert token_count <= 10
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_azure_async_with_system_message():
"""Test async call with system message."""
llm = LLM(model="azure/gpt-4o-mini", stream=False)
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_azure_async_with_parameters():
"""Test async call with multiple parameters."""
llm = LLM(
model="azure/gpt-4o-mini",
temperature=0.7,
max_tokens=100,
top_p=0.9,
frequency_penalty=0.5,
presence_penalty=0.3,
stream=False
)
result = await llm.acall("Tell me a short fact")
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_azure_async_conversation():
"""Test async call with conversation history."""
llm = LLM(model="azure/gpt-4o-mini", stream=False)
messages = [
{"role": "user", "content": "My name is Alice."},
{"role": "assistant", "content": "Hello Alice! Nice to meet you."},
{"role": "user", "content": "What is my name?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)

View File

@@ -0,0 +1,127 @@
"""Tests for Bedrock async completion functionality.
Note: These tests are skipped in CI because VCR.py does not support
aiobotocore's HTTP session. The cassettes were recorded locally but
cannot be played back properly in CI.
"""
import pytest
import tiktoken
from crewai.llm import LLM
SKIP_REASON = "VCR does not support aiobotocore async HTTP client"
@pytest.mark.vcr()
@pytest.mark.asyncio
@pytest.mark.skip(reason=SKIP_REASON)
async def test_bedrock_async_basic_call():
"""Test basic async call with Bedrock."""
llm = LLM(model="bedrock/us.anthropic.claude-3-5-sonnet-20241022-v2:0")
result = await llm.acall("Say hello")
assert result is not None
assert isinstance(result, str)
assert len(result) > 0
@pytest.mark.vcr()
@pytest.mark.asyncio
@pytest.mark.skip(reason=SKIP_REASON)
async def test_bedrock_async_with_temperature():
"""Test async call with temperature parameter."""
llm = LLM(model="bedrock/us.anthropic.claude-3-5-sonnet-20241022-v2:0", temperature=0.1)
result = await llm.acall("Say the word 'test' once")
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
@pytest.mark.skip(reason=SKIP_REASON)
async def test_bedrock_async_with_max_tokens():
"""Test async call with max_tokens parameter."""
llm = LLM(model="bedrock/us.anthropic.claude-3-5-sonnet-20241022-v2:0", max_tokens=10)
result = await llm.acall("Write a very long story about a dragon.")
assert result is not None
assert isinstance(result, str)
encoder = tiktoken.get_encoding("cl100k_base")
token_count = len(encoder.encode(result))
assert token_count <= 10
@pytest.mark.vcr()
@pytest.mark.asyncio
@pytest.mark.skip(reason=SKIP_REASON)
async def test_bedrock_async_with_system_message():
"""Test async call with system message."""
llm = LLM(model="bedrock/us.anthropic.claude-3-5-sonnet-20241022-v2:0")
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
@pytest.mark.skip(reason=SKIP_REASON)
async def test_bedrock_async_conversation():
"""Test async call with conversation history."""
llm = LLM(model="bedrock/us.anthropic.claude-3-5-sonnet-20241022-v2:0")
messages = [
{"role": "user", "content": "My name is Alice."},
{"role": "assistant", "content": "Hello Alice! Nice to meet you."},
{"role": "user", "content": "What is my name?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
@pytest.mark.skip(reason=SKIP_REASON)
async def test_bedrock_async_multiple_calls():
"""Test making multiple async calls in sequence."""
llm = LLM(model="bedrock/us.anthropic.claude-3-5-sonnet-20241022-v2:0")
result1 = await llm.acall("What is 1+1?")
result2 = await llm.acall("What is 2+2?")
assert result1 is not None
assert result2 is not None
assert isinstance(result1, str)
assert isinstance(result2, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
@pytest.mark.skip(reason=SKIP_REASON)
async def test_bedrock_async_with_parameters():
"""Test async call with multiple parameters."""
llm = LLM(
model="bedrock/us.anthropic.claude-3-5-sonnet-20241022-v2:0",
temperature=0.7,
max_tokens=100,
top_p=0.9
)
result = await llm.acall("Tell me a short fact")
assert result is not None
assert isinstance(result, str)

View File

@@ -0,0 +1,114 @@
"""Tests for Google (Gemini) async completion functionality."""
import pytest
import tiktoken
from crewai.llm import LLM
from crewai.llms.providers.gemini.completion import GeminiCompletion
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_gemini_async_basic_call():
"""Test basic async call with Gemini."""
llm = LLM(model="gemini/gemini-3-pro-preview")
result = await llm.acall("Say hello")
assert result is not None
assert isinstance(result, str)
assert len(result) > 0
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_gemini_async_with_temperature():
"""Test async call with temperature parameter."""
llm = LLM(model="gemini/gemini-3-pro-preview", temperature=0.1)
result = await llm.acall("Say the word 'test' once")
assert result is not None
assert isinstance(result, str)
@pytest.mark.asyncio
@pytest.mark.vcr
async def test_gemini_async_with_max_tokens():
"""Test async call with max_tokens parameter."""
llm = GeminiCompletion(model="gemini-3-pro-preview", max_output_tokens=1000)
result = await llm.acall("Write a very short story about a dragon.")
assert result is not None
assert isinstance(result, str)
encoder = tiktoken.get_encoding("cl100k_base")
token_count = len(encoder.encode(result))
assert token_count <= 1000
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_gemini_async_with_system_message():
"""Test async call with system message."""
llm = LLM(model="gemini/gemini-3-pro-preview")
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_gemini_async_conversation():
"""Test async call with conversation history."""
llm = LLM(model="gemini/gemini-3-pro-preview")
messages = [
{"role": "user", "content": "My name is Alice."},
{"role": "assistant", "content": "Hello Alice! Nice to meet you."},
{"role": "user", "content": "What is my name?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_gemini_async_multiple_calls():
"""Test making multiple async calls in sequence."""
llm = LLM(model="gemini/gemini-3-pro-preview")
result1 = await llm.acall("What is 1+1?")
result2 = await llm.acall("What is 2+2?")
assert result1 is not None
assert result2 is not None
assert isinstance(result1, str)
assert isinstance(result2, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_gemini_async_with_parameters():
"""Test async call with multiple parameters."""
llm = LLM(
model="gemini/gemini-3-pro-preview",
temperature=0.7,
max_output_tokens=1000,
top_p=0.9
)
result = await llm.acall("Tell me a short fact")
assert result is not None
assert isinstance(result, str)

View File

@@ -0,0 +1 @@
"""LiteLLM fallback tests."""

View File

@@ -0,0 +1,156 @@
"""Tests for LiteLLM fallback async completion functionality."""
import pytest
import tiktoken
from crewai.llm import LLM
@pytest.mark.asyncio
@pytest.mark.vcr
@pytest.mark.skip(reason="cassettes do not read properly but were generated correctly.")
async def test_litellm_async_basic_call():
"""Test basic async call with LiteLLM fallback."""
llm = LLM(model="gpt-4o-mini", is_litellm=True)
result = await llm.acall("Say hello")
assert result is not None
assert isinstance(result, str)
assert len(result) > 0
@pytest.mark.asyncio
@pytest.mark.vcr
@pytest.mark.skip(reason="cassettes do not read properly but were generated correctly.")
async def test_litellm_async_with_temperature():
"""Test async call with temperature parameter."""
llm = LLM(model="gpt-4o-mini", is_litellm=True, temperature=0.1)
result = await llm.acall("Say the word 'test' once")
assert result is not None
assert isinstance(result, str)
@pytest.mark.asyncio
@pytest.mark.vcr
@pytest.mark.skip(reason="cassettes do not read properly but were generated correctly.")
async def test_litellm_async_with_max_tokens():
"""Test async call with max_tokens parameter."""
llm = LLM(model="gpt-4o-mini", is_litellm=True, max_tokens=10)
result = await llm.acall("Write a very long story about a dragon.")
assert result is not None
assert isinstance(result, str)
encoder = tiktoken.get_encoding("cl100k_base")
token_count = len(encoder.encode(result))
assert token_count <= 10
@pytest.mark.asyncio
@pytest.mark.vcr
@pytest.mark.skip(reason="cassettes do not read properly but were generated correctly.")
async def test_litellm_async_with_system_message():
"""Test async call with system message."""
llm = LLM(model="gpt-4o-mini", is_litellm=True)
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"},
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.asyncio
@pytest.mark.vcr
@pytest.mark.skip(reason="cassettes do not read properly but were generated correctly.")
async def test_litellm_async_conversation():
"""Test async call with conversation history."""
llm = LLM(model="gpt-4o-mini", is_litellm=True)
messages = [
{"role": "user", "content": "My name is Alice."},
{"role": "assistant", "content": "Hello Alice! Nice to meet you."},
{"role": "user", "content": "What is my name?"},
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.asyncio
@pytest.mark.vcr
@pytest.mark.skip(reason="cassettes do not read properly but were generated correctly.")
async def test_litellm_async_multiple_calls():
"""Test making multiple async calls in sequence."""
llm = LLM(model="gpt-4o-mini", is_litellm=True)
result1 = await llm.acall("What is 1+1?")
result2 = await llm.acall("What is 2+2?")
assert result1 is not None
assert result2 is not None
assert isinstance(result1, str)
assert isinstance(result2, str)
@pytest.mark.asyncio
@pytest.mark.vcr
@pytest.mark.skip(reason="cassettes do not read properly but were generated correctly.")
async def test_litellm_async_with_parameters():
"""Test async call with multiple parameters."""
llm = LLM(
model="gpt-4o-mini",
is_litellm=True,
temperature=0.7,
max_tokens=100,
top_p=0.9,
frequency_penalty=0.5,
presence_penalty=0.3,
)
result = await llm.acall("Tell me a short fact")
assert result is not None
assert isinstance(result, str)
@pytest.mark.asyncio
@pytest.mark.vcr
@pytest.mark.skip(reason="cassettes do not read properly but were generated correctly.")
async def test_litellm_async_streaming():
"""Test async streaming call with LiteLLM fallback."""
llm = LLM(model="gpt-4o-mini", is_litellm=True, stream=True)
result = await llm.acall("Say hello world")
assert result is not None
assert isinstance(result, str)
assert len(result) > 0
@pytest.mark.asyncio
@pytest.mark.vcr
@pytest.mark.skip(reason="cassettes do not read properly but were generated correctly.")
async def test_litellm_async_streaming_with_parameters():
"""Test async streaming call with multiple parameters."""
llm = LLM(
model="gpt-4o-mini",
is_litellm=True,
stream=True,
temperature=0.5,
max_tokens=50,
)
result = await llm.acall("Count from 1 to 5")
assert result is not None
assert isinstance(result, str)

View File

@@ -475,10 +475,14 @@ def test_openai_get_client_params_priority_order():
params3 = llm3._get_client_params()
assert params3["base_url"] == "https://env.openai.com/v1"
def test_openai_get_client_params_no_base_url():
def test_openai_get_client_params_no_base_url(monkeypatch):
"""
Test that _get_client_params works correctly when no base_url is specified
"""
# Clear env vars that could set base_url
monkeypatch.delenv("OPENAI_BASE_URL", raising=False)
monkeypatch.delenv("OPENAI_API_BASE", raising=False)
llm = OpenAICompletion(model="gpt-4o")
client_params = llm._get_client_params()
# When no base_url is provided, it should not be in the params (filtered out as None)

View File

@@ -0,0 +1,139 @@
"""Tests for OpenAI async completion functionality."""
import pytest
import tiktoken
from crewai.llm import LLM
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_openai_async_basic_call():
"""Test basic async call with OpenAI."""
llm = LLM(model="gpt-4o-mini")
result = await llm.acall("Say hello")
assert result is not None
assert isinstance(result, str)
assert len(result) > 0
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_openai_async_with_temperature():
"""Test async call with temperature parameter."""
llm = LLM(model="gpt-4o-mini", temperature=0.1)
result = await llm.acall("Say the word 'test' once")
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_openai_async_with_max_tokens():
"""Test async call with max_tokens parameter."""
llm = LLM(model="gpt-4o-mini", max_tokens=10)
result = await llm.acall("Write a very long story about a dragon.")
assert result is not None
assert isinstance(result, str)
encoder = tiktoken.get_encoding("cl100k_base")
token_count = len(encoder.encode(result))
assert token_count <= 10
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_openai_async_with_system_message():
"""Test async call with system message."""
llm = LLM(model="gpt-4o-mini")
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_openai_async_conversation():
"""Test async call with conversation history."""
llm = LLM(model="gpt-4o-mini")
messages = [
{"role": "user", "content": "My name is Alice."},
{"role": "assistant", "content": "Hello Alice! Nice to meet you."},
{"role": "user", "content": "What is my name?"}
]
result = await llm.acall(messages)
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_openai_async_multiple_calls():
"""Test making multiple async calls in sequence."""
llm = LLM(model="gpt-4o-mini")
result1 = await llm.acall("What is 1+1?")
result2 = await llm.acall("What is 2+2?")
assert result1 is not None
assert result2 is not None
assert isinstance(result1, str)
assert isinstance(result2, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_openai_async_with_response_format_none():
"""Test async call with response_format set to None."""
llm = LLM(model="gpt-4o-mini", response_format=None)
result = await llm.acall("Tell me a short fact")
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_openai_async_with_response_format_json():
"""Test async call with JSON response format."""
llm = LLM(model="gpt-4o-mini", response_format={"type": "json_object"})
result = await llm.acall("Return a JSON object with a 'greeting' field")
assert result is not None
assert isinstance(result, str)
@pytest.mark.vcr()
@pytest.mark.asyncio
async def test_openai_async_with_parameters():
"""Test async call with multiple parameters."""
llm = LLM(
model="gpt-4o-mini",
temperature=0.7,
max_tokens=100,
top_p=0.9,
frequency_penalty=0.5,
presence_penalty=0.3
)
result = await llm.acall("Tell me a short fact")
assert result is not None
assert isinstance(result, str)

View File

@@ -77,6 +77,9 @@ class CustomLLM(BaseLLM):
"""
return 4096
async def acall(self, messages, tools=None, callbacks=None, available_functions=None, from_task=None, from_agent=None, response_model=None):
raise NotImplementedError
@pytest.mark.vcr()
def test_custom_llm_implementation():
@@ -192,6 +195,9 @@ class JWTAuthLLM(BaseLLM):
"""Return a default context window size."""
return 8192
async def acall(self, messages, tools=None, callbacks=None, available_functions=None, from_task=None, from_agent=None, response_model=None):
raise NotImplementedError
def test_custom_llm_with_jwt_auth():
"""Test a custom LLM implementation with JWT authentication."""
@@ -339,6 +345,9 @@ class TimeoutHandlingLLM(BaseLLM):
"""
return 8192
async def acall(self, messages, tools=None, callbacks=None, available_functions=None, from_task=None, from_agent=None, response_model=None):
raise NotImplementedError
def test_timeout_handling_llm():
"""Test a custom LLM implementation with timeout handling and retry logic."""

View File

@@ -10,12 +10,12 @@ requires-python = ">=3.10, <3.14"
classifiers = ["Private :: Do Not Upload"]
private = true
dependencies = [
"click>=8.3.0",
"toml>=0.10.2",
"openai>=1.0.0",
"python-dotenv>=1.1.1",
"pygithub>=1.59.1",
"rich>=13.9.4",
"click~=8.1.7",
"toml~=0.10.2",
"openai~=1.83.0",
"python-dotenv~=1.1.1",
"pygithub~=1.59.1",
"rich~=13.9.4",
]
[project.scripts]

View File

@@ -8,26 +8,26 @@ authors = [
[dependency-groups]
dev = [
"ruff>=0.13.1",
"mypy>=1.18.2",
"pre-commit>=4.3.0",
"bandit>=1.8.6",
"pytest>=8.4.2",
"pytest-asyncio>=1.2.0",
"pytest-subprocess>=1.5.3",
"ruff==0.14.7",
"mypy==1.19.0",
"pre-commit==4.5.0",
"bandit==1.9.2",
"pytest==8.4.2",
"pytest-asyncio==1.3.0",
"pytest-subprocess==1.5.3",
"vcrpy==7.0.0", # pinned, less versions break pytest-recording
"pytest-recording>=0.13.4",
"pytest-randomly>=4.0.1",
"pytest-timeout>=2.4.0",
"pytest-xdist>=3.8.0",
"pytest-split>=0.10.0",
"pytest-recording==0.13.4",
"pytest-randomly==4.0.1",
"pytest-timeout==2.4.0",
"pytest-xdist==3.8.0",
"pytest-split==0.10.0",
"types-requests~=2.31.0.6",
"types-pyyaml==6.0.*",
"types-regex==2024.11.6.*",
"types-appdirs==1.4.*",
"boto3-stubs[bedrock-runtime]>=1.40.54",
"types-psycopg2>=2.9.21.20251012",
"types-pymysql>=1.1.0.20250916",
"boto3-stubs[bedrock-runtime]==1.40.54",
"types-psycopg2==2.9.21.20251012",
"types-pymysql==1.1.0.20250916",
]

3414
uv.lock generated

File diff suppressed because it is too large Load Diff