以编程方式使用文档

您可以在以下位置找到有关 Anthropic 最新模型、其成本、上下文窗口和支持的输入类型的信息 Claude docs.

概述

集成详情

ClassPackageSerializableJS/TS SupportDownloadsLatest Version
ChatAnthropiclangchain-anthropicbeta(npm)<a href="https://pypi.org/project/langchain-anthropic/" target="_blank"><img src="https://static.pepy.tech/badge/langchain-anthropic/month" alt="Downloads per month" noZoom height="100" class="rounded" /></a><a href="https://pypi.org/project/langchain-anthropic/" target="_blank"><img src="https://img.shields.io/pypi/v/langchain-anthropic?style=flat-square&label=%20&color=orange" alt="PyPI - Latest version" noZoom height="100" class="rounded" /></a>

模型特性

工具调用结构化输出图像输入音频输入视频输入Token 级流式输出原生异步Token 使用量对数概率

设置

要访问 Anthropic (Claude) 模型,您需要安装 langchain-anthropic 集成包并获取 Claude API 密钥。

安装

    pip install -U langchain-anthropic
    
    uv add langchain-anthropic
    

凭证

前往 Claude 控制台 注册并生成 Claude API 密钥。完成此操作后,设置 ANTHROPIC_API_KEY 环境变量:

if "ANTHROPIC_API_KEY" not in os.environ:
    os.environ["ANTHROPIC_API_KEY"] = getpass.getpass("Enter your Anthropic API key: ")

要启用模型调用的自动追踪,请设置您的 LangSmith API 密钥:

os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
os.environ["LANGSMITH_TRACING"] = "true"

实例化

现在我们可以实例化模型对象并生成聊天补全:

from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(
    model="claude-haiku-4-5-20251001",
    # temperature=,
    # max_tokens=,
    # timeout=,
    # max_retries=,
    # ...
)

请参阅 ChatAnthropic API 参考以获取所有可用实例化参数的详细信息。

调用

调用

        messages = [
            (
                "system",
                "You are a helpful translator. Translate the user sentence to French.",
            ),
            (
                "human",
                "I love programming.",
            ),
        ]
        ai_msg = model.invoke(messages)
        
        print(ai_msg.text)
        
        J'adore la programmation.
        

流式传输

        stream = model.stream_events(messages, version="v3")
        for token in stream.text:
            print(token, end="", flush=True)
        
        J'aime la programmation.
        

要从流中聚合完整消息:

        stream = model.stream_events(messages, version="v3")
        full_message = stream.output
        
        AIMessage(content="J'aime la programmation.", id="run-b34faef0-882f-4869-a19c-ed2b856e6361")
        

Async

        ai_msg = await model.ainvoke(messages)

        # stream
        stream = await model.astream_events(messages, version="v3")
        async for token in stream.text:
            print(token, end="", flush=True)

        # batch
        await model.abatch([messages])
        
        AIMessage(
            content="J'aime la programmation.",
            response_metadata={
                "id": "msg_01Trik66aiQ9Z1higrD5XFx3",
                "model": "claude-sonnet-4-6",
                "stop_reason": "end_turn",
                "stop_sequence": None,
                "usage": {"input_tokens": 25, "output_tokens": 11},
            },
            id="run-5886ac5f-3c2e-49f5-8a44-b1e92808c929-0",
            usage_metadata={
                "input_tokens": 25,
                "output_tokens": 11,
                "total_tokens": 36,
            },
        )
        

在我们的 模型 guide.

内容块

使用工具时, 扩展思考和其他功能中,来自单个 Anthropic AIMessage 的内容可以是单个字符串或 Anthropic 内容块列表。

例如,当 Anthropic 模型调用工具时,工具调用是消息内容的一部分(同时也在标准化的 AIMessage.tool_calls):

from langchain_anthropic import ChatAnthropic
from typing_extensions import Annotated

model = ChatAnthropic(model="claude-haiku-4-5-20251001")


def get_weather(
    location: Annotated[str, ..., "Location as city and state."]
) -> str:
    """Get the weather at a location."""
    return "It's sunny."


model_with_tools = model.bind_tools([get_weather])
response = model_with_tools.invoke("Which city is hotter today: LA or NY?")
response.content
[{'text': "I'll help you compare the temperatures of Los Angeles and New York by checking their current weather. I'll retrieve the weather for both cities.",
  'type': 'text'},
 {'id': 'toolu_01CkMaXrgmsNjTso7so94RJq',
  'input': {'location': 'Los Angeles, CA'},
  'name': 'get_weather',
  'type': 'tool_use'},
 {'id': 'toolu_01SKaTBk9wHjsBTw5mrPVSQf',
  'input': {'location': 'New York, NY'},
  'name': 'get_weather',
  'type': 'tool_use'}]

使用 content_blocks 将使用 LangChain 的标准格式呈现内容,与其他模型提供商保持一致。了解更多关于 内容块.

response.content_blocks

您还可以使用以下方式以标准格式访问工具调用 tool_calls attribute:

response.tool_calls
[{'name': 'GetWeather',
  'args': {'location': 'Los Angeles, CA'},
  'id': 'toolu_01Ddzj5PkuZkrjF4tafzu54A'},
 {'name': 'GetWeather',
  'args': {'location': 'New York, NY'},
  'id': 'toolu_012kz4qHZQqD4qg8sFPeKqpP'}]

工具

Anthropic 的工具使用功能允许您定义 Claude 在对话期间可以调用的外部函数。这实现了动态信息检索、计算和与外部系统的交互。

请参阅 ChatAnthropic.bind_tools 了解如何将工具绑定到您的模型实例。

from pydantic import BaseModel, Field


class GetWeather(BaseModel):
    '''Get the current weather in a given location'''

    location: str = Field(description="The city and state, e.g. San Francisco, CA")


class GetPopulation(BaseModel):
    '''Get the current population in a given location'''

    location: str = Field(description="The city and state, e.g. San Francisco, CA")


model_with_tools = model.bind_tools([GetWeather, GetPopulation]) # [!code highlight]
ai_msg = model_with_tools.invoke("Which city is hotter today and which is bigger: LA or NY?")
ai_msg.tool_calls
[
    {
        "name": "GetWeather",
        "args": {"location": "Los Angeles, CA"},
        "id": "toolu_01KzpPEAgzura7hpBqwHbWdo",
    },
    {
        "name": "GetWeather",
        "args": {"location": "New York, NY"},
        "id": "toolu_01JtgbVGVJbiSwtZk3Uycezx",
    },
    {
        "name": "GetPopulation",
        "args": {"location": "Los Angeles, CA"},
        "id": "toolu_01429aygngesudV9nTbCKGuw",
    },
    {
        "name": "GetPopulation",
        "args": {"location": "New York, NY"},
        "id": "toolu_01JPktyd44tVMeBcPPnFSEJG",
    },
]

严格工具使用

Anthropic 支持选择性加入 工具调用的严格模式遵循。这确保通过约束解码验证工具名称和参数并正确类型化。

如果没有严格模式,Claude 偶尔会生成无效的工具输入,从而破坏您的应用程序:

  • 类型不匹配: passengers: "2" 而不是 passengers: 2
  • 缺少必需字段:省略函数预期的字段
  • 无效的枚举值:超出允许范围的值
  • 架构违规:嵌套对象不符合预期结构

严格工具使用确保符合架构的工具调用:

  • - 工具输入严格遵循您的 input_schema
  • - 保证字段类型和必需字段
  • - 消除对格式错误输入的错误处理
  • - 工具 name 使用始终来自提供的工具
使用严格工具调用使用标准工具调用
构建可靠性至关重要的代理工作流程简单的单轮工具调用
具有多个参数或嵌套对象的工具原型和实验
需要特定类型的函数(例如, int vs str)

要启用严格工具使用,请指定 strict=True 在调用 bind_tools

from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(model="claude-sonnet-4-6")

def get_weather(location: str) -> str:
    """Get the weather at a location."""
    return "It's sunny."

model_with_tools = model.bind_tools([get_weather], strict=True)  # [!code highlight]

示例:类型安全的预订系统

考虑一个预订系统,其中 passengers 必须是整数:

    from langchain_anthropic import ChatAnthropic
    from typing import Literal

    model = ChatAnthropic(model="claude-sonnet-4-6")

    def book_flight(
        destination: str,
        departure_date: str,
        passengers: int, # [!code highlight]
        cabin_class: Literal["economy", "business", "first"]
    ) -> str:
        """Book a flight to a destination.

        Args:
            destination: The destination city
            departure_date: Date in YYYY-MM-DD format
            passengers: Number of passengers (must be an integer)
            cabin_class: The cabin class for the flight
        """
        return f"Booked {passengers} passengers to {destination}"

    model_with_tools = model.bind_tools(
        [book_flight],
        strict=True, # [!code highlight]
        tool_choice="any",
    )
    response = model_with_tools.invoke("Book 2 passengers to Tokyo, business class, 2025-01-15")

    # With strict=True, passengers is guaranteed to be int, not "2" or "two"
    print(response.tool_calls[0]["args"]["passengers"])
    
    2
    

严格工具使用有一些需要注意的 JSON schema 限制。参见 Claude 文档 了解更多详情。

如果您的工具 schema 使用了不支持的功能,您将收到 400 错误。在这些情况下,请简化 schema 或使用标准(非严格)工具调用。

输入示例

对于复杂的工具,您可以提供使用示例来帮助 Claude 正确理解如何使用它们。这通过设置 input_examples 在工具的 extras parameter.

from langchain_anthropic import ChatAnthropic
from langchain.tools import tool

