mirror of
https://github.com/crewAIInc/crewAI.git
synced 2025-12-15 11:58:31 +00:00
supporting thinking for anthropic models (#3978)
* supporting thinking for anthropic models * drop comments here * thinking and tool calling support * fix: properly mock tool use and text block types in Anthropic tests - Updated the test for the Anthropic tool use conversation flow to include type attributes for mocked ToolUseBlock and text blocks, ensuring accurate simulation of tool interactions during testing. * feat: add AnthropicThinkingConfig for enhanced thinking capabilities This update introduces the AnthropicThinkingConfig class to manage thinking parameters for the Anthropic completion model. The LLM and AnthropicCompletion classes have been updated to utilize this new configuration. Additionally, new test cassettes have been added to validate the functionality of thinking blocks across interactions.
This commit is contained in:
@@ -283,11 +283,54 @@ In this section, you'll find detailed examples that help you select, configure,
|
||||
)
|
||||
```
|
||||
|
||||
**Extended Thinking (Claude Sonnet 4 and Beyond):**
|
||||
|
||||
CrewAI supports Anthropic's Extended Thinking feature, which allows Claude to think through problems in a more human-like way before responding. This is particularly useful for complex reasoning, analysis, and problem-solving tasks.
|
||||
|
||||
```python Code
|
||||
from crewai import LLM
|
||||
|
||||
# Enable extended thinking with default settings
|
||||
llm = LLM(
|
||||
model="anthropic/claude-sonnet-4",
|
||||
thinking={"type": "enabled"},
|
||||
max_tokens=10000
|
||||
)
|
||||
|
||||
# Configure thinking with budget control
|
||||
llm = LLM(
|
||||
model="anthropic/claude-sonnet-4",
|
||||
thinking={
|
||||
"type": "enabled",
|
||||
"budget_tokens": 5000 # Limit thinking tokens
|
||||
},
|
||||
max_tokens=10000
|
||||
)
|
||||
```
|
||||
|
||||
**Thinking Configuration Options:**
|
||||
- `type`: Set to `"enabled"` to activate extended thinking mode
|
||||
- `budget_tokens` (optional): Maximum tokens to use for thinking (helps control costs)
|
||||
|
||||
**Models Supporting Extended Thinking:**
|
||||
- `claude-sonnet-4` and newer models
|
||||
- `claude-3-7-sonnet` (with extended thinking capabilities)
|
||||
|
||||
**When to Use Extended Thinking:**
|
||||
- Complex reasoning and multi-step problem solving
|
||||
- Mathematical calculations and proofs
|
||||
- Code analysis and debugging
|
||||
- Strategic planning and decision making
|
||||
- Research and analytical tasks
|
||||
|
||||
**Note:** Extended thinking consumes additional tokens but can significantly improve response quality for complex tasks.
|
||||
|
||||
**Supported Environment Variables:**
|
||||
- `ANTHROPIC_API_KEY`: Your Anthropic API key (required)
|
||||
|
||||
**Features:**
|
||||
- Native tool use support for Claude 3+ models
|
||||
- Extended Thinking support for Claude Sonnet 4+
|
||||
- Streaming support for real-time responses
|
||||
- Automatic system message handling
|
||||
- Stop sequences for controlled output
|
||||
@@ -305,6 +348,7 @@ In this section, you'll find detailed examples that help you select, configure,
|
||||
|
||||
| Model | Context Window | Best For |
|
||||
|------------------------------|----------------|-----------------------------------------------|
|
||||
| claude-sonnet-4 | 200,000 tokens | Latest with extended thinking capabilities |
|
||||
| claude-3-7-sonnet | 200,000 tokens | Advanced reasoning and agentic tasks |
|
||||
| claude-3-5-sonnet-20241022 | 200,000 tokens | Latest Sonnet with best performance |
|
||||
| claude-3-5-haiku | 200,000 tokens | Fast, compact model for quick responses |
|
||||
|
||||
@@ -67,6 +67,7 @@ if TYPE_CHECKING:
|
||||
|
||||
from crewai.agent.core import Agent
|
||||
from crewai.llms.hooks.base import BaseInterceptor
|
||||
from crewai.llms.providers.anthropic.completion import AnthropicThinkingConfig
|
||||
from crewai.task import Task
|
||||
from crewai.tools.base_tool import BaseTool
|
||||
from crewai.utilities.types import LLMMessage
|
||||
@@ -585,6 +586,7 @@ class LLM(BaseLLM):
|
||||
reasoning_effort: Literal["none", "low", "medium", "high"] | None = None,
|
||||
stream: bool = False,
|
||||
interceptor: BaseInterceptor[httpx.Request, httpx.Response] | None = None,
|
||||
thinking: AnthropicThinkingConfig | dict[str, Any] | None = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
"""Initialize LLM instance.
|
||||
|
||||
@@ -3,8 +3,9 @@ from __future__ import annotations
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
from typing import TYPE_CHECKING, Any, Literal, cast
|
||||
|
||||
from anthropic.types import ThinkingBlock
|
||||
from pydantic import BaseModel
|
||||
|
||||
from crewai.events.types.llm_events import LLMCallType
|
||||
@@ -22,8 +23,7 @@ if TYPE_CHECKING:
|
||||
|
||||
try:
|
||||
from anthropic import Anthropic, AsyncAnthropic
|
||||
from anthropic.types import Message
|
||||
from anthropic.types.tool_use_block import ToolUseBlock
|
||||
from anthropic.types import Message, TextBlock, ThinkingBlock, ToolUseBlock
|
||||
import httpx
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
@@ -31,6 +31,11 @@ except ImportError:
|
||||
) from None
|
||||
|
||||
|
||||
class AnthropicThinkingConfig(BaseModel):
|
||||
type: Literal["enabled", "disabled"]
|
||||
budget_tokens: int | None = None
|
||||
|
||||
|
||||
class AnthropicCompletion(BaseLLM):
|
||||
"""Anthropic native completion implementation.
|
||||
|
||||
@@ -52,6 +57,7 @@ class AnthropicCompletion(BaseLLM):
|
||||
stream: bool = False,
|
||||
client_params: dict[str, Any] | None = None,
|
||||
interceptor: BaseInterceptor[httpx.Request, httpx.Response] | None = None,
|
||||
thinking: AnthropicThinkingConfig | None = None,
|
||||
**kwargs: Any,
|
||||
):
|
||||
"""Initialize Anthropic chat completion client.
|
||||
@@ -97,6 +103,10 @@ class AnthropicCompletion(BaseLLM):
|
||||
self.top_p = top_p
|
||||
self.stream = stream
|
||||
self.stop_sequences = stop_sequences or []
|
||||
self.thinking = thinking
|
||||
self.previous_thinking_blocks: list[ThinkingBlock] = []
|
||||
# Model-specific settings
|
||||
self.is_claude_3 = "claude-3" in model.lower()
|
||||
self.supports_tools = True
|
||||
|
||||
@property
|
||||
@@ -326,6 +336,12 @@ class AnthropicCompletion(BaseLLM):
|
||||
if tools and self.supports_tools:
|
||||
params["tools"] = self._convert_tools_for_interference(tools)
|
||||
|
||||
if self.thinking:
|
||||
if isinstance(self.thinking, AnthropicThinkingConfig):
|
||||
params["thinking"] = self.thinking.model_dump()
|
||||
else:
|
||||
params["thinking"] = self.thinking
|
||||
|
||||
return params
|
||||
|
||||
def _convert_tools_for_interference(
|
||||
@@ -365,6 +381,34 @@ class AnthropicCompletion(BaseLLM):
|
||||
|
||||
return anthropic_tools
|
||||
|
||||
def _extract_thinking_block(
|
||||
self, content_block: Any
|
||||
) -> ThinkingBlock | dict[str, Any] | None:
|
||||
"""Extract and format thinking block from content block.
|
||||
|
||||
Args:
|
||||
content_block: Content block from Anthropic response
|
||||
|
||||
Returns:
|
||||
Dictionary with thinking block data including signature, or None if not a thinking block
|
||||
"""
|
||||
if content_block.type == "thinking":
|
||||
thinking_block = {
|
||||
"type": "thinking",
|
||||
"thinking": content_block.thinking,
|
||||
}
|
||||
if hasattr(content_block, "signature"):
|
||||
thinking_block["signature"] = content_block.signature
|
||||
return thinking_block
|
||||
if content_block.type == "redacted_thinking":
|
||||
redacted_block = {"type": "redacted_thinking"}
|
||||
if hasattr(content_block, "thinking"):
|
||||
redacted_block["thinking"] = content_block.thinking
|
||||
if hasattr(content_block, "signature"):
|
||||
redacted_block["signature"] = content_block.signature
|
||||
return redacted_block
|
||||
return None
|
||||
|
||||
def _format_messages_for_anthropic(
|
||||
self, messages: str | list[LLMMessage]
|
||||
) -> tuple[list[LLMMessage], str | None]:
|
||||
@@ -374,6 +418,7 @@ class AnthropicCompletion(BaseLLM):
|
||||
- System messages are separate from conversation messages
|
||||
- Messages must alternate between user and assistant
|
||||
- First message must be from user
|
||||
- When thinking is enabled, assistant messages must start with thinking blocks
|
||||
|
||||
Args:
|
||||
messages: Input messages
|
||||
@@ -398,8 +443,29 @@ class AnthropicCompletion(BaseLLM):
|
||||
system_message = cast(str, content)
|
||||
else:
|
||||
role_str = role if role is not None else "user"
|
||||
content_str = content if content is not None else ""
|
||||
formatted_messages.append({"role": role_str, "content": content_str})
|
||||
|
||||
if isinstance(content, list):
|
||||
formatted_messages.append({"role": role_str, "content": content})
|
||||
elif (
|
||||
role_str == "assistant"
|
||||
and self.thinking
|
||||
and self.previous_thinking_blocks
|
||||
):
|
||||
structured_content = cast(
|
||||
list[dict[str, Any]],
|
||||
[
|
||||
*self.previous_thinking_blocks,
|
||||
{"type": "text", "text": content if content else ""},
|
||||
],
|
||||
)
|
||||
formatted_messages.append(
|
||||
LLMMessage(role=role_str, content=structured_content)
|
||||
)
|
||||
else:
|
||||
content_str = content if content is not None else ""
|
||||
formatted_messages.append(
|
||||
LLMMessage(role=role_str, content=content_str)
|
||||
)
|
||||
|
||||
# Ensure first message is from user (Anthropic requirement)
|
||||
if not formatted_messages:
|
||||
@@ -449,7 +515,6 @@ class AnthropicCompletion(BaseLLM):
|
||||
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,
|
||||
@@ -477,15 +542,22 @@ class AnthropicCompletion(BaseLLM):
|
||||
from_agent,
|
||||
)
|
||||
|
||||
# Extract text content
|
||||
content = ""
|
||||
thinking_blocks: list[ThinkingBlock] = []
|
||||
|
||||
if response.content:
|
||||
for content_block in response.content:
|
||||
if hasattr(content_block, "text"):
|
||||
content += content_block.text
|
||||
else:
|
||||
thinking_block = self._extract_thinking_block(content_block)
|
||||
if thinking_block:
|
||||
thinking_blocks.append(cast(ThinkingBlock, thinking_block))
|
||||
|
||||
if thinking_blocks:
|
||||
self.previous_thinking_blocks = thinking_blocks
|
||||
|
||||
content = self._apply_stop_words(content)
|
||||
|
||||
self._emit_call_completed_event(
|
||||
response=content,
|
||||
call_type=LLMCallType.LLM_CALL,
|
||||
@@ -540,6 +612,16 @@ class AnthropicCompletion(BaseLLM):
|
||||
|
||||
final_message: Message = stream.get_final_message()
|
||||
|
||||
thinking_blocks: list[ThinkingBlock] = []
|
||||
if final_message.content:
|
||||
for content_block in final_message.content:
|
||||
thinking_block = self._extract_thinking_block(content_block)
|
||||
if thinking_block:
|
||||
thinking_blocks.append(cast(ThinkingBlock, thinking_block))
|
||||
|
||||
if thinking_blocks:
|
||||
self.previous_thinking_blocks = thinking_blocks
|
||||
|
||||
usage = self._extract_anthropic_token_usage(final_message)
|
||||
self._track_token_usage_internal(usage)
|
||||
|
||||
@@ -644,7 +726,26 @@ class AnthropicCompletion(BaseLLM):
|
||||
follow_up_params = params.copy()
|
||||
|
||||
# Add Claude's tool use response to conversation
|
||||
assistant_message = {"role": "assistant", "content": initial_response.content}
|
||||
assistant_content: list[
|
||||
ThinkingBlock | ToolUseBlock | TextBlock | dict[str, Any]
|
||||
] = []
|
||||
for block in initial_response.content:
|
||||
thinking_block = self._extract_thinking_block(block)
|
||||
if thinking_block:
|
||||
assistant_content.append(thinking_block)
|
||||
elif block.type == "tool_use":
|
||||
assistant_content.append(
|
||||
{
|
||||
"type": "tool_use",
|
||||
"id": block.id,
|
||||
"name": block.name,
|
||||
"input": block.input,
|
||||
}
|
||||
)
|
||||
elif hasattr(block, "text"):
|
||||
assistant_content.append({"type": "text", "text": block.text})
|
||||
|
||||
assistant_message = {"role": "assistant", "content": assistant_content}
|
||||
|
||||
# Add user message with tool results
|
||||
user_message = {"role": "user", "content": tool_results}
|
||||
@@ -663,12 +764,20 @@ class AnthropicCompletion(BaseLLM):
|
||||
follow_up_usage = self._extract_anthropic_token_usage(final_response)
|
||||
self._track_token_usage_internal(follow_up_usage)
|
||||
|
||||
# Extract final text content
|
||||
final_content = ""
|
||||
thinking_blocks: list[ThinkingBlock] = []
|
||||
|
||||
if final_response.content:
|
||||
for content_block in final_response.content:
|
||||
if hasattr(content_block, "text"):
|
||||
final_content += content_block.text
|
||||
else:
|
||||
thinking_block = self._extract_thinking_block(content_block)
|
||||
if thinking_block:
|
||||
thinking_blocks.append(cast(ThinkingBlock, thinking_block))
|
||||
|
||||
if thinking_blocks:
|
||||
self.previous_thinking_blocks = thinking_blocks
|
||||
|
||||
final_content = self._apply_stop_words(final_content)
|
||||
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"What is the weather
|
||||
in Tokyo? Use the get_weather tool."}],"model":"claude-sonnet-4-5","stream":false,"tools":[{"name":"get_weather","description":"Get
|
||||
the current weather in a given location","input_schema":{"type":"object","properties":{"location":{"type":"string","description":"The
|
||||
city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"],"description":"The
|
||||
unit of temperature"}},"required":["location"]}}]}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- ACCEPT-ENCODING-XXX
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '509'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- X-USER-AGENT-XXX
|
||||
x-stainless-arch:
|
||||
- X-STAINLESS-ARCH-XXX
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- X-STAINLESS-OS-XXX
|
||||
x-stainless-package-version:
|
||||
- 0.71.1
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAAwAAAP//dJBBS8NAEIX/isx5A0k0he5NhR60FRG9KLKsmzGJ3eyku7O1JeS/SyLV
|
||||
qnic9703j5keWirRggRjdSwxCeQccnKWFEme5kU6z+cgoClBQhsqlWYXp6+rl+a8NrvIzfbuMqti
|
||||
tnkEAbzvcHRhCLpCEODJjoIOoQmsHYMAQ47RMcin/uBnIqtiwEPLOEeVZuf0sFjla7pZhkUw17Pd
|
||||
m1veEghwuh1zFbJ6R801+jHqusgge7BkNDfkQMI9rfckTq50px0Mw7OAwNQpjzpM/Kh5AgE3EZ1B
|
||||
kC5aKyBOd8j+c7liWqMLIGd5KsBoU6MyHqcy9dPxxT3q8j92yI4F2NXYotdWFe1f/zfN6t90EECR
|
||||
j6WiEBDQbxuDihv0IGH8fql9CcPwAQAA//8DAI8uRSjwAQAA
|
||||
headers:
|
||||
CF-RAY:
|
||||
- CF-RAY-XXX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 08 Dec 2025 23:16: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-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-12-08T23:16:54Z'
|
||||
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:
|
||||
- '2925'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: "{\"max_tokens\":4096,\"messages\":[{\"role\":\"user\",\"content\":\"What
|
||||
is the weather in Tokyo? Use the get_weather tool.\"},{\"role\":\"assistant\",\"content\":[{\"type\":\"tool_use\",\"id\":\"toolu_01AoUFM2koNLsFscK6xjnLPo\",\"name\":\"get_weather\",\"input\":{\"location\":\"Tokyo,
|
||||
Japan\"}}]},{\"role\":\"user\",\"content\":[{\"type\":\"tool_result\",\"tool_use_id\":\"toolu_01AoUFM2koNLsFscK6xjnLPo\",\"content\":\"The
|
||||
weather in Tokyo, Japan is sunny and 72\xB0F\"}]}],\"model\":\"claude-sonnet-4-5\",\"stream\":false,\"tools\":[{\"name\":\"get_weather\",\"description\":\"Get
|
||||
the current weather in a given location\",\"input_schema\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The
|
||||
city and state, e.g. San Francisco, CA\"},\"unit\":{\"type\":\"string\",\"enum\":[\"celsius\",\"fahrenheit\"],\"description\":\"The
|
||||
unit of temperature\"}},\"required\":[\"location\"]}}]}"
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- ACCEPT-ENCODING-XXX
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '814'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- X-USER-AGENT-XXX
|
||||
x-stainless-arch:
|
||||
- X-STAINLESS-ARCH-XXX
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- X-STAINLESS-OS-XXX
|
||||
x-stainless-package-version:
|
||||
- 0.71.1
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA3SQ3UoDMRBGXyXMlcKubGOrNreiiHdC70RCTIZu2t3Jmky0a9l36jP0yWSLxT+8
|
||||
GvjOGWb4ttAGhw0osI3JDssUiJDLaTkrZSVn1VzOoQDvQEGblrqaTN9bvlmt7qYPmytif++e1+cX
|
||||
CAVw3+FoYUpmOQYxNGNgUvKJDTEUYAMxEoN63B59xs1IDkPBokbxhoZrjMKTWIR1H4RPwuYYkbjp
|
||||
RcpEvTDkxKXc727Fiem6GDa+NYxNL6Tc765Pz2B4KiBx6HREkwKBAiSnOUeCT5DwJSNZBEW5aQrI
|
||||
h7fVFjx1mTWHNVICdVlNCrDG1qhtRMM+kP5pVEce0bj/2HF3PIBdjS1G0+hZ+9f/opP6Nx0KCJm/
|
||||
R1IWkDC+eouaPUZQMJbtTHQwDB8AAAD//wMAkp8os98BAAA=
|
||||
headers:
|
||||
CF-RAY:
|
||||
- CF-RAY-XXX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 08 Dec 2025 23:16:59 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- ANTHROPIC-ORGANIZATION-ID-XXX
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-12-08T23:16:58Z'
|
||||
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:
|
||||
- '1'
|
||||
strict-transport-security:
|
||||
- STS-XXX
|
||||
x-envoy-upstream-service-time:
|
||||
- '2878'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -8,8 +8,6 @@ interactions:
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate, zstd
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
@@ -17,9 +15,11 @@ interactions:
|
||||
Content-Type:
|
||||
- application/json
|
||||
User-Agent:
|
||||
- CrewAI-CLI/1.3.0
|
||||
- X-USER-AGENT-XXX
|
||||
X-Crewai-Version:
|
||||
- 1.3.0
|
||||
accept-encoding:
|
||||
- ACCEPT-ENCODING-XXX
|
||||
method: POST
|
||||
uri: https://app.crewai.com/crewai_plus/api/v1/tracing/batches
|
||||
response:
|
||||
@@ -37,61 +37,31 @@ interactions:
|
||||
cache-control:
|
||||
- no-store
|
||||
content-security-policy:
|
||||
- 'default-src ''self'' *.app.crewai.com app.crewai.com; script-src ''self''
|
||||
''unsafe-inline'' *.app.crewai.com app.crewai.com https://cdn.jsdelivr.net/npm/apexcharts
|
||||
https://www.gstatic.com https://run.pstmn.io https://apis.google.com https://apis.google.com/js/api.js
|
||||
https://accounts.google.com https://accounts.google.com/gsi/client https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css.map
|
||||
https://*.google.com https://docs.google.com https://slides.google.com https://js.hs-scripts.com
|
||||
https://js.sentry-cdn.com https://browser.sentry-cdn.com https://www.googletagmanager.com
|
||||
https://js-na1.hs-scripts.com https://js.hubspot.com http://js-na1.hs-scripts.com
|
||||
https://bat.bing.com https://cdn.amplitude.com https://cdn.segment.com https://d1d3n03t5zntha.cloudfront.net/
|
||||
https://descriptusercontent.com https://edge.fullstory.com https://googleads.g.doubleclick.net
|
||||
https://js.hs-analytics.net https://js.hs-banner.com https://js.hsadspixel.net
|
||||
https://js.hscollectedforms.net https://js.usemessages.com https://snap.licdn.com
|
||||
https://static.cloudflareinsights.com https://static.reo.dev https://www.google-analytics.com
|
||||
https://share.descript.com/; style-src ''self'' ''unsafe-inline'' *.app.crewai.com
|
||||
app.crewai.com https://cdn.jsdelivr.net/npm/apexcharts; img-src ''self'' data:
|
||||
*.app.crewai.com app.crewai.com https://zeus.tools.crewai.com https://dashboard.tools.crewai.com
|
||||
https://cdn.jsdelivr.net https://forms.hsforms.com https://track.hubspot.com
|
||||
https://px.ads.linkedin.com https://px4.ads.linkedin.com https://www.google.com
|
||||
https://www.google.com.br; font-src ''self'' data: *.app.crewai.com app.crewai.com;
|
||||
connect-src ''self'' *.app.crewai.com app.crewai.com https://zeus.tools.crewai.com
|
||||
https://connect.useparagon.com/ https://zeus.useparagon.com/* https://*.useparagon.com/*
|
||||
https://run.pstmn.io https://connect.tools.crewai.com/ https://*.sentry.io
|
||||
https://www.google-analytics.com https://edge.fullstory.com https://rs.fullstory.com
|
||||
https://api.hubspot.com https://forms.hscollectedforms.net https://api.hubapi.com
|
||||
https://px.ads.linkedin.com https://px4.ads.linkedin.com https://google.com/pagead/form-data/16713662509
|
||||
https://google.com/ccm/form-data/16713662509 https://www.google.com/ccm/collect
|
||||
https://worker-actionkit.tools.crewai.com https://api.reo.dev; frame-src ''self''
|
||||
*.app.crewai.com app.crewai.com https://connect.useparagon.com/ https://zeus.tools.crewai.com
|
||||
https://zeus.useparagon.com/* https://connect.tools.crewai.com/ https://docs.google.com
|
||||
https://drive.google.com https://slides.google.com https://accounts.google.com
|
||||
https://*.google.com https://app.hubspot.com/ https://td.doubleclick.net https://www.googletagmanager.com/
|
||||
https://www.youtube.com https://share.descript.com'
|
||||
- CSP-FILTERED
|
||||
expires:
|
||||
- '0'
|
||||
permissions-policy:
|
||||
- camera=(), microphone=(self), geolocation=()
|
||||
- PERMISSIONS-POLICY-XXX
|
||||
pragma:
|
||||
- no-cache
|
||||
referrer-policy:
|
||||
- strict-origin-when-cross-origin
|
||||
- REFERRER-POLICY-XXX
|
||||
strict-transport-security:
|
||||
- max-age=63072000; includeSubDomains
|
||||
- STS-XXX
|
||||
vary:
|
||||
- Accept
|
||||
x-content-type-options:
|
||||
- nosniff
|
||||
- X-CONTENT-TYPE-XXX
|
||||
x-frame-options:
|
||||
- SAMEORIGIN
|
||||
- X-FRAME-OPTIONS-XXX
|
||||
x-permitted-cross-domain-policies:
|
||||
- none
|
||||
- X-PERMITTED-XXX
|
||||
x-request-id:
|
||||
- 4124c4ce-02cf-4d08-9b0b-8983c2e9da6e
|
||||
- X-REQUEST-ID-XXX
|
||||
x-runtime:
|
||||
- '0.073764'
|
||||
- X-RUNTIME-XXX
|
||||
x-xss-protection:
|
||||
- 1; mode=block
|
||||
- X-XSS-PROTECTION-XXX
|
||||
status:
|
||||
code: 401
|
||||
message: Unauthorized
|
||||
@@ -99,10 +69,12 @@ interactions:
|
||||
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Say hello in one
|
||||
word"}],"model":"claude-3-5-haiku-20241022","stop_sequences":["\nObservation:","\nThought:"],"stream":false}'
|
||||
headers:
|
||||
User-Agent:
|
||||
- X-USER-AGENT-XXX
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate, zstd
|
||||
- ACCEPT-ENCODING-XXX
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
@@ -113,16 +85,14 @@ interactions:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- Anthropic/Python 0.71.0
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
- X-STAINLESS-ARCH-XXX
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
- X-STAINLESS-OS-XXX
|
||||
x-stainless-package-version:
|
||||
- 0.71.0
|
||||
x-stainless-retry-count:
|
||||
@@ -145,7 +115,7 @@ interactions:
|
||||
0ab7TSeBWPh7tBbIlF6dIcWOEiTmoqxOFtP0AQAA//8DAM5WvkqaAQAA
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 99a939a5a931556e-EWR
|
||||
- CF-RAY-XXX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
@@ -161,19 +131,19 @@ interactions:
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- SCRUBBED-ORG-ID
|
||||
- ANTHROPIC-ORGANIZATION-ID-XXX
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- '400000'
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- '400000'
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- '2025-11-07T01:58:22Z'
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- '80000'
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- '80000'
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- '2025-11-07T01:58:22Z'
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '4000'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
@@ -181,22 +151,128 @@ interactions:
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-11-07T01:58:22Z'
|
||||
anthropic-ratelimit-tokens-limit:
|
||||
- '480000'
|
||||
- ANTHROPIC-RATELIMIT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-tokens-remaining:
|
||||
- '480000'
|
||||
- ANTHROPIC-RATELIMIT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-tokens-reset:
|
||||
- '2025-11-07T01:58:22Z'
|
||||
- ANTHROPIC-RATELIMIT-TOKENS-RESET-XXX
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
request-id:
|
||||
- req_011CUshbL7CEVoner91hUvxL
|
||||
- REQUEST-ID-XXX
|
||||
retry-after:
|
||||
- '41'
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
- STS-XXX
|
||||
x-envoy-upstream-service-time:
|
||||
- '390'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"Say hello in one
|
||||
word"}],"model":"claude-3-5-haiku-20241022","stop_sequences":["\nObservation:","\nThought:"],"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:
|
||||
- '182'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
x-api-key:
|
||||
- X-API-KEY-XXX
|
||||
x-stainless-arch:
|
||||
- X-STAINLESS-ARCH-XXX
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- X-STAINLESS-OS-XXX
|
||||
x-stainless-package-version:
|
||||
- 0.71.1
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA3SQ3UrEMBCFn8VznUJb7SJ5gr2UvRCsSAjJ7Da2TbrJRFxK3126WPzDq4HzfTMD
|
||||
Z8YYLA2QMIPOlorboik67fpc1GV9V5V1DQFnITGmkyqr+9Qe7e78+HRpjw87v3ev7aHqIcCXiVaL
|
||||
UtIngkAMwxrolFxi7RkCJngmz5DP8+Yzva/kOiT27gbLi0DiMKlIOgUPCfJWcY4enyDROZM3BOnz
|
||||
MAjk60c5w/kps+LQk0+QVS1gtOlImUiaXfDqp1BuPJK2/7Ftd71PU0cjRT2oZvzrf9Gq+00XgZD5
|
||||
e9QIJIpvzpBiRxESa0tWR4tl+QAAAP//AwD8cXPFlwEAAA==
|
||||
headers:
|
||||
CF-RAY:
|
||||
- CF-RAY-XXX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 08 Dec 2025 23:16:53 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- ANTHROPIC-ORGANIZATION-ID-XXX
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-12-08T23:16:53Z'
|
||||
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:
|
||||
- '8'
|
||||
strict-transport-security:
|
||||
- STS-XXX
|
||||
x-envoy-upstream-service-time:
|
||||
- '787'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"max_tokens":10000,"messages":[{"role":"user","content":"What is the weather
|
||||
in Tokyo?"}],"model":"claude-sonnet-4-5","stream":false,"thinking":{"type":"enabled","budget_tokens":5000}}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- ACCEPT-ENCODING-XXX
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '185'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- X-USER-AGENT-XXX
|
||||
x-stainless-arch:
|
||||
- X-STAINLESS-ARCH-XXX
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- X-STAINLESS-OS-XXX
|
||||
x-stainless-package-version:
|
||||
- 0.71.1
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAAwAAAP//hFVrj+o4Ev0rVr7s7O00JAGahzRa0bxC84YGGrZXLeMUiYljB9tJCFf9
|
||||
31fhNnNnZmd3PyWqOnXqJZ/6bkTCA2a0DMJw4sGjEpyDfqw+1h4dy6lZTadpmAb1jJYRKf/Dsgfg
|
||||
Vdv9ST1+al/t3kvWSeIXf2qYhs5jKFCgFPbBMA0pWGHASlGlMdeGaRDBNXBttP75/Y7XAeUh5X7B
|
||||
cP9tGa8BoESBRFQhrAojwgeRaKQDQCSRErhGGWAdFBiOXkWYixJyRQYpSBMNkSf43zQKcAoIEwJK
|
||||
IS2QBMweNY0AUX4UMsKaCm4iyglLvCLJn6k9rHEJTXIUcpEx8HxAGVaIYaVREntYg1ekb8eSMuRY
|
||||
TtVEmHtoiAjmXGh0kCJTcKuacg2Sg0ZC3itiNIXfUimQKSWgSu/8nQ+RCkTCPMTgR8+3YRRFIB1g
|
||||
/TNBLEVKvb+ayW/93SpSie+D0ii4MUCOyI3+SLmHdEDVHwJ0AJECloIqGaahqM+xTmSxrZ5s9zrh
|
||||
btgJ/M4obC8ZsU8T3o93TetY8/pVt3fci+XbzOVVq532q7bUM5aH9u706kAY1li2GuW1jnjDy3CK
|
||||
K/tDm4t0Mn1acPs68OIHPK5cen4+rV+kNbPPIc9pb9cUuDs9QJj3Hfck/dpuPit3htmRLy13OdqP
|
||||
uwoLCINtvb0YP7+yZXm1cYUgzqT66k4vR/fkjLuV5/LTotv3H5y8F6mK9ZIHo5h0iTv39+csFbLh
|
||||
KuY4ad1K7PVll6rRbtWojuPJaMP5sgJil8p501KOb9sg8kN3zsrTNVUTubuU49W41h7U6udhuuzt
|
||||
JmR+rcrKJhpEvaeH/np2PU8228VyF70t7CteXb1pLGu9cfttvhjMppVKN58fZjpq5OdrZp+sN+vc
|
||||
S7flfjbw1dSqNoP9au/t1Xw8TC+Lq+1tGxWyGdU5cdsv17W7SSOezfx9vm12t1XyvI8lX0+qtex6
|
||||
mSWxPM5ZNdo48m3aPETNbcweqoNyeA12+DDrdSZzq45P9ejhnK7eukPhAJvMJ+58dGls6KWfDUG/
|
||||
dJyUOits6/6s6VcuwyEf6u3zYr3PdTaLyy6ez8rts3jbdkV7WXE3Z3/uhlfRC+gwTrJsu5tdgvoq
|
||||
0Lt1J6Zrfap0r76V9222kN6ETp96h9eVHciTnZEsV/vJ0KLrRKqkPH1ggZOchnI/G0yvEmqBOK3W
|
||||
y12WEG8wEAv9/FQDl0+U7ngz1wl0I2o07Oilweq6606PnK27dqZk+OqoZtOz+4faQZ7K+YWOus2X
|
||||
ALrj8kUNO711KJ6S7KE6AE0vp8bJy3pqVyV4I3btxa+/Gp/mT7WCS6Fjt0/L+L8q8xevsYReBfLh
|
||||
fyuZiXKR/HiirUIO7BL69m0FWJIACc4oh2/fWmgghM8AvRu3mDvJu4GOQiIaReBRrAFJUAnT6p07
|
||||
Bcv2K1UGB0U1qDKOY1WwdQIg4Z2kRERkojYhyRfeLGTrHrvmHkhfioR777xSsI4FwQwpkUgCN7ZC
|
||||
wF9wjDmagAYhBRM+LTBtHzjJ0S+nCJd8UTrFf79rmELieKSEYlY0AASrouh3PlTFrCQgzPPiRPgI
|
||||
mIKve/Cj9ZscogBYfBtcRnVgIpWQAGGFfOAgMUOE0aiYx++VTkiUFXp6X4AWCC4xEI28RBapPHo8
|
||||
wm1HCrASXP3D+PyXaSgt4g95sxgtA7j3oRPJjS+HgnMCnIDR4gljppHcLmLru0F5nOgPLULgymhV
|
||||
K6ZBMAngg0i41fPxR4B190vA3n/z3WMLfogDiIpmP2rRf+J/eu3gz95P0xCJ/r3JbjZN4+sofWgK
|
||||
0mgZxR33sPSMz89/AwAA//8DAHYWWLc6CAAA
|
||||
headers:
|
||||
CF-RAY:
|
||||
- CF-RAY-XXX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 08 Dec 2025 23:16:46 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- ANTHROPIC-ORGANIZATION-ID-XXX
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-12-08T23:16:42Z'
|
||||
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:
|
||||
- '18'
|
||||
strict-transport-security:
|
||||
- STS-XXX
|
||||
x-envoy-upstream-service-time:
|
||||
- '5323'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -0,0 +1,223 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"max_tokens":10000,"messages":[{"role":"user","content":"What is 2+2?"}],"model":"claude-sonnet-4-5","stream":false,"thinking":{"type":"enabled","budget_tokens":5000}}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- ACCEPT-ENCODING-XXX
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '168'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- X-USER-AGENT-XXX
|
||||
x-stainless-arch:
|
||||
- X-STAINLESS-ARCH-XXX
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- X-STAINLESS-OS-XXX
|
||||
x-stainless-package-version:
|
||||
- 0.71.1
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAAwAAAP//dJLdb6JAFMX/FXJfxRYRaiXpgyBWRUWL1W03GzKFW5gCMzoz+NHG/31j
|
||||
s6b7kX26N/d37nk55wMqnmIJDiQlqVNsSs4YqqbVtJumYdpG1+yCDjQFByqZxUbLfrrnbbbmviff
|
||||
CkymnYQVaw90UMcNnlUoJckQdBC8PB+IlFQqwhTokHCmkClwvn9c9CqnrKAsOztcVgeWOZUalRrR
|
||||
JK02JWpEUJVXqGiibWuUinJ2pZkNU8NtTUqpWVegg6QZI6oWZ19fSdcrnkZennlB0ZuJ0MLOIjy6
|
||||
qvHNvB08B5Pd8n3GF/1VtFxNh24/DFTKDGNxrKXqNKrAnRxfa9MO5tNxa3egHd9dmWxNl3u339tG
|
||||
9iiaR362t7j0/OzAR8FBDSzik/7sbbBqlf25mppe+3kYRaN9+PDipTvSLY1FL+nMn94X7nZ/W6yv
|
||||
3f6Lz/aLyEvUMN+LxwVVue8+d6zVhJuV1XhI6oEf2kExOzbE22sg0+MAxxNx2/W4Ox6HlXcUUk4H
|
||||
vcZ4yPq9Sfry3l0ak32xnOQh3gyvw0Pa8zPf9GxXLML8cOD123o93QwiI9i6nYA/3vf8OzjpX3ng
|
||||
4ZzU53DA1Bqaqd1pFpx+6CAV38QCieQMHECWxqoWDH4BidsaWYLgsLosdag/e+B8AGWbWsWKF8gk
|
||||
OFZbh4QkOcaJQHIOMv5TYFy4QJL+j11+z/64ybFCQcrYrv7Vf9FW/jc96cBr9fupfaODRLGjCcaK
|
||||
ogAHzuVNiUjhdPoJAAD//wMAg2mrwC8DAAA=
|
||||
headers:
|
||||
CF-RAY:
|
||||
- CF-RAY-XXX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 08 Dec 2025 23:16:49 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- ANTHROPIC-ORGANIZATION-ID-XXX
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- ANTHROPIC-RATELIMIT-INPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-LIMIT-XXX
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-REMAINING-XXX
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- ANTHROPIC-RATELIMIT-OUTPUT-TOKENS-RESET-XXX
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-12-08T23:16:48Z'
|
||||
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:
|
||||
- '12'
|
||||
strict-transport-security:
|
||||
- STS-XXX
|
||||
x-envoy-upstream-service-time:
|
||||
- '2856'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: '{"max_tokens":10000,"messages":[{"role":"user","content":"What is 2+2?"},{"role":"assistant","content":[{"type":"thinking","thinking":"This
|
||||
is a simple arithmetic question. 2+2 equals 4.","signature":"EtsBCkYIChgCKkANrO4e7QOyBt+X28FZKLvTzNoQDVSTVMHBDOKtdn00Qyust7+mKBLyfu25KPMJ1vxi7EBV2nWiTwBDAqS5ISPSEgw4osCEgxoIKxtF4aEaDNjFV1lDPtM2C3ZHSSIwORbCdva9l0QAc7PYzQBqw8kW/BDbEnwQSCctHhwrUQithEBZ74VLo2m4+RcuFEO5KkNy+rjfKsdyFeJLr89CoBJJOmCyrssMFA+JHnDALdbz9T0LwkTLhOe6H/OxdAEgE2C5BrQOhxxoujWWMpFS0KqB7KoUGAE="},{"type":"text","text":"2
|
||||
+ 2 = 4"}]},{"role":"user","content":"Now what is 3+3?"}],"model":"claude-sonnet-4-5","stream":false,"thinking":{"type":"enabled","budget_tokens":5000}}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- ACCEPT-ENCODING-XXX
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '681'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- X-USER-AGENT-XXX
|
||||
x-stainless-arch:
|
||||
- X-STAINLESS-ARCH-XXX
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- X-STAINLESS-OS-XXX
|
||||
x-stainless-package-version:
|
||||
- 0.71.1
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAAwAAAP//dJNbb6M6FIX/CvJraHMloUjnIQ3kMmlC0twgp0eRC65xDDbxBWiq/PcR
|
||||
1enMnDOaJ2+vb+0tS3v5A2Q8RilwQJRCHaM7yRlD6q53Z911Wh2r9dB5ACYgMXBAJvGp1W7bBTnn
|
||||
4TYQx7au1CoYL577Z2AC9Z6j2oWkhBgBEwie1gKUkkgFmQImiDhTiCng/P3x5VcJYZQwXE/4Kh2w
|
||||
TZChJRIGkQaUtWhkyFDciGAa6RQqZHSNhtG9f2Ev7LMy/jL69WWbEPnZZUglIMGJeuOihCI2oCAq
|
||||
yZAikXHRSCrC2T0wgSSYQaVF/RiPl6MRDWejBI/m9HFdFAPfb0yOdNmerfc9Ee6myaaa+ZDCp7Et
|
||||
bD9/L9tRZ5i6h1Ased8uWb7GXFTBDodb9O73vP3+mDM3X1yJUmz62qcevo4vawpVY0Xd89i1OYau
|
||||
HwyHVdWa0zXlj15ejWbl7Im/40vTf+Zv8/BirXfNRXXsjTw6ecKKe24yvdi+aqy+Na1goi2LQuEd
|
||||
usXy29YuxoQ8zNnzfBc2r738cPQyP2FMb9rhBq0C5R47MztIBslGXadYD9iqd5i/Tjaj4fUabPYB
|
||||
brx2znKnhVxG8nieoIjuznNKS68bHIdnSp8a7fWbJmG5aJ6FG8aTbnYY0NLdqsmisdTTnPD+Opk9
|
||||
uOW+wj2sg2ZYbK3eqhjIhb3NCrfCj+Bm/gwBqup4fB4O+LFPcPvHBFLx/CQQlJwBByAWn5QWDPwL
|
||||
JLpoxCIEHKbT1AT6M3zOByAs1+qkOEVMAqc/MEEEowSdIoFgvfrTfw2tLy4QjP/Evnrr+ShPUIYE
|
||||
TE9W9rv/J20n/6c3E3CtfpWsrgkkEgWJ0EkRJIAD6h8TQxGD2+07AAAA//8DADmgnx6kAwAA
|
||||
headers:
|
||||
CF-RAY:
|
||||
- CF-RAY-XXX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 08 Dec 2025 23:16: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-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-12-08T23:16:51Z'
|
||||
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:
|
||||
- '2431'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
219
lib/crewai/tests/cassettes/test_anthropic_function_calling.yaml
Normal file
219
lib/crewai/tests/cassettes/test_anthropic_function_calling.yaml
Normal file
@@ -0,0 +1,219 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"max_tokens":4096,"messages":[{"role":"user","content":"What is the weather
|
||||
in Tokyo? Use the get_weather tool."}],"model":"claude-sonnet-4-5","stream":false,"tools":[{"name":"get_weather","description":"Get
|
||||
the current weather in a given location","input_schema":{"type":"object","properties":{"location":{"type":"string","description":"The
|
||||
city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"],"description":"The
|
||||
unit of temperature"}},"required":["location"]}}]}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate, zstd
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '509'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- Anthropic/Python 0.71.0
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 0.71.0
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA3SQzU7DMBCE32XPjpQEUqhviCKkcmn5qVQhZBlnSaI6drDXlDbKuyMHFQqI4843
|
||||
s6PdHlpbogYOSstQYuKtMUjJaVIkeZoX6TSfAoOmBA6tr0SaPSwXLrt7uZ6vFup9ttpfLCd0WwED
|
||||
2nUYXei9rBAYOKujIL1vPElDwEBZQ2gI+GN/8JO1WgSPh5Y4B5FmV/a52p5Xs9nkBqv1fJ81u/Xl
|
||||
GTAwso25CklsUVKNLkZNFwh4D9oqSY01wOHebnYWhuGJgSfbCYfSj+CocgQeXwMahcBN0JpBGA/g
|
||||
/edWQXaDxgOf5CkDJVWNQjkcW8RPxxd3KMv/2CEbC7CrsUUntSjav/5vmtW/6cDABjqWihMGHt1b
|
||||
o1BQgw44xLeX0pUwDB8AAAD//wMA6heqv+kBAAA=
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 9a4c0d75ba3d6800-SJC
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Wed, 26 Nov 2025 20:14:34 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- 32982f3d-354e-4063-a1d9-6e3e0361bcfe
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- '2025-11-26T20:14:33Z'
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- '2025-11-26T20:14:34Z'
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-11-26T20:14:32Z'
|
||||
anthropic-ratelimit-tokens-limit:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-remaining:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-reset:
|
||||
- '2025-11-26T20:14:33Z'
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
request-id:
|
||||
- req_011CVX7YqtSMhTjqLnjZvaj1
|
||||
retry-after:
|
||||
- '28'
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
x-envoy-upstream-service-time:
|
||||
- '2874'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: "{\"max_tokens\":4096,\"messages\":[{\"role\":\"user\",\"content\":\"What
|
||||
is the weather in Tokyo? Use the get_weather tool.\"},{\"role\":\"assistant\",\"content\":[{\"type\":\"tool_use\",\"id\":\"toolu_01Eobgw8gDD6KegYJz1iyYC7\",\"name\":\"get_weather\",\"input\":{\"location\":\"Tokyo\"}}]},{\"role\":\"user\",\"content\":[{\"type\":\"tool_result\",\"tool_use_id\":\"toolu_01Eobgw8gDD6KegYJz1iyYC7\",\"content\":\"The
|
||||
weather in Tokyo is sunny and 72\xB0F\"}]}],\"model\":\"claude-sonnet-4-5\",\"stream\":false,\"tools\":[{\"name\":\"get_weather\",\"description\":\"Get
|
||||
the current weather in a given location\",\"input_schema\":{\"type\":\"object\",\"properties\":{\"location\":{\"type\":\"string\",\"description\":\"The
|
||||
city and state, e.g. San Francisco, CA\"},\"unit\":{\"type\":\"string\",\"enum\":[\"celsius\",\"fahrenheit\"],\"description\":\"The
|
||||
unit of temperature\"}},\"required\":[\"location\"]}}]}"
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate, zstd
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '800'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- Anthropic/Python 0.71.0
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 0.71.0
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA3SQTWrDMBBGryJm1YJcHNE0RMsGktLu2mxKKUZYQ6zGHjnSqIkJvlPOkJMVh4b+
|
||||
0dXA994ww7eHxlusQUNZm2Qxi54IObvOxpnK1TifqilIcBY0NHFV5KO5fWsebv32WW0XT/d3oxnu
|
||||
HhcbkMBdi4OFMZoVgoTg6yEwMbrIhhgklJ4YiUG/7M8+424gp6FhWaHYouEKg3Akln7deeGiKFMI
|
||||
SFx3IiaiThiyYqKOh7m4MG0b/M41hrHuhFLHw+zyCvpXCZF9WwQ00RNoQLIFp0DwCSJuElKJoCnV
|
||||
tYR0elvvwVGbuGC/Roqgb6YTCaUpKyzKgIadp+KnkZ95QGP/Y+fd4QC2FTYYTF2Mm7/+Fx1Vv2kv
|
||||
wSf+HiklIWJ4dyUW7DCAhqFsa4KFvv8AAAD//wMANWIHid8BAAA=
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 9a4c0d886f9e6800-SJC
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Wed, 26 Nov 2025 20:14:36 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- 32982f3d-354e-4063-a1d9-6e3e0361bcfe
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- '2025-11-26T20:14:36Z'
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- '2025-11-26T20:14:36Z'
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-11-26T20:14:35Z'
|
||||
anthropic-ratelimit-tokens-limit:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-remaining:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-reset:
|
||||
- '2025-11-26T20:14:36Z'
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
request-id:
|
||||
- req_011CVX7Z4is92Sz8oA63UNxC
|
||||
retry-after:
|
||||
- '26'
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
x-envoy-upstream-service-time:
|
||||
- '2240'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
122
lib/crewai/tests/cassettes/test_anthropic_thinking.yaml
Normal file
122
lib/crewai/tests/cassettes/test_anthropic_thinking.yaml
Normal file
@@ -0,0 +1,122 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"max_tokens":10000,"messages":[{"role":"user","content":"What is the weather
|
||||
in Tokyo?"}],"model":"claude-sonnet-4-5","stream":false,"thinking":{"type":"enabled","budget_tokens":5000}}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '185'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- Anthropic/Python 0.75.0
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 0.75.0
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAAwAAAP//hJNdr6o4GIX/SsPNXIjbD/xAk3OhiIiyZasI4uxkUmkFBFpsy4f75Pz3
|
||||
CU72PjOTyZyrNm/WWu9K0+e7lFGEU2kqBSksEG5zSggW7UF72O53+8PupD+RZClG0lTKePhHtzeo
|
||||
vMQjm621jXbB3apfy6MTbyRZEo8cNyrMOQyxJEuMps0Ach5zAYmQZCmgRGAipOnv3z/1IopJEpOw
|
||||
Sfi8TiUnwqDgmIGYA8ibIcgwgBdaCCAiDIKCMUwEqDAUUSMjwKHJg76AFa1wiZkMTIAo+U2ACJYY
|
||||
wCDAnANBAcMwbYs4wyAmV8oyKGJKZBCTIC1Qs+ff0QElKG5E/AWYgEe0SBFI8bNHBhJCKyAiKIAJ
|
||||
AtjsyxktY/RfFb/WAUgQ4EUYYi5A9AzADxA8k68xQUBEMf+74UWSJR6HBIqCNY+ms2ShJb6pRaG2
|
||||
SRYxKo4IGeFJ88ywQ4ptYvST/ai6kfRUWkZy7GgByjU9+ugeNMtZwbi/qm19TY38SJR0LLbWSHGx
|
||||
07MyVd3ODVsYt4Uefhw42u+9QutPWpfwEnG4WIR6vP6YxC70t7hUiWZWSydeP4I7bUX9JOrtkJJk
|
||||
W9VLbgfDHSmm+qhIoYxXd7O3UtTOCfOQ3CLYJYwNB2dFW/Y295nG3BmZ7V6z1ezijBkcdWsbovTi
|
||||
ozl8qOb6TrpZy7xdnVw7l4OROuK0YMVB25da2FuuD+Ftm26LnZLYnRPOjGprCe1YuaWXtd7Ouj9z
|
||||
W/PCNy3DCvhmtwwYsxfeil6KfWtvJZdKqz+83B7ekxQRmrVUdDesszLcLOqxPTg583l/fbtk+n2j
|
||||
L2Z1NkrXTgdmV66og+H89Co67jLprVl5K7eHFJdmHYyx0XH7kbtfDpA6r52ra9rzYbgx/OH4auuW
|
||||
r78Nc3j3rkd/sIJqy1F07VR4F19bmG8t1PU8pYv2+0FL7O4DrF1VcVQ1Ha3z0l5lll/Dw80IcN7P
|
||||
B8GEr6+FueP2Yuzl+s7P6t79sRlN5gGH/Gzs3XNkcMUux841JxVx+ditJxd2sm5vNTyIdc4mxGDG
|
||||
TP8m/ZB/QonrBtfnMZV+SdLnF0dQQBlw+sWCwGkKHrT4BbPv5J04FIRY/C81V8r+csjPzCcv03fS
|
||||
BlqEg+TLUuELjwXmII2Tr24vAc3kpnzxjwFlX4KQlk3WAUMWROBPusqlJYIYCMJ/JfRJYVhcHwhz
|
||||
EY8KHvW0EppMMZM104l5KIvMf5fMOD7xmq86VXSgsqPZaaU7qnFZDiotHNJbQR24T1D8ac4hKC81
|
||||
X1Rh8IvkwSa79NYtBxZ1hwwfvfO9NezUdQ8xhzW3OtqPvOn9Zh+O62JuUp2MqO61IXsFl9YuXELO
|
||||
61YDXJgX82rzcEXTY0Mp+6AjOHmhliCdziUKfYCE5wIxoFaKcw2VubjbN7ISStbZP0EStednDRk2
|
||||
A7SJmF9C/xScrDyCu//YOlvvRxgwIrLTF+Nf/RfdDr/p1JAv+fvR9vK0oYT4Yg10tojUUv1uOo4d
|
||||
TdM7AAAA//8DANemNnfhBgAA
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 9a4b033548b28ea2-SJC
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Wed, 26 Nov 2025 17:12:50 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- 32982f3d-354e-4063-a1d9-6e3e0361bcfe
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- '2025-11-26T17:12:47Z'
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- '2025-11-26T17:12:51Z'
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-11-26T17:12:46Z'
|
||||
anthropic-ratelimit-tokens-limit:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-remaining:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-reset:
|
||||
- '2025-11-26T17:12:47Z'
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
request-id:
|
||||
- req_011CVWsgwRugLxGNv45mLXEL
|
||||
retry-after:
|
||||
- '13'
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
x-envoy-upstream-service-time:
|
||||
- '4553'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -0,0 +1,222 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '{"max_tokens":10000,"messages":[{"role":"user","content":"What is 2+2?"}],"model":"claude-sonnet-4-5","stream":false,"thinking":{"type":"enabled","budget_tokens":5000}}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate, zstd
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '168'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- Anthropic/Python 0.71.0
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 0.71.0
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAAwAAAP//dJJbj6JAEIX/CqlXcBYRvJDMg3hXcJzVZS6bDelAIS1NI3SjMhP/+4bJ
|
||||
mtlL9qkq9Z06L+e8Q5ZHyMCGkJEqwpbIOUfZMltWy9ANSx8YA9CARmBDJvaB3u4f1kXqmPlrvvR4
|
||||
bJXhjPgHAhrI+oiNCoUgewQNypw1ByIEFZJwCRqEOZfIJdjf3296mVCeUr5vHG6rDbuECoUKhSiC
|
||||
ZkeGCimpTDKUNFSKCoWkOb9TDNVQsKgIE4p5BxoIuudEVmXjO5HCGaUvi1GyH63S4bp8MLH3+FA7
|
||||
Un02+tPXlXvava3zx7G/3fne3Bk/rGTEdf2xroTsqdnKceu4MqzVxlu2Txfamzi+wZ/o7uyMh8XW
|
||||
Wmw328n+re7HQ8PR1fPQWnS445HxzBlZbvW6e/Gn5y9fu2W9OO85O0cTGlvr5dOa0faCvYzbh03/
|
||||
sLSQMevLud1zlt8G7i5Vaxx1J3PuRjKLfS9i4bQbs1W6nsre2J+5SVTIPHGeLxezyJz+YrU69rzB
|
||||
UFW9tt6J5Xanmt5hM68HmPiX43qiP81JTsL5crjR3W6x8NLTQZI4RDyQlI3dDpkNJ/dw1T7zwEuT
|
||||
1MewwVBUxVDuFROuPzQQMj8GJRKRc7ABeRTIquTwCwgsKuQhgs0rxjSoPnpgvwPlx0oGMk+RC7DN
|
||||
jgYhCRMMwhJJE2Twp0C/8RJJ9D92+2388ZhghiVhgZX9q/+k7eRvetUgr+Tvp05XA4HliYYYSIol
|
||||
2NCUNyJlBNfrTwAAAP//AwD5LVCFLwMAAA==
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 9a4bfbbe0e3b26b0-SJC
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Wed, 26 Nov 2025 20:02:28 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- 32982f3d-354e-4063-a1d9-6e3e0361bcfe
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- '2025-11-26T20:02:28Z'
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- '2025-11-26T20:02:28Z'
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-11-26T20:02:26Z'
|
||||
anthropic-ratelimit-tokens-limit:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-remaining:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-reset:
|
||||
- '2025-11-26T20:02:28Z'
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
request-id:
|
||||
- req_011CVX6dM9aWdpYdmnHARrXh
|
||||
retry-after:
|
||||
- '35'
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
x-envoy-upstream-service-time:
|
||||
- '2775'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: '{"max_tokens":10000,"messages":[{"role":"user","content":"What is 2+2?"},{"role":"assistant","content":[{"type":"thinking","thinking":"This
|
||||
is a simple arithmetic question. 2+2 equals 4.","signature":"EtsBCkYIChgCKkANrO4e7QOyBt+X28FZKLvTzNoQDVSTVMHBDOKtdn00Qyust7+mKBLyfu25KPMJ1vxi7EBV2nWiTwBDAqS5ISPSEgzy8fA2B0+wA5I3nBMaDGBC5LuZTYVFw/R6ryIwgnlwdEif5NJWNli1IlYD1jP8jJ5ell5/w17BJU9LTk+yeC6EHnLdtmfVMdlcF6flKkNFt7DVGLhdqtohBXxx4qmB8IKKp7M9A++M103ftST+4MjPHy9ehVxpNE0WHaoacHJAP0L6qIMkvjtafceejaklDL3aGAE="},{"type":"text","text":"2
|
||||
+ 2 = 4"}]},{"role":"user","content":"Now what is 3+3?"}],"model":"claude-sonnet-4-5","stream":false,"thinking":{"type":"enabled","budget_tokens":5000}}'
|
||||
headers:
|
||||
accept:
|
||||
- application/json
|
||||
accept-encoding:
|
||||
- gzip, deflate, zstd
|
||||
anthropic-version:
|
||||
- '2023-06-01'
|
||||
connection:
|
||||
- keep-alive
|
||||
content-length:
|
||||
- '681'
|
||||
content-type:
|
||||
- application/json
|
||||
host:
|
||||
- api.anthropic.com
|
||||
user-agent:
|
||||
- Anthropic/Python 0.71.0
|
||||
x-stainless-arch:
|
||||
- arm64
|
||||
x-stainless-async:
|
||||
- 'false'
|
||||
x-stainless-lang:
|
||||
- python
|
||||
x-stainless-os:
|
||||
- MacOS
|
||||
x-stainless-package-version:
|
||||
- 0.71.0
|
||||
x-stainless-retry-count:
|
||||
- '0'
|
||||
x-stainless-runtime:
|
||||
- CPython
|
||||
x-stainless-runtime-version:
|
||||
- 3.13.3
|
||||
x-stainless-timeout:
|
||||
- NOT_GIVEN
|
||||
method: POST
|
||||
uri: https://api.anthropic.com/v1/messages
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAAwAAAP//dJJbc6JAEIX/CtWvwURQUajKAyJe4jUGEd3aokYYYQQGZIYIpvzvW6TW
|
||||
zV5qn7qrv9PnoU9/QJL6OAYNvBgVPm6wlFLMG+1GpyE35U5TlVUQgfigQcICtynZg93JKmUrP676
|
||||
RqRcncXr69QCEXiV4VqFGUMBBhHyNK4HiDHCOKIcRPBSyjHloH37uOt5SGhEaFA73FsNrJAwgTAB
|
||||
CYzniAQhP6b5BeW+gHLCwwRz4gnnAjNOUvootIQHoSU8C8ojiMBIQBEv8trdLMy+Ee0mRhgY08gI
|
||||
9Y01WlOyUZFMl14fIV5J64dSyTpWheyNtLyO+PRQIUXfT9vKcdsbt9DSsQeDUElOUknG22wgq6dg
|
||||
G7wtV/tqli2cuRlc5Hn/Ye4508nQGPOu1UMDw5A27y1HovHTm9l2SjK5TJq0v8/R1hm3PX2SssQJ
|
||||
omsvvRpnc9gcGvP4YNtqudKV1L6envbtWVZZzswazgev2ctwx6ZR5G+qve33jd1ZL9F40euG0bmX
|
||||
RM1DNl322Vtw6q6k97EtKX7lqNZMduyhWarkOsbt6cqXuvEmLC7labY4X4/Julr3DnpyGnkv567p
|
||||
B3pRViPdfIab+JUOLuvcPosGv84Mt+8iMJ5mbo4RSylogKnv8iKn8BMwfC4w9TBotIhjEYrPr9A+
|
||||
gNCs4C5PI0wZaEpXBA95IXa9HKM6TfdPQfPOc4z8/7H7bu2PsxAnOEex20n+1X9RKfyb3kRIC/77
|
||||
qKWKwHD+TjzscoJz0KB+ZR/lPtxuPwAAAP//AwBO51LgPQMAAA==
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 9a4bfbd00b1426b0-SJC
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Wed, 26 Nov 2025 20:02:31 GMT
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Robots-Tag:
|
||||
- none
|
||||
anthropic-organization-id:
|
||||
- 32982f3d-354e-4063-a1d9-6e3e0361bcfe
|
||||
anthropic-ratelimit-input-tokens-limit:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-remaining:
|
||||
- '30000'
|
||||
anthropic-ratelimit-input-tokens-reset:
|
||||
- '2025-11-26T20:02:30Z'
|
||||
anthropic-ratelimit-output-tokens-limit:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-remaining:
|
||||
- '8000'
|
||||
anthropic-ratelimit-output-tokens-reset:
|
||||
- '2025-11-26T20:02:31Z'
|
||||
anthropic-ratelimit-requests-limit:
|
||||
- '50'
|
||||
anthropic-ratelimit-requests-remaining:
|
||||
- '49'
|
||||
anthropic-ratelimit-requests-reset:
|
||||
- '2025-11-26T20:02:29Z'
|
||||
anthropic-ratelimit-tokens-limit:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-remaining:
|
||||
- '38000'
|
||||
anthropic-ratelimit-tokens-reset:
|
||||
- '2025-11-26T20:02:30Z'
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
request-id:
|
||||
- req_011CVX6dZXDfHGDm98QN81RZ
|
||||
retry-after:
|
||||
- '30'
|
||||
strict-transport-security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
x-envoy-upstream-service-time:
|
||||
- '2540'
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -12,8 +12,11 @@ from crewai.task import Task
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_anthropic_api_key():
|
||||
"""Automatically mock ANTHROPIC_API_KEY for all tests in this module."""
|
||||
with patch.dict(os.environ, {"ANTHROPIC_API_KEY": "test-key"}):
|
||||
"""Automatically mock ANTHROPIC_API_KEY for all tests in this module if not already set."""
|
||||
if "ANTHROPIC_API_KEY" not in os.environ:
|
||||
with patch.dict(os.environ, {"ANTHROPIC_API_KEY": "test-key"}):
|
||||
yield
|
||||
else:
|
||||
yield
|
||||
|
||||
|
||||
@@ -63,6 +66,7 @@ def test_anthropic_tool_use_conversation_flow():
|
||||
with patch.object(completion.client.messages, 'create') as mock_create:
|
||||
# Mock initial response with tool use - need to properly mock ToolUseBlock
|
||||
mock_tool_use = Mock(spec=ToolUseBlock)
|
||||
mock_tool_use.type = "tool_use"
|
||||
mock_tool_use.id = "tool_123"
|
||||
mock_tool_use.name = "get_weather"
|
||||
mock_tool_use.input = {"location": "San Francisco"}
|
||||
@@ -75,6 +79,7 @@ def test_anthropic_tool_use_conversation_flow():
|
||||
|
||||
# Mock final response after tool result - properly mock text content
|
||||
mock_text_block = Mock()
|
||||
mock_text_block.type = "text"
|
||||
# Set the text attribute as a string, not another Mock
|
||||
mock_text_block.configure_mock(text="Based on the weather data, it's a beautiful day in San Francisco with sunny skies and 75°F temperature.")
|
||||
|
||||
@@ -698,3 +703,167 @@ def test_anthropic_stop_sequences_sent_to_api():
|
||||
assert result is not None
|
||||
assert isinstance(result, str)
|
||||
assert len(result) > 0
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization", "x-api-key"])
|
||||
def test_anthropic_thinking():
|
||||
"""Test that thinking is properly handled and thinking params are passed to messages.create"""
|
||||
from unittest.mock import patch
|
||||
from crewai.llms.providers.anthropic.completion import AnthropicCompletion
|
||||
|
||||
llm = LLM(
|
||||
model="anthropic/claude-sonnet-4-5",
|
||||
thinking={"type": "enabled", "budget_tokens": 5000},
|
||||
max_tokens=10000
|
||||
)
|
||||
|
||||
assert isinstance(llm, AnthropicCompletion)
|
||||
|
||||
original_create = llm.client.messages.create
|
||||
captured_params = {}
|
||||
|
||||
def capture_and_call(**kwargs):
|
||||
captured_params.update(kwargs)
|
||||
return original_create(**kwargs)
|
||||
|
||||
with patch.object(llm.client.messages, 'create', side_effect=capture_and_call):
|
||||
result = llm.call("What is the weather in Tokyo?")
|
||||
|
||||
assert result is not None
|
||||
assert isinstance(result, str)
|
||||
assert len(result) > 0
|
||||
|
||||
assert "thinking" in captured_params
|
||||
assert captured_params["thinking"] == {"type": "enabled", "budget_tokens": 5000}
|
||||
|
||||
assert captured_params["model"] == "claude-sonnet-4-5"
|
||||
assert captured_params["max_tokens"] == 10000
|
||||
assert "messages" in captured_params
|
||||
assert len(captured_params["messages"]) > 0
|
||||
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization", "x-api-key"])
|
||||
def test_anthropic_thinking_blocks_preserved_across_turns():
|
||||
"""Test that thinking blocks are stored and included in subsequent API calls across turns"""
|
||||
from unittest.mock import patch
|
||||
from crewai.llms.providers.anthropic.completion import AnthropicCompletion
|
||||
|
||||
llm = LLM(
|
||||
model="anthropic/claude-sonnet-4-5",
|
||||
thinking={"type": "enabled", "budget_tokens": 5000},
|
||||
max_tokens=10000
|
||||
)
|
||||
|
||||
assert isinstance(llm, AnthropicCompletion)
|
||||
|
||||
# Capture all messages.create calls to verify thinking blocks are included
|
||||
original_create = llm.client.messages.create
|
||||
captured_calls = []
|
||||
|
||||
def capture_and_call(**kwargs):
|
||||
captured_calls.append(kwargs)
|
||||
return original_create(**kwargs)
|
||||
|
||||
with patch.object(llm.client.messages, 'create', side_effect=capture_and_call):
|
||||
# First call - establishes context and generates thinking blocks
|
||||
messages = [{"role": "user", "content": "What is 2+2?"}]
|
||||
first_result = llm.call(messages)
|
||||
|
||||
# Verify first call completed
|
||||
assert first_result is not None
|
||||
assert isinstance(first_result, str)
|
||||
assert len(first_result) > 0
|
||||
|
||||
# Verify thinking blocks were stored after first response
|
||||
assert len(llm.previous_thinking_blocks) > 0, "No thinking blocks stored after first call"
|
||||
first_thinking = llm.previous_thinking_blocks[0]
|
||||
assert first_thinking["type"] == "thinking"
|
||||
assert "thinking" in first_thinking
|
||||
assert "signature" in first_thinking
|
||||
|
||||
# Store the thinking block content for comparison
|
||||
stored_thinking_content = first_thinking["thinking"]
|
||||
stored_signature = first_thinking["signature"]
|
||||
|
||||
# Second call - should include thinking blocks from first call
|
||||
messages.append({"role": "assistant", "content": first_result})
|
||||
messages.append({"role": "user", "content": "Now what is 3+3?"})
|
||||
second_result = llm.call(messages)
|
||||
|
||||
# Verify second call completed
|
||||
assert second_result is not None
|
||||
assert isinstance(second_result, str)
|
||||
|
||||
# Verify at least 2 API calls were made
|
||||
assert len(captured_calls) >= 2, f"Expected at least 2 API calls, got {len(captured_calls)}"
|
||||
|
||||
# Verify second call includes thinking blocks in assistant message
|
||||
second_call_messages = captured_calls[1]["messages"]
|
||||
|
||||
# Should have: user message + assistant message (with thinking blocks) + follow-up user message
|
||||
assert len(second_call_messages) >= 2
|
||||
|
||||
# Find the assistant message in the second call
|
||||
assistant_message = None
|
||||
for msg in second_call_messages:
|
||||
if msg["role"] == "assistant" and isinstance(msg.get("content"), list):
|
||||
assistant_message = msg
|
||||
break
|
||||
|
||||
assert assistant_message is not None, "Assistant message with list content not found in second call"
|
||||
assert isinstance(assistant_message["content"], list)
|
||||
|
||||
# Verify thinking block is included in assistant message content
|
||||
thinking_found = False
|
||||
for block in assistant_message["content"]:
|
||||
if isinstance(block, dict) and block.get("type") == "thinking":
|
||||
thinking_found = True
|
||||
assert "thinking" in block
|
||||
assert "signature" in block
|
||||
# Verify it matches what was stored from the first call
|
||||
assert block["thinking"] == stored_thinking_content
|
||||
assert block["signature"] == stored_signature
|
||||
break
|
||||
|
||||
assert thinking_found, "Thinking block not found in assistant message content in second call"
|
||||
|
||||
@pytest.mark.vcr(filter_headers=["authorization", "x-api-key"])
|
||||
def test_anthropic_function_calling():
|
||||
"""Test that function calling is properly handled"""
|
||||
llm = LLM(model="anthropic/claude-sonnet-4-5")
|
||||
|
||||
def get_weather(location: str) -> str:
|
||||
return f"The weather in {location} is sunny and 72°F"
|
||||
|
||||
tools = [
|
||||
{
|
||||
"name": "get_weather",
|
||||
"description": "Get the current weather in a given location",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "The city and state, e.g. San Francisco, CA"
|
||||
},
|
||||
"unit": {
|
||||
"type": "string",
|
||||
"enum": ["celsius", "fahrenheit"],
|
||||
"description": "The unit of temperature"
|
||||
}
|
||||
},
|
||||
"required": ["location"]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
result = llm.call(
|
||||
"What is the weather in Tokyo? Use the get_weather tool.",
|
||||
tools=tools,
|
||||
available_functions={"get_weather": get_weather}
|
||||
)
|
||||
|
||||
assert result is not None
|
||||
assert isinstance(result, str)
|
||||
assert len(result) > 0
|
||||
# Verify the response includes information about Tokyo's weather
|
||||
assert "tokyo" in result.lower() or "72" in result
|
||||
|
||||
Reference in New Issue
Block a user