@tool(
    extras={ # [!code highlight]
        "input_examples": [ # [!code highlight]
            { # [!code highlight]
                "query": "weather report", # [!code highlight]
                "location": "San Francisco", # [!code highlight]
                "format": "detailed" # [!code highlight]
            }, # [!code highlight]
            { # [!code highlight]
                "query": "temperature", # [!code highlight]
                "location": "New York", # [!code highlight]
                "format": "brief" # [!code highlight]
            } # [!code highlight]
        ] # [!code highlight]
    } # [!code highlight]
)
def search_weather_data(query: str, location: str, format: str = "brief") -> str:
    """Search weather database with specific query and format preferences.

    Args:
        query: The type of weather information to retrieve
        location: City or region to search
        format: Output format, either 'brief' or 'detailed'
    """
    return f"{format.title()} {query} for {location}: Data found"

model = ChatAnthropic(model="claude-sonnet-4-6")
model_with_tools = model.bind_tools([search_weather_data])

response = model_with_tools.invoke(
    "Get me a detailed weather report for Seattle"
)

extras 参数还支持: - defer_loading (bool):按需加载工具用于 工具搜索 - cache_control (dict):启用 提示缓存 用于该工具 - eager_input_streaming (bool):启用 细粒度工具流式传输 用于该工具

细粒度工具流式传输

Anthropic 支持 细粒度工具流式传输,这可以减少使用大参数流式传输工具调用时的延迟。

细粒度流式传输不是在传输前缓冲整个参数值,而是在参数数据可用时立即发送。对于大型工具参数,这可以将初始延迟从 15 秒减少到约 3 秒。

要为应增量流式传输工具参数的工具启用细粒度工具流式传输,请设置 extras={"eager_input_streaming": True} 在工具上。该值会传递到工具定义中的 Anthropic API。

from langchain_anthropic import ChatAnthropic
from langchain.tools import tool

model = ChatAnthropic(model="claude-sonnet-4-6")

@tool(extras={"eager_input_streaming": True})
def write_document(title: str, content: str) -> str:
    """Write a document with the given title and content."""
    return f"Document '{title}' written successfully"

model_with_tools = model.bind_tools([write_document])

# Stream tool calls with reduced latency
for chunk in model_with_tools.stream(
    "Write a detailed technical document about the benefits of streaming APIs"
):
    print(chunk.content)

流式数据作为 input_json_delta 块到达 chunk.content。您可以累积这些来构建完整的工具参数:

from langchain_anthropic import ChatAnthropic
from langchain.tools import tool

model = ChatAnthropic(model="claude-sonnet-4-6")

@tool(extras={"eager_input_streaming": True})
def write_document(title: str, content: str) -> str:
    """Write a document with the given title and content."""
    return f"Document '{title}' written successfully"

model_with_tools = model.bind_tools([write_document])

accumulated_json = ""

for chunk in model_with_tools.stream("Write a document about AI"):
    for block in chunk.content:
        if isinstance(block, dict) and block.get("type") == "input_json_delta":
            accumulated_json += block.get("partial_json", "")
            try:
                # Try to parse accumulated JSON
                parsed = json.loads(accumulated_json)
                print(f"Complete args: {parsed}")
            except json.JSONDecodeError:
                # JSON is still incomplete, continue accumulating
                pass
Complete args: {'title': 'Artificial Intelligence: An Overview', 'content': '# Artificial Intelligence: An Overview...

编程式工具调用

工具可配置为可从 Claude 的 代码执行 环境中调用,减少涉及大数据处理或多工具工作流程的延迟和令牌消耗。

请参阅 Claude 的 编程式工具调用指南 了解详情。要使用此功能:

  • - 包含 代码执行 内置工具到您的工具集中
  • - 指定 extras={"allowed_callers": ["code_execution_20250825"]} 用于您希望通过编程调用的工具

请参阅下方获取完整示例 create_agent.

from langchain.agents import create_agent
from langchain.tools import tool
from langchain_anthropic import ChatAnthropic


@tool(extras={"allowed_callers": ["code_execution_20250825"]}) # [!code highlight]
def get_weather(location: str) -> str:
    """Get the weather at a location."""
    return "It's sunny."

tools = [
    {"type": "code_execution_20250825", "name": "code_execution"}, # [!code highlight]
    get_weather,
]

model = ChatAnthropic(
    model="claude-sonnet-4-6",
    reuse_last_container=True,  # [!code highlight]
)

agent = create_agent(model, tools=tools)

input_query = {
    "role": "user",
    "content": "What's the weather in Boston?",
}

result = agent.invoke({"messages": [input_query]})

多模态

Claude 支持将图像和 PDF 作为内容块输入,包括 Anthropic 的原生格式(请参阅 视觉PDF 支持)以及 LangChain 的 标准格式.

支持的输入方法

方法图像PDF
Base64 内联数据
HTTP/HTTPS URLs
Files API

图像输入

使用 HumanMessage 列表内容格式提供图像输入及文本。

    from langchain_anthropic import ChatAnthropic
    from langchain.messages import HumanMessage

    model = ChatAnthropic(model="claude-sonnet-4-6")

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Describe the image at the URL."},
            {
                "type": "image",
                "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg",
            },
        ]
    )
    response = model.invoke([message])
    
    from langchain_anthropic import ChatAnthropic
    from langchain.messages import HumanMessage

    model = ChatAnthropic(model="claude-sonnet-4-6")

    image_url = "https://picsum.photos/id/237/200/300"
    image_data = base64.b64encode(httpx.get(image_url, follow_redirects=True).content).decode("utf-8")

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Describe the image."},
            { # [!code highlight]
                "type": "image", # [!code highlight]
                "base64": image_data, # [!code highlight]
                "mime_type": "image/jpeg", # [!code highlight]
            }, # [!code highlight]
        ]
    )
    response = model.invoke([message])
    
    from langchain_anthropic import ChatAnthropic
    from langchain.messages import HumanMessage

    client = anthropic.Anthropic()
    file = client.beta.files.upload(
        file=("image.png", open("/path/to/image.png", "rb"), "image/png"),
    )

    model = ChatAnthropic(
        model="claude-sonnet-4-6",
        betas=["files-api-2025-04-14"], # [!code highlight]
    )

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Describe this image."},
            {
                "type": "image",
                "file_id": file.id, # [!code highlight]
            },
        ]
    )
    response = model.invoke([message])
    

PDF 输入

提供 PDF 文件输入及文本。

    from langchain_anthropic import ChatAnthropic
    from langchain.messages import HumanMessage

    model = ChatAnthropic(model="claude-sonnet-4-6")

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Summarize this document."},
            {
                "type": "file",
                "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
                "mime_type": "application/pdf",
            },
        ]
    )
    response = model.invoke([message])
    
    from langchain_anthropic import ChatAnthropic
    from langchain.messages import HumanMessage

    model = ChatAnthropic(model="claude-sonnet-4-6")

    pdf_url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
    pdf_data = base64.b64encode(httpx.get(pdf_url).content).decode("utf-8")

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Summarize this document."},
            {
                "type": "file",
                "base64": pdf_data, # [!code highlight]
                "mime_type": "application/pdf", # [!code highlight]
            },
        ]
    )
    response = model.invoke([message])
    
    from langchain_anthropic import ChatAnthropic
    from langchain.messages import HumanMessage

    client = anthropic.Anthropic()
    file = client.beta.files.upload(
        file=("document.pdf", open("/path/to/document.pdf", "rb"), "application/pdf"),
    )

    model = ChatAnthropic(
        model="claude-sonnet-4-6",
        betas=["files-api-2025-04-14"], # [!code highlight]
    )

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Summarize this document."},
            {
                "type": "file",
                "file_id": file.id, # [!code highlight]
            },
        ]
    )
    response = model.invoke([message])
    

扩展思维

某些 Claude 模型支持 扩展思维 功能,将输出导致最终答案的分步骤推理过程。

请参阅 Claude 文档.

查看兼容模型。要使用扩展思维,请在初始化 @[ thinking ] 时指定ChatAnthropic参数。如有需要,也可以在调用时作为参数传入。

对于 Claude Sonnet 及更早版本模型,您需要指定令牌预算。对于 Claude Opus 4.6+,您可以使用自适应思维,自动确定预算。

    from langchain_anthropic import ChatAnthropic

    model = ChatAnthropic(
        model="claude-sonnet-4-6",
        max_tokens=5000,
        thinking={"type": "enabled", "budget_tokens": 2000}, # [!code highlight]
    )

    response = model.invoke("What is the cube root of 50.653?")
    print(json.dumps(response.content_blocks, indent=2))
    
    from langchain_anthropic import ChatAnthropic

    model = ChatAnthropic(
        model="claude-opus-4-8",
        max_tokens=5000,
        thinking={"type": "adaptive"}, # [!code highlight]
    )

    response = model.invoke("What is the cube root of 50.653?")
    print(json.dumps(response.content_blocks, indent=2))
    
    from langchain_anthropic import ChatAnthropic

    model = ChatAnthropic(model="claude-sonnet-4-6")

    response = model.invoke(
        "What is the cube root of 50.653?",
        max_tokens=5000,
        thinking={"type": "enabled", "budget_tokens": 2000} # [!code highlight]
    )
    print(json.dumps(response.content_blocks, indent=2))
    
[
  {
    "type": "reasoning",
    "reasoning": "To find the cube root of 50.653, I need to find the value of $x$ such that $x^3 = 50.653$.\n\nI can try to estimate this first. \n$3^3 = 27$\n$4^3 = 64$\n\nSo the cube root of 50.653 will be somewhere between 3 and 4, but closer to 4.\n\nLet me try to compute this more precisely. I can use the cube root function:\n\ncube root of 50.653 = 50.653^(1/3)\n\nLet me calculate this:\n50.653^(1/3) \u2248 3.6998\n\nLet me verify:\n3.6998^3 \u2248 50.6533\n\nThat's very close to 50.653, so I'm confident that the cube root of 50.653 is approximately 3.6998.\n\nActually, let me compute this more precisely:\n50.653^(1/3) \u2248 3.69981\n\nLet me verify once more:\n3.69981^3 \u2248 50.652998\n\nThat's extremely close to 50.653, so I'll say that the cube root of 50.653 is approximately 3.69981.",
    "extras": {"signature": "ErUBCkYIBxgCIkB0UjV..."}
  },
  {
    "type": "text",
    "text": "The cube root of 50.653 is approximately 3.6998.\n\nTo verify: 3.6998\u00b3 = 50.6530, which is very close to our original number.",
  }
]

努力程度

某些 Claude 模型支持 努力程度 功能,用于控制 Claude 响应时使用的令牌数量。这有助于在响应质量与延迟和成本之间取得平衡。

from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(
    model="claude-opus-4-5-20251101",
    effort="medium",  # Options: "max", "xhigh", "high", "medium", "low" [!code highlight]
)

response = model.invoke("Analyze the trade-offs between microservices and monolithic architectures")

请参阅 Claude 文档 了解何时使用不同的投入级别以及支持哪些模型。

任务预算

Claude Opus 4.7 及更高版本支持 任务预算,这是代理循环(思考、工具调用、工具结果和最终输出)的非强制性 token 目标。模型会看到一个实时倒计时,并用它来优先处理工作并优雅地完成。与 max_tokens不同,任务预算不是硬性上限。

from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(
    model="claude-opus-4-8",
    output_config={  # [!code highlight]
        "effort": "high",  # [!code highlight]
        "task_budget": {"type": "tokens", "total": 128_000},  # [!code highlight]
    },  # [!code highlight]
)

引用

Anthropic 支持 引用 功能,允许 Claude 根据用户提供的源文档在其答案中附加上下文。

包含 or search_result 的文档 "citations": {"enabled": True} 内容块包含在查询中时,Claude 可能会在其回复中生成引用。

简单示例

在这个示例中,我们传递了一个 纯文本文档。在后台,Claude 会 自动将 输入文本分块成句子,这些句子在生成引用时使用。

from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(model="claude-haiku-4-5-20251001")

messages = [
    {
        "role": "user",
        "content": [
            {
                "type": "document",
                "source": {
                    "type": "text",
                    "media_type": "text/plain",
                    "data": "The grass is green. The sky is blue.",
                },
                "title": "My Document",
                "context": "This is a trustworthy document.",
                "citations": {"enabled": True},
            },
            {"type": "text", "text": "What color is the grass and sky?"},
        ],
    }
]
response = model.invoke(messages)
response.content
[{'text': 'Based on the document, ', 'type': 'text'},
 {'text': 'the grass is green',
  'type': 'text',
  'citations': [{'type': 'char_location',
    'cited_text': 'The grass is green. ',
    'document_index': 0,
    'document_title': 'My Document',
    'start_char_index': 0,
    'end_char_index': 20}]},
 {'text': ', and ', 'type': 'text'},
 {'text': 'the sky is blue',
  'type': 'text',
  'citations': [{'type': 'char_location',
    'cited_text': 'The sky is blue.',
    'document_index': 0,
    'document_title': 'My Document',
    'start_char_index': 20,
    'end_char_index': 36}]},
 {'text': '.', 'type': 'text'}]

在工具结果中(代理式 RAG)

Claude 支持 搜索_结果 内容块,表示针对知识库或其他自定义来源的查询的可引用结果。这些内容块可以以顶层方式(如上述示例所示)和在工具结果中传递给 claude。这允许 Claude 使用工具调用的结果来引用其回复中的元素。

要在线索调用的响应中传递搜索结果,请定义一个返回 search_result 内容块列表的工具,使用 Anthropic 的原生格式。例如:

def retrieval_tool(query: str) -> list[dict]:
    """Access my knowledge base."""

    # Run a search (e.g., with a LangChain vector store)
    results = vector_store.similarity_search(query=query, k=2)

    # Package results into search_result blocks
    return [
        {
            "type": "search_result",
            # Customize fields as desired, using document metadata or otherwise
            "title": "My Document Title",
            "source": "Source description or provenance",
            "citations": {"enabled": True},
            "content": [{"type": "text", "text": doc.page_content}],
        }
        for doc in results
    ]

End to end example with LangGraph

这里我们演示一个端到端示例,其中我们用示例文档填充 LangChain 向量存储 ,并为 Claude 配备一个查询这些文档的工具。

这里的工具接受一个搜索查询和一个 category 字符串字面量,但可以使用任何有效的工具签名。

此示例需要安装 langchain-openainumpy

    pip install langchain-openai numpy
    
    from typing import Literal

    from langchain.chat_models import init_chat_model
    from langchain.embeddings import init_embeddings
    from langchain_core.documents import Document
    from langchain_core.vectorstores import InMemoryVectorStore
    from langgraph.checkpoint.memory import InMemorySaver
    from langchain.agents import create_agent


    # Set up vector store
    # Ensure you set your OPENAI_API_KEY environment variable
    embeddings = init_embeddings("openai:text-embedding-3-small")
    vector_store = InMemoryVectorStore(embeddings)

    document_1 = Document(
        id="1",
        page_content=(
            "To request vacation days, submit a leave request form through the "
            "HR portal. Approval will be sent by email."
        ),
        metadata={
            "category": "HR Policy",
            "doc_title": "Leave Policy",
            "provenance": "Leave Policy - page 1",
        },
    )
    document_2 = Document(
        id="2",
        page_content="Managers will review vacation requests within 3 business days.",
        metadata={
            "category": "HR Policy",
            "doc_title": "Leave Policy",
            "provenance": "Leave Policy - page 2",
        },
    )
    document_3 = Document(
        id="3",
        page_content=(
            "Employees with over 6 months tenure are eligible for 20 paid vacation days "
            "per year."
        ),
        metadata={
            "category": "Benefits Policy",
            "doc_title": "Benefits Guide 2025",
            "provenance": "Benefits Policy - page 1",
        },
    )

    documents = [document_1, document_2, document_3]
    vector_store.add_documents(documents=documents)


    # Define tool
    async def retrieval_tool(
        query: str, category: Literal["HR Policy", "Benefits Policy"]
    ) -> list[dict]:
        """Access my knowledge base."""

        def _filter_function(doc: Document) -> bool:
            return doc.metadata.get("category") == category

        results = vector_store.similarity_search(
            query=query, k=2, filter=_filter_function
        )

        return [
            {
                "type": "search_result",
                "title": doc.metadata["doc_title"],
                "source": doc.metadata["provenance"],
                "citations": {"enabled": True},
                "content": [{"type": "text", "text": doc.page_content}],
            }
            for doc in results
        ]



    # Create agent
    model = init_chat_model("claude-haiku-4-5-20251001")

    checkpointer = InMemorySaver()
    agent = create_agent(model, [retrieval_tool], checkpointer=checkpointer)


    # Invoke on a query
    config = {"configurable": {"thread_id": "session_1"}}

    input_message = {
        "role": "user",
        "content": "How do I request vacation days?",
    }
    stream = await agent.astream_events(
        {"messages": [input_message]},
        config,
        version="v3",
    )
    async for snapshot in stream.values:
        snapshot["messages"][-1].pretty_print()
    

与文本分割器配合使用

Anthropic 还允许您使用 自定义文档 类型指定您自己的分割。LangChain 文本分割器 可用于为此目的生成有意义的分割。请参见下面的示例,我们分割 LangChain README.md (一个 Markdown 文档)并将其作为上下文传递给 Claude:

此示例需要安装 langchain-text-splitters

pip install langchain-text-splitters
from langchain_anthropic import ChatAnthropic
from langchain_text_splitters import MarkdownTextSplitter


def format_to_anthropic_documents(documents: list[str]):
    return {
        "type": "document",
        "source": {
            "type": "content",
            "content": [{"type": "text", "text": document} for document in documents],
        },
        "citations": {"enabled": True},
    }


# Pull readme
get_response = requests.get(
    "https://raw.githubusercontent.com/langchain-ai/langchain/master/README.md"
)
readme = get_response.text

# Split into chunks
splitter = MarkdownTextSplitter(
    chunk_overlap=0,
    chunk_size=50,
)
documents = splitter.split_text(readme)

# Construct message
message = {
    "role": "user",
    "content": [
        format_to_anthropic_documents(documents),
        {"type": "text", "text": "Give me a link to LangChain's tutorials."},
    ],
}

# Query model
model = ChatAnthropic(model="claude-haiku-4-5-20251001")
response = model.invoke([message])

提示词缓存

Anthropic 支持 缓存 提示词中元素的缓存,包括消息、工具定义、工具结果、图像和文档。这允许您重用大型文档、指令、 少样本文档和其他数据以降低延迟和成本。

在直接模型调用中有两种方式启用提示词缓存:

  • - **自动缓存**:传递 cache_control 在调用时(model.invoke(..., cache_control=...)). This is provider/API-level caching: the Anthropic API applies the cache breakpoint to the last cacheable block and moves it forward as conversations grow.
  • - **显式缓存断点**:放置 cache_control 直接放在各个内容块上,以实现精细的、直接的断点控制,准确控制需要缓存的内容。

自动缓存

传递 cache_control 作为调用参数,自动缓存直到并包括最后一个可缓存块的所有内容。在具有相同前缀的后续请求中,缓存内容会自动重用。随着对话增长,缓存断点会向前移动,因此您无需管理各个 cache_control markers.

from langchain_anthropic import ChatAnthropic


model = ChatAnthropic(model="claude-sonnet-4-5")

# Pull LangChain readme
get_response = requests.get(
    "https://raw.githubusercontent.com/langchain-ai/langchain/b476fdb54aa6e6f5f0b24a68c2f4a94e43b369f9/README.md"
)
readme = get_response.text

messages = [
    {
        "role": "system",
        "content": [
            {
                "type": "text",
                "text": "You are a technology expert.",
            },
            {
                "type": "text",
                "text": f"{readme}"
            },
        ],
    },
    {
        "role": "user",
        "content": "What's LangChain, according to its README?",
    },
]

response = model.invoke(
    messages,
    cache_control={"type": "ephemeral"},  # [!code highlight]
)

usage = response.usage_metadata["input_token_details"]
print(f"Usage:\n{usage}")

对于 1 小时缓存,指定 ttl field:

response = model.invoke(
    messages,
    cache_control={"type": "ephemeral", "ttl": "1h"},  # [!code highlight]
)

显式缓存断点

为了实现精细控制,请在各个内容块上标记 cache_control。当您需要缓存以不同频率变化的不同部分时,这很有用。

消息

from langchain_anthropic import ChatAnthropic


model = ChatAnthropic(model="claude-sonnet-4-5")

# Pull LangChain readme
get_response = requests.get(
    "https://raw.githubusercontent.com/langchain-ai/langchain/b476fdb54aa6e6f5f0b24a68c2f4a94e43b369f9/README.md"
)
readme = get_response.text

messages = [
    {
        "role": "system",
        "content": [
            {
                "type": "text",
                "text": "You are a technology expert.",
            },
            {
                "type": "text",
                "text": f"{readme}",
                "cache_control": {"type": "ephemeral"},  # [!code highlight]
            },
        ],
    },
    {
        "role": "user",
        "content": "What's LangChain, according to its README?",
    },
]

response_1 = model.invoke(messages)
response_2 = model.invoke(messages)

usage_1 = response_1.usage_metadata["input_token_details"]
usage_2 = response_2.usage_metadata["input_token_details"]

print(f"First invocation:\n{usage_1}")
print(f"\nSecond:\n{usage_2}")
First invocation:
{'cache_read': 0, 'cache_creation': 0, 'ephemeral_5m_input_tokens': 1569, 'ephemeral_1h_input_tokens': 0}

Second:
{'cache_read': 1569, 'cache_creation': 0, 'ephemeral_5m_input_tokens': 0, 'ephemeral_1h_input_tokens': 0}

缓存工具

from langchain_anthropic import ChatAnthropic
from langchain.tools import tool


# For demonstration purposes, we artificially expand the
# tool description using the LangChain README text.
get_response = requests.get(
    "https://raw.githubusercontent.com/langchain-ai/langchain/master/README.md"
)
readme = get_response.text
description = (
    "Get the weather at a location. "
    f"By the way, check out this readme: {readme}"
)


@tool(description=description, extras={"cache_control": {"type": "ephemeral"}})  # [!code highlight]
def get_weather(location: str) -> str:
    return "It's sunny."


model = ChatAnthropic(model="claude-sonnet-4-6")
model_with_tools = model.bind_tools([get_weather])
query = "What's the weather in San Francisco?"

response_1 = model_with_tools.invoke(query)
response_2 = model_with_tools.invoke(query)

usage_1 = response_1.usage_metadata["input_token_details"]
usage_2 = response_2.usage_metadata["input_token_details"]

print(f"First invocation:\n{usage_1}")
print(f"\nSecond:\n{usage_2}")
First invocation:
{'cache_read': 0, 'cache_creation': 1809}

Second:
{'cache_read': 1809, 'cache_creation': 0}

对话应用中的增量缓存

提示词缓存可用于 多轮对话 以维护来自早期消息的上下文,而无需冗余处理。

我们可以通过标记最后一条消息来启用增量缓存 cache_control。Claude 将自动使用最长的先前缓存前缀用于后续消息。

下面,我们实现一个包含此功能的简单聊天机器人。我们遵循 LangChain 聊天机器人教程,但添加了一个自定义 归约器 ,用于自动标记每条用户消息中的最后一个内容块 cache_control:

Chatbot with incremental prompt caching

    from langchain_anthropic import ChatAnthropic
    from langgraph.checkpoint.memory import MemorySaver
    from langgraph.graph import START, StateGraph, add_messages
    from typing_extensions import Annotated, TypedDict


    model = ChatAnthropic(model="claude-sonnet-4-6")

    # Pull LangChain readme
    get_response = requests.get(
        "https://raw.githubusercontent.com/langchain-ai/langchain/master/README.md"
    )
    readme = get_response.text


    def messages_reducer(left: list, right: list) -> list:
        # Update last user message
        for i in range(len(right) - 1, -1, -1):
            if right[i].type == "human":
                right[i].content[-1]["cache_control"] = {"type": "ephemeral"}
                break

        return add_messages(left, right)


    class State(TypedDict):
        messages: Annotated[list, messages_reducer]


    workflow = StateGraph(state_schema=State)


    # Define the function that calls the model
    def call_model(state: State):
        response = model.invoke(state["messages"])
        return {"messages": [response]}


    # Define the (single) node in the graph
    workflow.add_edge(START, "model")
    workflow.add_node("model", call_model)

    # Add memory
    memory = MemorySaver()
    app = workflow.compile(checkpointer=memory)
    
    from langchain.messages import HumanMessage

    config = {"configurable": {"thread_id": "abc123"}}

    query = "Hi! I'm Bob."

    input_message = HumanMessage([{"type": "text", "text": query}])
    output = app.invoke({"messages": [input_message]}, config)
    output["messages"][-1].pretty_print()
    print(f"\n{output['messages'][-1].usage_metadata['input_token_details']}")
    
    ================================== Ai Message ==================================

    Hello, Bob! It's nice to meet you. How are you doing today? Is there something I can help you with?

    {'cache_read': 0, 'cache_creation': 0, 'ephemeral_5m_input_tokens': 0, 'ephemeral_1h_input_tokens': 0}
    
    query = f"Check out this readme: {readme}"

    input_message = HumanMessage([{"type": "text", "text": query}])
    output = app.invoke({"messages": [input_message]}, config)
    output["messages"][-1].pretty_print()
    print(f"\n{output['messages'][-1].usage_metadata['input_token_details']}")
    
    ================================== Ai Message ==================================

    I can see you've shared the README from the LangChain GitHub repository. This is the documentation for LangChain, which is a popular framework for building applications powered by Large Language Models (LLMs). Here's a summary of what the README contains:

    LangChain is:
    - A framework for developing LLM-powered applications
    - Helps chain together components and integrations to simplify AI application development
    - Provides a standard interface for models, embeddings, vector stores, etc.

    Key features/benefits:
    - Real-time data augmentation (connect LLMs to diverse data sources)
    - Model interoperability (swap models easily as needed)
    - Large ecosystem of integrations

    The LangChain ecosystem includes:
    - LangSmith - For evaluations and observability
    - LangGraph - For building complex agents with customizable architecture
    - LangSmith - For deployment and scaling of agents

    The README also mentions installation instructions (`pip install -U langchain`) and links to various resources including tutorials, how-to guides, conceptual guides, and API references.

    Is there anything specific about LangChain you'd like to know more about, Bob?

    {'cache_read': 0, 'cache_creation': 1846, 'ephemeral_5m_input_tokens': 1846, 'ephemeral_1h_input_tokens': 0}
    
    query = "What was my name again?"

    input_message = HumanMessage([{"type": "text", "text": query}])
    output = app.invoke({"messages": [input_message]}, config)
    output["messages"][-1].pretty_print()
    print(f"\n{output['messages'][-1].usage_metadata['input_token_details']}")
    
    ================================== Ai Message ==================================

    Your name is Bob. You introduced yourself at the beginning of our conversation.

    {'cache_read': 1846, 'cache_creation': 278, 'ephemeral_5m_input_tokens': 278, 'ephemeral_1h_input_tokens': 0}
    

LangSmith 追踪中,切换"原始输出"将准确显示发送到聊天模型的消息,包括 cache_control keys.

令牌计数

您可以在发送消息到模型之前使用 get_num_tokens_from_messages()。这使用 Anthropic 官方 令牌计数 API.

消息令牌计数

        from langchain_anthropic import ChatAnthropic
        from langchain.messages import HumanMessage, SystemMessage

        model = ChatAnthropic(model="claude-sonnet-4-6")

        messages = [
            SystemMessage(content="You are a scientist"),
            HumanMessage(content="Hello, Claude"),
        ]

        token_count = model.get_num_tokens_from_messages(messages)
        print(token_count)
        
        14
        

工具令牌计数

您还可以在使用工具时计算令牌:

        from langchain.tools import tool

        @tool(parse_docstring=True)
        def get_weather(location: str) -> str:
            """Get the current weather in a given location

            Args:
                location: The city and state, e.g. San Francisco, CA
            """
            return "Sunny"

        messages = [
            HumanMessage(content="What's the weather like in San Francisco?"),
        ]

        token_count = model.get_num_tokens_from_messages(messages, tools=[get_weather])
        print(token_count)
        
        586
        

上下文管理

Anthropic 支持上下文管理功能,可自动管理模型的上下文窗口以优化性能和成本。

有关更多详情和配置选项,请参阅 Claude 文档

清除工具使用

从上下文中清除工具结果以减少令牌使用量,同时保持对话流程。

from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(
    model="claude-sonnet-4-6",
    betas=["context-management-2025-06-27"], # [!code highlight]
    context_management={"edits": [{"type": "clear_tool_uses_20250919"}]}, # [!code highlight]
)
model_with_tools = model.bind_tools([{"type": "web_search_20260209", "name": "web_search"}])
response = model_with_tools.invoke("Search for recent developments in AI")

自动压缩

Claude Opus 4.6 及更高版本支持自动 服务端压缩,当上下文窗口接近其限制时,智能压缩对话历史。这允许更长的对话而无需手动上下文管理。

from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(
    model="claude-opus-4-8",
    betas=["compact-2026-01-12"], # [!code highlight]
    max_tokens=4096,
    context_management={ # [!code highlight]
        "edits": [ # [!code highlight]
            { # [!code highlight]
                "type": "compact_20260112", # [!code highlight]
                "trigger": {"type": "input_tokens", "value": 50000}, # [!code highlight]
            } # [!code highlight]
        ] # [!code highlight]
    }, # [!code highlight]
)

有关触发配置的详细信息,请参阅 Anthropic 的文档 触发配置.

当触发压缩事件时, ChatAnthropic 将返回 压缩块 表示提示的状态。这些应该保留在传递回模型的消息历史中,用于多轮应用程序。

结构化输出

Anthropic 支持原生 结构化输出功能,可保证其响应符合给定模式。

您可以在单个模型调用中访问此功能,或通过指定 响应格式 的 LangChain 代理。请参阅下面的示例。

Individual model calls

使用 with_structured_output 方法来生成结构化模型响应。指定 method="json_schema" 以启用 Anthropic 的原生结构化输出功能;否则该方法默认使用函数调用。

from langchain_anthropic import ChatAnthropic
from pydantic import BaseModel, Field

model = ChatAnthropic(model="claude-sonnet-4-6")

class Movie(BaseModel):
    """A movie with details."""
    title: str = Field(description="The title of the movie")
    year: int = Field(description="The year the movie was released")
    director: str = Field(description="The director of the movie")
    rating: float = Field(description="The movie's rating out of 10")

model_with_structure = model.with_structured_output(Movie, method="json_schema")  # [!code highlight]
response = model_with_structure.invoke("Provide details about the movie Inception")
response
Movie(title='Inception', year=2010, director='Christopher Nolan', rating=8.8)

Agent response format

指定 response_format 配合 ProviderStrategy 以在生成最终响应时启用 Anthropic 的结构化输出功能。

from langchain.agents import create_agent
from langchain.agents.structured_output import ProviderStrategy
from pydantic import BaseModel

class Weather(BaseModel):
    temperature: float
    condition: str

def weather_tool(location: str) -> str:
    """Get the weather at a location."""
    return "Sunny and 75 degrees F."

agent = create_agent(
    model="anthropic:claude-sonnet-4-5",
    tools=[weather_tool],
    response_format=ProviderStrategy(Weather),  # [!code highlight]
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "What's the weather in SF?"}]
})

result["structured_response"]
Weather(temperature=75.0, condition='Sunny')

内置工具

Anthropic 支持多种内置的客户端和服务器端 工具.

服务器端工具(例如, 网络搜索)会传递给模型并由 Anthropic 执行。客户端工具(例如, bash 工具)需要您在应用程序中实现回调执行逻辑,并将结果返回给模型。

在这两种情况下,您都可以通过在模型实例上使用 bind_tools 来使工具对聊天模型可用。

重要的是,客户端工具需要您实现执行逻辑。有关示例,请参阅下面的相关部分。

Bash 工具

Claude 支持客户端 bash 工具 ,允许其在持久的 bash 会话中执行 shell 命令。这支持系统操作、脚本执行和命令行自动化。

Anthropic type

        from anthropic.types.beta import BetaToolBash20250124Param  # [!code highlight]
        from langchain_anthropic import ChatAnthropic
        from langchain.messages import HumanMessage, ToolMessage
        from langchain.tools import tool

        tool_spec = BetaToolBash20250124Param(  # [!code highlight]
            name="bash",  # [!code highlight]
            type="bash_20250124",  # [!code highlight]
        )  # [!code highlight]


        @tool(extras={"provider_tool_definition": tool_spec})  # [!code highlight]
        def bash(*, command: str, restart: bool = False, **kw):
            """Execute a bash command."""
            if restart:
                return "Bash session restarted"
            try:
                result = subprocess.run(
                    command,
                    shell=True,
                    capture_output=True,
                    text=True,
                    timeout=30,
                )
                return result.stdout + result.stderr
            except Exception as e:
                return f"Error: {e}"


        model = ChatAnthropic(model="claude-sonnet-4-6")
        model_with_bash = model.bind_tools([bash]) # [!code highlight]

        # Initial request
        messages = [HumanMessage("List all files in the current directory")]
        response = model_with_bash.invoke(messages)
        print(response.content_blocks)

        # Tool execution loop
        while response.tool_calls:
            # Execute each tool call
            tool_messages = []
            for tool_call in response.tool_calls:
                result = bash.invoke(tool_call)
                tool_messages.append(result)

            # Continue conversation with tool results
            messages = [*messages, response, *tool_messages]
            response = model_with_bash.invoke(messages)
            print(response.content_blocks)
        

create_agent

        from anthropic.types.beta import BetaToolBash20250124Param # [!code highlight]
        from langchain.agents import create_agent
        from langchain_anthropic import ChatAnthropic
        from langchain.tools import tool

        tool_spec = BetaToolBash20250124Param( # [!code highlight]
            name="bash", # [!code highlight]
            type="bash_20250124", # [!code highlight]
        ) # [!code highlight]


        @tool(extras={"provider_tool_definition": tool_spec}) # [!code highlight]
        def bash(*, command: str, restart: bool = False, **kw):
            """Execute a bash command."""
            if restart:
                return "Bash session restarted"
            result = subprocess.run(
                command,
                shell=True,
                capture_output=True,
                text=True,
            )
            return result.stdout + result.stderr


        agent = create_agent(
            model=ChatAnthropic(model="claude-sonnet-4-6"),
            tools=[bash],  # [!code highlight]
        )

        result = agent.invoke({"messages": [{"role": "user", "content": "List files"}]})

        for message in result["messages"]:
            message.pretty_print()
        

Dict

        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(model="claude-sonnet-4-6")

        bash_tool = { # [!code highlight]
            "type": "bash_20250124", # [!code highlight]
            "name": "bash", # [!code highlight]
        } # [!code highlight]

        model_with_bash = model.bind_tools([bash_tool]) # [!code highlight]
        response = model_with_bash.invoke(
            "List all Python files in the current directory"
        )
        # You must handle execution of the bash command in response.tool_calls via a tool execution loop
        

使用 create_agent 会自动处理工具执行循环。

response.tool_calls 包含 Claude 要执行的 bash 命令。您必须在您的环境中运行此命令并传回结果。

        [{'type': 'text',
        'text': "I'll list the Python files in the current directory for you."},
        {'type': 'tool_call',
        'name': 'bash',
        'args': {'command': 'ls -la *.py'},
        'id': 'toolu_01ABC123...'}]
        

Bash 工具支持两个参数: - command (必填): 要执行的 bash 命令 - restart (可选): 设置为 true 重启 bash 会话

代码执行

Claude 可以使用服务端 代码执行工具 在沙盒环境中执行代码。

Anthropic type

        from anthropic.types.beta import BetaCodeExecutionTool20250825Param # [!code highlight]
        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(
            model="claude-sonnet-4-6",
            # (Optional) Enable the param below to automatically
            # pass back in container IDs from previous response
            reuse_last_container=True,
        )

        code_tool = BetaCodeExecutionTool20250825Param( # [!code highlight]
            name="code_execution", # [!code highlight]
            type="code_execution_20250825", # [!code highlight]
        ) # [!code highlight]
        model_with_tools = model.bind_tools([code_tool]) # [!code highlight]

        response = model_with_tools.invoke(
            "Calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
        )
        

create_agent

        from anthropic.types.beta import BetaCodeExecutionTool20250825Param # [!code highlight]
        from langchain.agents import create_agent
        from langchain_anthropic import ChatAnthropic

        code_tool = BetaCodeExecutionTool20250825Param( # [!code highlight]
            name="code_execution", # [!code highlight]
            type="code_execution_20250825", # [!code highlight]
        ) # [!code highlight]

        agent = create_agent(
            model=ChatAnthropic(model="claude-sonnet-4-6"),
            tools=[code_tool],  # [!code highlight]
        )

        result = agent.invoke({
            "messages": [{"role": "user", "content": "Calculate mean and std of [1,2,3,4,5]"}]
        })

        for message in result["messages"]:
            message.pretty_print()
        

Dict

        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(
            model="claude-sonnet-4-6",
        )

        code_tool = {"type": "code_execution_20250825", "name": "code_execution"} # [!code highlight]
        model_with_tools = model.bind_tools([code_tool])

        response = model_with_tools.invoke(
            "Calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
        )
        

Use with Files API

通过 Files API,Claude 可以编写代码来访问文件以进行数据分析和其它用途。请参阅以下示例:

    from anthropic.types.beta import BetaCodeExecutionTool20250825Param # [!code highlight]
    from langchain_anthropic import ChatAnthropic


    client = anthropic.Anthropic()
    file = client.beta.files.upload(
        file=open("/path/to/sample_data.csv", "rb")
    )
    file_id = file.id


    # Run inference
    model = ChatAnthropic(
        model="claude-sonnet-4-6",
    )

    code_tool = BetaCodeExecutionTool20250825Param( # [!code highlight]
        name="code_execution", # [!code highlight]
        type="code_execution_20250825", # [!code highlight]
    ) # [!code highlight]
    model_with_tools = model.bind_tools([code_tool])

    input_message = {
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "Please plot these data and tell me what you see.",
            },
            {
                "type": "container_upload",
                "file_id": file_id,
            },
        ]
    }
    response = model_with_tools.invoke([input_message])
    

请注意,Claude 可能会在代码执行过程中生成文件。您可以使用 Files API 访问这些文件:

    # Take all file outputs for demonstration purposes
    file_ids = []
    for block in response.content:
        if block["type"] == "bash_code_execution_tool_result":
            file_ids.extend(
                content["file_id"]
                for content in block.get("content", {}).get("content", [])
                if "file_id" in content
            )

    for i, file_id in enumerate(file_ids):
        file_content = client.beta.files.download(file_id)
        file_content.write_to_file(f"/path/to/file_{i}.png")
    

计算机使用

Claude 支持客户端 计算机使用 功能,使其能够通过截屏、鼠标控制和键盘输入与桌面环境进行交互。

Anthropic type

        from typing import Literal

        from anthropic.types.beta import BetaToolComputerUse20250124Param # [!code highlight]
        from langchain_anthropic import ChatAnthropic
        from langchain.messages import HumanMessage, ToolMessage
        from langchain.tools import tool

        DISPLAY_WIDTH = 1024
        DISPLAY_HEIGHT = 768

        tool_spec = BetaToolComputerUse20250124Param( # [!code highlight]
            name="computer", # [!code highlight]
            type="computer_20250124", # [!code highlight]
            display_width_px=DISPLAY_WIDTH, # [!code highlight]
            display_height_px=DISPLAY_HEIGHT, # [!code highlight]
            display_number=1, # [!code highlight]
        ) # [!code highlight]

        @tool(extras={"provider_tool_definition": tool_spec}) # [!code highlight]
        def computer(
            *,
            action: Literal[
                "key", "type", "mouse_move", "left_click", "left_click_drag",
                "right_click", "middle_click", "double_click", "screenshot",
                "cursor_position", "scroll"
            ],
            coordinate: list[int] | None = None,
            text: str | None = None,
            **kw
        ):
            """Control the computer display."""
            if action == "screenshot":
                # Take screenshot and return base64-encoded image
                # Implementation depends on your display setup (e.g., Xvfb, pyautogui)
                return {"type": "image", "data": "base64_screenshot_data..."}
            elif action == "left_click" and coordinate:
                # Execute click at coordinate
                return f"Clicked at {coordinate}"
            elif action == "type" and text:
                # Type text
                return f"Typed: {text}"
            # ... implement other actions
            return f"Executed {action}"

        model = ChatAnthropic(model="claude-sonnet-4-6")
        model_with_computer = model.bind_tools([computer]) # [!code highlight]

        # Initial request
        messages = [HumanMessage("Take a screenshot to see what's on the screen")]
        response = model_with_computer.invoke(messages)
        print(response.content_blocks)

        # Tool execution loop
        while response.tool_calls:
            tool_messages = []
            for tool_call in response.tool_calls:
                result = computer.invoke(tool_call)
                tool_messages.append(
                    ToolMessage(content=str(result), tool_call_id=tool_call["id"])
                )

            messages = [*messages, response, *tool_messages]
            response = model_with_computer.invoke(messages)
            print(response.content_blocks)
        

create_agent

        from typing import Literal

        from anthropic.types.beta import BetaToolComputerUse20250124Param # [!code highlight]
        from langchain.agents import create_agent
        from langchain_anthropic import ChatAnthropic
        from langchain.tools import tool

        tool_spec = BetaToolComputerUse20250124Param( # [!code highlight]
            name="computer", # [!code highlight]
            type="computer_20250124", # [!code highlight]
            display_width_px=1024, # [!code highlight]
            display_height_px=768, # [!code highlight]
        ) # [!code highlight]


        @tool(extras={"provider_tool_definition": tool_spec}) # [!code highlight]
        def computer(
            *,
            action: Literal[
                "key", "type", "mouse_move", "left_click", "left_click_drag",
                "right_click", "middle_click", "double_click", "screenshot",
                "cursor_position", "scroll"
            ],
            coordinate: list[int] | None = None,
            text: str | None = None,
            **kw
        ):
            """Control the computer display."""
            if action == "screenshot":
                return {"type": "image", "data": "base64_screenshot_data..."}
            elif action == "left_click" and coordinate:
                return f"Clicked at {coordinate}"
            elif action == "type" and text:
                return f"Typed: {text}"
            return f"Executed {action}"


        agent = create_agent(
            model=ChatAnthropic(model="claude-sonnet-4-6"),
            tools=[computer],  # [!code highlight]
        )

        result = agent.invoke({
            "messages": [{"role": "user", "content": "Take a screenshot"}]
        })

        for message in result["messages"]:
            message.pretty_print()
        

Dict

        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(model="claude-sonnet-4-6")

        computer_tool = {
            "type": "computer_20250124",
            "name": "computer",
            "display_width_px": 1024,
            "display_height_px": 768,
            "display_number": 1,
        }

        model_with_computer = model.bind_tools([computer_tool]) # [!code highlight]
        response = model_with_computer.invoke(
            "Take a screenshot to see what's on the screen"
        )
        # You must handle execution of the computer actions in response.tool_calls via a tool execution loop
        

使用 @[create_agent可以自动处理工具执行循环。

response.tool_calls 将包含 Claude 想要执行的计算机操作。您必须在您的环境中执行此操作并传回结果。

        [{'type': 'text',
        'text': "I'll take a screenshot to see what's currently on the screen."},
        {'type': 'tool_call',
        'name': 'computer',
        'args': {'action': 'screenshot'},
        'id': 'toolu_01RNsqAE7dDZujELtacNeYv9'}]
        

远程 MCP

Claude 可以使用服务端 MCP 连接器工具 用于模型生成的远程 MCP 服务器调用。

Anthropic type

        from anthropic.types.beta import BetaMCPToolsetParam # [!code highlight]
        from langchain_anthropic import ChatAnthropic

        mcp_servers = [
            {
                "type": "url",
                "url": "https://docs.langchain.com/mcp",
                "name": "LangChain Docs",
            }
        ]

        model = ChatAnthropic(
            model="claude-sonnet-4-6",
            mcp_servers=mcp_servers, # [!code highlight]
        )

        mcp_tool = BetaMCPToolsetParam( # [!code highlight]
            type="mcp_toolset", # [!code highlight]
            mcp_server_name="LangChain Docs", # [!code highlight]
        ) # [!code highlight]

        response = model.invoke(
            "What are LangChain content blocks?",
            tools=[mcp_tool], # [!code highlight]
        )
        

create_agent

        from anthropic.types.beta import BetaMCPToolsetParam # [!code highlight]
        from langchain.agents import create_agent
        from langchain_anthropic import ChatAnthropic

        mcp_servers = [
            {
                "type": "url",
                "url": "https://docs.langchain.com/mcp",
                "name": "LangChain Docs",
            }
        ]

        mcp_tool = BetaMCPToolsetParam( # [!code highlight]
            type="mcp_toolset", # [!code highlight]
            mcp_server_name="LangChain Docs", # [!code highlight]
        ) # [!code highlight]

        agent = create_agent(
            model=ChatAnthropic(
                model="claude-sonnet-4-6",
                mcp_servers=mcp_servers,  # [!code highlight]
            ),
            tools=[mcp_tool],  # [!code highlight]
        )

        result = agent.invoke({
            "messages": [{"role": "user", "content": "What are LangChain content blocks?"}]
        })

        for message in result["messages"]:
            message.pretty_print()
        

Dict

        from langchain_anthropic import ChatAnthropic

        mcp_servers = [
            {
                "type": "url",
                "url": "https://docs.langchain.com/mcp",
                "name": "LangChain Docs",
                # "tool_configuration": {  # optional configuration
                #     "enabled": True,
                #     "allowed_tools": ["ask_question"],
                # },
                # "authorization_token": "PLACEHOLDER",  # optional authorization if needed
            }
        ]

        model = ChatAnthropic(
            model="claude-sonnet-4-6",
            mcp_servers=mcp_servers, # [!code highlight]
        )

        response = model.invoke(
            "What are LangChain content blocks?",
            tools=[{"type": "mcp_toolset", "mcp_server_name": "LangChain Docs"}], # [!code highlight]
        )
        response.content_blocks
        

文本编辑器

Claude 支持客户端文本编辑器工具,可用于查看和修改本地文本文件。请参阅 文本编辑器工具文档 了解更多详情。

Anthropic type

        from typing import Literal

        from anthropic.types.beta import BetaToolTextEditor20250728Param # [!code highlight]
        from langchain_anthropic import ChatAnthropic
        from langchain.messages import HumanMessage, ToolMessage
        from langchain.tools import tool

        tool_spec = BetaToolTextEditor20250728Param( # [!code highlight]
            name="str_replace_based_edit_tool", # [!code highlight]
            type="text_editor_20250728", # [!code highlight]
        ) # [!code highlight]

        # Simple in-memory file storage for demonstration
        files: dict[str, str] = {
            "/workspace/primes.py": "def is_prime(n):\n    if n < 2\n        return False\n    return True"
        }

        @tool(extras={"provider_tool_definition": tool_spec}) # [!code highlight]
        def str_replace_based_edit_tool(
            *,
            command: Literal["view", "create", "str_replace", "insert", "undo_edit"],
            path: str,
            file_text: str | None = None,
            old_str: str | None = None,
            new_str: str | None = None,
            insert_line: int | None = None,
            view_range: list[int] | None = None,
            **kw
        ):
            """View and edit text files."""
            if command == "view":
                if path not in files:
                    return f"Error: File {path} not found"
                content = files[path]
                if view_range:
                    lines = content.splitlines()
                    start, end = view_range[0] - 1, view_range[1]
                    return "\n".join(lines[start:end])
                return content
            elif command == "create":
                files[path] = file_text or ""
                return f"Created {path}"
            elif command == "str_replace" and old_str is not None:
                if path not in files:
                    return f"Error: File {path} not found"
                files[path] = files[path].replace(old_str, new_str or "", 1)
                return f"Replaced in {path}"
            # ... implement other commands
            return f"Executed {command} on {path}"

        model = ChatAnthropic(model="claude-sonnet-4-6")
        model_with_tools = model.bind_tools([str_replace_based_edit_tool]) # [!code highlight]

        # Initial request
        messages = [HumanMessage("There's a syntax error in my primes.py file. Can you fix it?")]
        response = model_with_tools.invoke(messages)
        print(response.content_blocks)

        # Tool execution loop
        while response.tool_calls:
            tool_messages = []
            for tool_call in response.tool_calls:
                result = str_replace_based_edit_tool.invoke(tool_call)
                tool_messages.append(
                    ToolMessage(content=result, tool_call_id=tool_call["id"])
                )

            messages = [*messages, response, *tool_messages]
            response = model_with_tools.invoke(messages)
            print(response.content_blocks)
        

create_agent

        from typing import Literal

        from anthropic.types.beta import BetaToolTextEditor20250728Param # [!code highlight]
        from langchain.agents import create_agent
        from langchain_anthropic import ChatAnthropic
        from langchain.tools import tool

        # Simple in-memory file storage
        files: dict[str, str] = {
            "/workspace/primes.py": "def is_prime(n):\n    if n < 2\n        return False\n    return True"
        }

        tool_spec = BetaToolTextEditor20250728Param( # [!code highlight]
            name="str_replace_based_edit_tool", # [!code highlight]
            type="text_editor_20250728", # [!code highlight]
        ) # [!code highlight]


        @tool(extras={"provider_tool_definition": tool_spec}) # [!code highlight]
        def str_replace_based_edit_tool(
            *,
            command: Literal["view", "create", "str_replace", "insert", "undo_edit"],
            path: str,
            file_text: str | None = None,
            old_str: str | None = None,
            new_str: str | None = None,
            **kw
        ):
            """View and edit text files."""
            if command == "view":
                return files.get(path, f"Error: File {path} not found")
            elif command == "create":
                files[path] = file_text or ""
                return f"Created {path}"
            elif command == "str_replace" and old_str is not None:
                if path not in files:
                    return f"Error: File {path} not found"
                files[path] = files[path].replace(old_str, new_str or "", 1)
                return f"Replaced in {path}"
            return f"Executed {command} on {path}"


        agent = create_agent(
            model=ChatAnthropic(model="claude-sonnet-4-6"),
            tools=[str_replace_based_edit_tool],  # [!code highlight]
        )

        result = agent.invoke({
            "messages": [{"role": "user", "content": "Fix the syntax error in /workspace/primes.py"}]
        })

        for message in result["messages"]:
            message.pretty_print()
        

Dict

        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(model="claude-sonnet-4-6")

        editor_tool = {"type": "text_editor_20250728", "name": "str_replace_based_edit_tool"} # [!code highlight]

        model_with_tools = model.bind_tools([editor_tool]) # [!code highlight]

        response = model_with_tools.invoke(
            "There's a syntax error in my primes.py file. Can you help me fix it?"
        )
        # You must handle execution of the text editor commands in response.tool_calls via a tool execution loop
        

使用 @[create_agent自动处理工具执行循环。

        [{'name': 'str_replace_based_edit_tool',
        'args': {'command': 'view', 'path': '/root'},
        'id': 'toolu_011BG5RbqnfBYkD8qQonS9k9',
        'type': 'tool_call'}]
        

网页获取

Claude 可以使用服务端 网页获取工具 从指定的网页和 PDF 文档中检索完整内容,并以其引用作为响应依据。

Anthropic type

        from anthropic.types.beta import BetaWebFetchTool20250910Param # [!code highlight]
        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(model="claude-haiku-4-5-20251001")

        fetch_tool = BetaWebFetchTool20250910Param( # [!code highlight]
            name="web_fetch", # [!code highlight]
            type="web_fetch_20250910", # [!code highlight]
            max_uses=3, # [!code highlight]
        ) # [!code highlight]

        model_with_tools = model.bind_tools([fetch_tool]) # [!code highlight]

        response = model_with_tools.invoke(
            "Please analyze the content at https://docs.langchain.com/"
        )
        

create_agent

        from anthropic.types.beta import BetaWebFetchTool20250910Param # [!code highlight]
        from langchain.agents import create_agent
        from langchain_anthropic import ChatAnthropic

        fetch_tool = BetaWebFetchTool20250910Param( # [!code highlight]
            name="web_fetch", # [!code highlight]
            type="web_fetch_20250910", # [!code highlight]
            max_uses=3, # [!code highlight]
        ) # [!code highlight]

        agent = create_agent(
            model=ChatAnthropic(model="claude-haiku-4-5-20251001"),
            tools=[fetch_tool],  # [!code highlight]
        )

        result = agent.invoke({
            "messages": [{"role": "user", "content": "Analyze https://docs.langchain.com/"}]
        })

        for message in result["messages"]:
            message.pretty_print()
        

Dict

        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(model="claude-haiku-4-5-20251001")

        fetch_tool = {"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 3} # [!code highlight]

        model_with_tools = model.bind_tools([fetch_tool]) # [!code highlight]

        response = model_with_tools.invoke(
            "Please analyze the content at https://docs.langchain.com/"
        )
        

网络搜索

Claude 可以使用服务端 网络搜索工具 运行搜索并以其引用作为响应依据。

Anthropic type

        from anthropic.types import WebSearchTool20260209Param # [!code highlight]
        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(model="claude-sonnet-4-6")

        search_tool = WebSearchTool20260209Param( # [!code highlight]
            name="web_search", # [!code highlight]
            type="web_search_20260209", # [!code highlight]
            max_uses=3, # [!code highlight]
        ) # [!code highlight]

        model_with_tools = model.bind_tools([search_tool]) # [!code highlight]

        response = model_with_tools.invoke("How do I update a web app to TypeScript 5.5?")
        

create_agent

        from anthropic.types import WebSearchTool20260209Param # [!code highlight]
        from langchain.agents import create_agent
        from langchain_anthropic import ChatAnthropic

        search_tool = WebSearchTool20260209Param( # [!code highlight]
            name="web_search", # [!code highlight]
            type="web_search_20260209", # [!code highlight]
            max_uses=3, # [!code highlight]
        ) # [!code highlight]

        agent = create_agent(
            model=ChatAnthropic(model="claude-sonnet-4-6"),
            tools=[search_tool],  # [!code highlight]
        )

        result = agent.invoke({
            "messages": [{"role": "user", "content": "How do I update a web app to TypeScript 5.5?"}]
        })

        for message in result["messages"]:
            message.pretty_print()
        

Dict

        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(model="claude-sonnet-4-6")

        search_tool = {"type": "web_search_20260209", "name": "web_search", "max_uses": 3} # [!code highlight]

        model_with_tools = model.bind_tools([search_tool]) # [!code highlight]

        response = model_with_tools.invoke("How do I update a web app to TypeScript 5.5?")
        

记忆工具

Claude 支持记忆工具,用于跨对话线程的客户端存储和检索上下文。参见 记忆工具文档 了解更多详情。

Anthropic type

        from typing import Literal

        from anthropic.types.beta import BetaMemoryTool20250818Param  # [!code highlight]
        from langchain_anthropic import ChatAnthropic
        from langchain.messages import HumanMessage, ToolMessage
        from langchain.tools import tool

        tool_spec = BetaMemoryTool20250818Param(  # [!code highlight]
            name="memory",  # [!code highlight]
            type="memory_20250818",  # [!code highlight]
        )  # [!code highlight]

        # Simple in-memory storage for demonstration purposes
        memory_store: dict[str, str] = {
            "/memories/interests": "User enjoys Python programming and hiking"
        }


        @tool(extras={"provider_tool_definition": tool_spec})  # [!code highlight]
        def memory(
            *,
            command: Literal["view", "create", "str_replace", "insert", "delete", "rename"],
            path: str,
            content: str | None = None,
            old_str: str | None = None,
            new_str: str | None = None,
            insert_line: int | None = None,
            new_path: str | None = None,
            **kw,
        ):
            """Manage persistent memory across conversations."""
            if command == "view":
                if path == "/memories":
                    # List all memories
                    return "\n".join(memory_store.keys()) or "No memories stored"
                return memory_store.get(path, f"No memory at {path}")
            elif command == "create":
                memory_store[path] = content or ""
                return f"Created memory at {path}"
            elif command == "str_replace" and old_str is not None:
                if path in memory_store:
                    memory_store[path] = memory_store[path].replace(old_str, new_str or "", 1)
                return f"Updated {path}"
            elif command == "delete":
                memory_store.pop(path, None)
                return f"Deleted {path}"
            # ... implement other commands
            return f"Executed {command} on {path}"


        model = ChatAnthropic(model="claude-sonnet-4-6")
        model_with_tools = model.bind_tools([memory]) # [!code highlight]

        # Initial request
        messages = [HumanMessage("What are my interests?")]
        response = model_with_tools.invoke(messages)
        print(response.content_blocks)

        # Tool execution loop
        while response.tool_calls:
            tool_messages = []
            for tool_call in response.tool_calls:
                result = memory.invoke(tool_call)
                tool_messages.append(ToolMessage(content=result, tool_call_id=tool_call["id"]))

            messages = [*messages, response, *tool_messages]
            response = model_with_tools.invoke(messages)
            print(response.content_blocks)
        
        [{'type': 'text',
        'text': "I'll check my memory to see what information I have about your interests."},
        {'type': 'tool_call',
        'name': 'memory',
        'args': {'command': 'view', 'path': '/memories'},
        'id': 'toolu_01XeP9sxx44rcZHFNqXSaKqh'}]
        

create_agent

        from typing import Literal

        from anthropic.types.beta import BetaMemoryTool20250818Param # [!code highlight]
        from langchain.agents import create_agent
        from langchain_anthropic import ChatAnthropic
        from langchain.tools import tool

        # Simple in-memory storage
        memory_store: dict[str, str] = {
            "/memories/interests": "User enjoys Python programming and hiking"
        }

        tool_spec = BetaMemoryTool20250818Param( # [!code highlight]
            name="memory", # [!code highlight]
            type="memory_20250818", # [!code highlight]
        ) # [!code highlight]


        @tool(extras={"provider_tool_definition": tool_spec}) # [!code highlight]
        def memory(
            *,
            command: Literal["view", "create", "str_replace", "insert", "delete", "rename"],
            path: str,
            content: str | None = None,
            old_str: str | None = None,
            new_str: str | None = None,
            **kw
        ):
            """Manage persistent memory across conversations."""
            if command == "view":
                if path == "/memories":
                    return "\n".join(memory_store.keys()) or "No memories stored"
                return memory_store.get(path, f"No memory at {path}")
            elif command == "create":
                memory_store[path] = content or ""
                return f"Created memory at {path}"
            elif command == "str_replace" and old_str is not None:
                if path in memory_store:
                    memory_store[path] = memory_store[path].replace(old_str, new_str or "", 1)
                return f"Updated {path}"
            elif command == "delete":
                memory_store.pop(path, None)
                return f"Deleted {path}"
            return f"Executed {command} on {path}"


        agent = create_agent(
            model=ChatAnthropic(model="claude-sonnet-4-6"),
            tools=[memory],  # [!code highlight]
        )

        result = agent.invoke({
            "messages": [{"role": "user", "content": "What are my interests?"}]
        })

        for message in result["messages"]:
            message.pretty_print()
        

使用 @[create_agent自动处理工具执行循环。

Dict

        from langchain_anthropic import ChatAnthropic

        model = ChatAnthropic(
            model="claude-sonnet-4-6",
        )
        model_with_tools = model.bind_tools([{"type": "memory_20250818", "name": "memory"}]) # [!code highlight]

        response = model_with_tools.invoke("What are my interests?")
        response.content_blocks
        # You must handle execution of the memory commands in response.tool_calls via a tool execution loop
        
        [{'type': 'text',
        'text': "I'll check my memory to see what information I have about your interests."},
        {'type': 'tool_call',
        'name': 'memory',
        'args': {'command': 'view', 'path': '/memories'},
        'id': 'toolu_01XeP9sxx44rcZHFNqXSaKqh'}]
        

工具搜索

Claude 支持服务端 工具搜索 该功能支持动态工具发现和加载。Claude 无需将所有工具定义预加载到上下文窗口中,而是可以搜索您的工具目录并仅加载所需的工具。

这在以下情况下很有用:

  • - 您的系统中有 10 个以上的工具可用
  • - 工具定义消耗了大量 token
  • - 使用大型工具集时遇到工具选择准确性问题

有两种工具搜索变体:

  • 正则表达式 (tool_search_tool_regex_20251119):Claude 构建正则表达式模式来搜索工具
  • BM25 (tool_search_tool_bm25_20251119):Claude 使用自然语言查询来搜索工具

使用 extras 参数指定 defer_loading 关于 LangChain 工具:

Anthropic type

        from anthropic.types.beta import BetaToolSearchToolRegex20251119Param # [!code highlight]
        from langchain_anthropic import ChatAnthropic
        from langchain.tools import tool

        @tool(extras={"defer_loading": True}) # [!code highlight]
        def get_weather(location: str, unit: str = "fahrenheit") -> str:
            """Get the current weather for a location.

            Args:
                location: City name
                unit: Temperature unit (celsius or fahrenheit)
            """
            return f"Weather in {location}: Sunny"

        @tool(extras={"defer_loading": True}) # [!code highlight]
        def search_files(query: str) -> str:
            """Search through files in the workspace.

            Args:
                query: Search query
            """
            return f"Found files matching '{query}'"

        model = ChatAnthropic(model="claude-sonnet-4-6")

        tool_search = BetaToolSearchToolRegex20251119Param( # [!code highlight]
            name="tool_search_tool_regex", # [!code highlight]
            type="tool_search_tool_regex_20251119", # [!code highlight]
        ) # [!code highlight]

        model_with_tools = model.bind_tools([
            tool_search, # [!code highlight]
            get_weather,
            search_files,
        ])
        response = model_with_tools.invoke("What's the weather in San Francisco?")
        

create_agent

        from anthropic.types.beta import BetaToolSearchToolRegex20251119Param # [!code highlight]
        from langchain.agents import create_agent
        from langchain_anthropic import ChatAnthropic
        from langchain.tools import tool

        tool_search = BetaToolSearchToolRegex20251119Param( # [!code highlight]
            name="tool_search_tool_regex", # [!code highlight]
            type="tool_search_tool_regex_20251119", # [!code highlight]
        ) # [!code highlight]


        @tool(extras={"defer_loading": True}) # [!code highlight]
        def get_weather(location: str, unit: str = "fahrenheit") -> str:
            """Get the current weather for a location.

            Args:
                location: City name
                unit: Temperature unit (celsius or fahrenheit)
            """
            return f"Weather in {location}: Sunny"


        @tool(extras={"defer_loading": True}) # [!code highlight]
        def search_files(query: str) -> str:
            """Search through files in the workspace.

            Args:
                query: Search query
            """
            return f"Found files matching '{query}'"


        agent = create_agent(
            model=ChatAnthropic(model="claude-sonnet-4-6"),
            tools=[
                tool_search,  # [!code highlight]
                get_weather,
                search_files,
            ],
        )

        result = agent.invoke({
            "messages": [{"role": "user", "content": "What's the weather in San Francisco?"}]
        })

        for message in result["messages"]:
            message.pretty_print()
        

Dict

        from langchain_anthropic import ChatAnthropic
        from langchain.tools import tool

        @tool(extras={"defer_loading": True})  # [!code highlight]
        def get_weather(location: str, unit: str = "fahrenheit") -> str:
            """Get the current weather for a location.

            Args:
                location: City name
                unit: Temperature unit (celsius or fahrenheit)
            """
            return f"Weather in {location}: Sunny"

        @tool(extras={"defer_loading": True})  # [!code highlight]
        def search_files(query: str) -> str:
            """Search through files in the workspace.

            Args:
                query: Search query
            """
            return f"Found files matching '{query}'"

        model = ChatAnthropic(model="claude-sonnet-4-6")

        model_with_tools = model.bind_tools([
            {"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"}, # [!code highlight]
            get_weather,
            search_files,
        ])
        response = model_with_tools.invoke("What's the weather in San Francisco?")
        
sequenceDiagram
    participant User
    participant Model
    participant ToolSearch as Tool Search
    participant Tool as get_weather

    User->>Model: "What's the weather in San Francisco?"
    Model->>ToolSearch: tool_search_tool_regex(pattern="weather")
    ToolSearch-->>Model: tool_references: [get_weather]
    Model->>Tool: get_weather(location="San Francisco")
    Tool-->>Model: Weather result
    Model->>User: Response with weather info

关键要点:

  • - 带有 defer_loading: True 的工具仅在 Claude 通过搜索发现时才加载
  • - 为获得最佳性能,请将 3-5 个最常用的工具保持为非延迟加载
  • - 两种变体都会搜索工具名称、描述、参数名称和参数描述

参见 Claude 文档 了解更多关于工具搜索的详细信息,包括与 MCP 服务器和客户端实现的配合使用。

响应元数据

ai_msg = model.invoke(messages)
ai_msg.response_metadata
{
    "id": "msg_013xU6FHEGEq76aP4RgFerVT",
    "model": "claude-sonnet-4-6",
    "stop_reason": "end_turn",
    "stop_sequence": None,
    "usage": {"input_tokens": 25, "output_tokens": 11},
}

Token 使用元数据

ai_msg = model.invoke(messages)
ai_msg.usage_metadata
{"input_tokens": 25, "output_tokens": 11, "total_tokens": 36}

包含令牌使用情况的消息块将在流式传输期间包含,由 default:

stream = model.stream_events(messages, version="v3")
full_message = stream.output
full_message.usage_metadata
{"input_tokens": 25, "output_tokens": 11, "total_tokens": 36}

可以通过设置来禁用这些 stream_usage=False 在流方法中或初始化时 ChatAnthropic.

API 参考

有关所有功能和配置选项的详细文档,请参阅 ChatAnthropic API 参考。