本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
使用工具完成 Amazon Bedrock 模型响应
您可以使用 Amazon Bedrock API 向模型授予访问一些工具的权限,这些工具可以帮助模型针对您发送给模型的消息生成响应。例如,您可能有一个聊天应用程序,支持用户查询某个电台播放的最受欢迎的歌曲。要回答关于最受欢迎的歌曲的请求,模型需要使用一个可以查询并返回歌曲信息的工具。
注意
现在,您可以使用工具使用结构化输出。有关更多信息,请参阅从模型中获取经过验证的 JSON 结果。
在 Amazon Bedrock 中,模型不会直接调用工具。相反,当您向模型发送消息时,您还需要提供一个或多个可能帮助模型生成响应的工具的定义。在这个示例中,您需要提供一个工具的定义,该工具可以返回指定电台上最受欢迎的歌曲。如果模型确定需要该工具来生成对消息的响应,则根据用于调用模型的 API,模型可以执行客户端调用,也可以让 Bedrock 使用服务器端工具调用该工具。让我们更详细地讨论这两个选项。
客户端工具调用
如果您使用响应 API、聊天完成 API、Converse API 或 InvokeModel API 来发送请求,则模型将使用客户端工具调用。这意味着在您的代码中,您可以代表模型调用该工具。在这个场景中,假设工具实现是一个 API。该工具也可以是数据库、Lambda 函数或其他软件。您可以决定如何实现工具。然后,您可以继续与模型进行对话,并提供包含工具结果的消息。最后,模型会为原始消息生成响应,其中包括您发送给模型的工具结果。
让我们定义将用于工具使用的工具。以下 Python 示例展示了如何使用在虚构的广播电台返回最受欢迎的歌曲的工具。
def get_most_popular_song(station_name: str) -> str: stations = { "Radio Free Mars": "Starman – David Bowie", "Neo Tokyo FM": "Plastic Love – Mariya Takeuchi", "Cloud Nine Radio": "Blinding Lights – The Weeknd", } return stations.get(station_name, "Unknown Station – No chart data available")
将响应 API 用于客户端工具
你可以使用 OpenAI 提供的函数调用
from openai import OpenAI import json client = OpenAI() response = client.responses.create( model="oss-gpt-120b", input="What is the most popular song on Radio Free Mars?", tools=[ { "type": "function", "name": "get_most_popular_song", "description": "Returns the most popular song on a radio station", "parameters": { "type": "object", "properties": { "station_name": { "type": "string", "description": "Name of the radio station" } }, "required": ["station_name"] } } ] ) if response.output and response.output[0].content: tool_call = response.output[0].content[0] args = json.loads(tool_call["arguments"]) result = get_most_popular_song(args["station_name"]) final_response = client.responses.create( model="oss-gpt-120b", input=[ { "role": "tool", "tool_call_id": tool_call["id"], "content": result } ] ) print(final_response.output_text)
将 “聊天完成” API 用于客户端工具
您也可以使用 “聊天完成” API。以下是使用聊天完成的 Python 代码:
from openai import OpenAI import json client = OpenAI() completion = client.chat.completions.create( model="oss-gpt-120b", messages=[{"role": "user", "content": "What is the most popular song on Neo Tokyo FM?"}], tools=[{ "type": "function", "function": { "name": "get_most_popular_song", "description": "Returns the most popular song on a radio station", "parameters": { "type": "object", "properties": { "station_name": {"type": "string", "description": "Name of the radio station"} }, "required": ["station_name"] } } }] ) message = completion.choices[0].message if message.tool_calls: tool_call = message.tool_calls[0] args = json.loads(tool_call.function.arguments) result = get_most_popular_song(args["station_name"]) followup = client.chat.completions.create( model="oss-gpt-120b", messages=[ {"role": "user", "content": "What is the most popular song on Neo Tokyo FM?"}, message, {"role": "tool", "tool_call_id": tool_call.id, "content": result} ] ) print(followup.choices[0].message.content)
有关在响应中使用函数调用 API 和聊天完成 API 的更多详细信息,请参阅 OpenAI 中的函数调用
将 Converse API 用于客户端工具
您可以通过 Converse API 让模型在对话中使用工具。以下 Python 示例展示了如何使用在虚构的广播电台返回最受欢迎的歌曲的工具。
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 """Shows how to use tools with the Converse API and the Cohere Command R model.""" import logging import json import boto3 from botocore.exceptions import ClientError class StationNotFoundError(Exception): """Raised when a radio station isn't found.""" pass logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO) def get_top_song(call_sign): """Returns the most popular song for the requested station. Args: call_sign (str): The call sign for the station for which you want the most popular song. Returns: response (json): The most popular song and artist. """ song = "" artist = "" if call_sign == 'WZPZ': song = "Elemental Hotel" artist = "8 Storey Hike" else: raise StationNotFoundError(f"Station {call_sign} not found.") return song, artist def generate_text(bedrock_client, model_id, tool_config, input_text): """Generates text using the supplied Amazon Bedrock model. If necessary, the function handles tool use requests and sends the result to the model. Args: bedrock_client: The Boto3 Bedrock runtime client. model_id (str): The Amazon Bedrock model ID. tool_config (dict): The tool configuration. input_text (str): The input text. Returns: Nothing. """ logger.info("Generating text with model %s", model_id) # Create the initial message from the user input. messages = [{"role": "user", "content": [{"text": input_text}]}] response = bedrock_client.converse(modelId=model_id, messages=messages, toolConfig=tool_config) output_message = response['output']['message'] messages.append(output_message) stop_reason = response['stopReason'] if stop_reason == 'tool_use': # Tool use requested. Call the tool and send the result to the model. tool_requests = response['output']['message']['content'] for tool_request in tool_requests: if 'toolUse' in tool_request: tool = tool_request['toolUse'] logger.info("Requesting tool %s. Request: %s", tool['name'], tool['toolUseId']) if tool['name'] == 'top_song': tool_result = {} try: song, artist = get_top_song(tool['input']['sign']) tool_result = {"toolUseId": tool['toolUseId'], "content": [{"json": {"song": song, "artist": artist}}]} except StationNotFoundError as err: tool_result = {"toolUseId": tool['toolUseId'], "content": [{"text": err.args[0]}], "status": 'error'} tool_result_message = {"role": "user", "content": [{"toolResult": tool_result}]} messages.append(tool_result_message) # Send the tool result to the model. response = bedrock_client.converse(modelId=model_id, messages=messages, toolConfig=tool_config) output_message = response['output']['message'] # print the final response from the model. for content in output_message['content']: print(json.dumps(content, indent=4)) def main(): """Entrypoint for tool use example.""" logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") model_id = "cohere.command-r-v1:0" input_text = "What is the most popular song on WZPZ?" tool_config = { "tools": [ { "toolSpec": { "name": "top_song", "description": "Get the most popular song played on a radio station.", "inputSchema": { "json": { "type": "object", "properties": { "sign": { "type": "string", "description": "The call sign for the radio station for which you want the most popular song. Example calls signs are WZPZ, and WKRP." } }, "required": ["sign"] } } } } ] } bedrock_client = boto3.client(service_name='bedrock-runtime') try: print(f"Question: {input_text}") generate_text(bedrock_client, model_id, tool_config, input_text) except ClientError as err: message = err.response['Error']['Message'] logger.error("A client error occurred: %s", message) print(f"A client error occured: {message}") else: print(f"Finished generating text with model {model_id}.") if __name__ == "__main__": main()
使用 Invoke APIs 进行客户端工具使用
可以将工具与基本推理运算(InvokeModel或 InvokeModelWithResponseStream)一起使用。要查找您在请求正文中传递的推理参数,请参阅您要使用的模型的推理参数。
服务器端工具调用
如果您使用 Responses API 来调用模型,那么除了我们之前讨论的客户端工具调用之外,它还可以使用服务器端工具调用。服务器端工具调用是一种机制,在这种机制中,工具(APIs、函数、工作流程)是在可信的后端环境中执行的,而不是在客户端上执行的。这提高了应用程序的安全性、可靠性和治理状况。在 Amazon Bedrock 执行实现工具使用的 Lambda 函数之前,它会确保 Lambda 函数与调用该函数的应用程序具有相同的 IAM 策略。由于 Amazon Bedrock 推动工具的执行,客户可以专注于实现其业务逻辑,而不是添加工具功能。Amazon Bedrock 还支持最高的治理标准,例如符合 ISO、SOC 和 HIPAA 资格。客户可以提交自己的自定义 Lambda 函数来运行该工具,也可以使用现有的预定义工具,例如备注和任务。使用 Responses API 的服务器端工具从 OpenAI 的 GPT OSS 20B/120B 型号开始,其他模型的支持即将推出。您可以使用模型 API 来发现可用于响应 API 的可用模型。有关响应 API 的更多详细信息,请参阅使用 Open APIs AI 生成响应。
您可以在 Amazon Bedrock 上使用两种类型的工具:使用 Lambda 的自定义工具或 Bedrock 支持的预定义工具。在本节中,我们将介绍如何使用响应 API 创建自定义 Lambda 工具。让我们详细讨论两者。
在响应 API 中使用 Lambda 的自定义工具
通过在 Bedrock 中将 Lambda 函数用作自定义工具,您可以通过将自定义 AWS Lambda 函数集成为工具来扩展代理的功能。这使您能够创建无服务器、可扩展的工具,AI 助手和其他应用程序可以通过模型上下文协议 (MCP) 调用这些工具。以下是此功能的优点:
扩展功能:添加自定义业务逻辑、API 集成或数据处理功能。
安全运行工具:Lambda 允许工具访问 VPC 内的资源,而无需授予完整的 VPC 访问权限。
无服务器架构:无需基础设施管理,Lambda 会自动处理扩展。
成本效益:仅为执行时间付费,不为闲置资源付费。
易于集成:Lambda 函数与内置工具无缝显示。
要让 Amazon Bedrock 中的模型使用工具完成对消息的响应,您需要将消息以及一个或多个工具的定义发送给模型。根据应用程序的提示,如果模型确定其中一个工具可以帮助生成响应,则它会返回请求 Bedrock 使用该工具并将工具结果发送回模型。然后,模型会使用这些结果生成对原始消息的响应。
以下步骤展示了如何使用带有响应 API 的工具。
工作原理
Lambda 函数:创建实现 MCP 协议的 Lambda 函数
工具发现:Bedrock 调用你的 Lambda 函数来发现可用的工具
工具注册:您的工具已在 Bedrock 中注册
工具执行:当代理请求您的工具时,Bedrock 会调用您的 Lambda 函数
响应处理:结果通过标准接口返回给代理
第 1 步:定义 Lambda 函数以获取最受欢迎的歌曲
创建一个实现 MCP 协议的 Lambda 函数。下面是一个简单的 Python 示例:
import json def lambda_handler(event, context): # Parse JSON-RPC request method = event.get('method') params = event.get('params', {}) request_id = event.get('id') if method == 'tools/list': return { "jsonrpc": "2.0", "id": request_id, "result": { "tools": [ { "name": "my_custom_tool", "description": "My custom business logic tool", "inputSchema": { "type": "object", "properties": { "input": { "type": "string", "description": "Input text to process" } }, "required": ["input"] } } ] } } elif method == 'tools/call': tool_name = params.get('name') arguments = params.get('arguments', {}) if tool_name == 'my_custom_tool': # Your custom logic here result = f"Processed: {arguments.get('input', '')}" return { "jsonrpc": "2.0", "id": request_id, "result": { "content": [ { "type": "text", "text": result } ] } } # Error response for unsupported methods return { "jsonrpc": "2.0", "id": request_id, "error": { "code": -32601, "message": "Method not found" } }
步骤 2:部署 Lambda 函数
接下来,使用您的 IAM 角色部署此 Lambda 函数以获取 ARN。您可以在此处阅读有关部署 Lambda 函数的更多信息。
# Example using AWS CLI aws lambda create-function \ --function-name my-custom-tool \ --runtime python3.14 \ --role arn:aws:iam::YOUR-ACCOUNT:role/lambda-execution-role \ --handler lambda_function.lambda_handler \ --zip-file fileb://function.zip
假设你的 ARN 是:arn:aws:lambda:us-west-2:123456789012:function:my-custom-tool
第 3 步:在推理请求中定义消息和工具定义
要发送消息和工具定义,您可以使用响应 API 操作。Amazon Bedrock 使用响应 API 的连接器和远程 MCP 服务器功能connector_id字段中,您可以传入您在上一步中创建的 Lambda ARN。您无需提供授权证书,因为 Bedrock 使用与调用模型的应用程序相同的 IAM 角色和策略。以下是一个工具的示例架构,该工具可以获取电台播放的最受欢迎的歌曲。
from openai import OpenAI client = OpenAI() resp = client.responses.create( model="oss-gpt-120b", tools=[ { "type": "mcp", "server_label": "xamzn_arn", "connector_id": "arn:aws:lambda:us-west-2:123456789012:function:my-custom-tool", "require_approval": "never", }, ], input="My custom prompt.", ) print(resp.output_text)
第 4 步:Bedrock 调用该工具并将响应传回模型
支持响应 API
当您在tools参数中指定 Lambda 函数时,API 将尝试从服务器获取工具列表。如果成功检索工具列表,则模型响应mcp_list_tools输出中将出现一个新的输出项目。此对象的tools属性将显示成功导入的工具。一旦模型可以访问这些工具定义,它就可以根据模型的上下文选择调用它们。当模型决定调用 Lambda 工具时,API 将向 Lambda 函数发出请求,要求其调用该工具,并将其输出放入模型的上下文中。你可以在 OpenAI
{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32000, "message": "Tool execution failed", "data": "Additional error details" } }
在响应 API 中使用 AWS 提供的工具
Bedrock 中提供了两个 AWS 提供的工具:记笔记功能(笔记工具)和任务管理(任务工具)。让我们详细介绍一下这两个。
备注工具概述
该notes工具允许您在同一个对话会话中存储和检索键值对。这提供了一种简单的记忆机制,用于维护多个交互的上下文。密钥是区分大小写的字符串,对密钥长度或命名约定没有限制。系统会覆盖同一个密钥的先前值。值存储为字符串(JSON URLs 等),并且在工具级别没有大小限制。价值观在整个对话会话中都保持不变。记忆仅限于当前对话。
参数
| 参数 | Type | 必需 | 描述 |
|---|---|---|---|
operation |
字符串 | 是 | 要执行的操作:"store"或 "recall" |
key |
字符串 | 是 | 内存项目的密钥标识符 |
value |
字符串 | 有条件 | 要存储的值(仅在"store"操作时才需要) |
有效操作
store: 将键值对保存到内存recall: 通过键检索值
你可以使用任何一种自然语言(例如 “记住我最喜欢的颜色是蓝色”、“关于我最喜欢的颜色,我跟你说了什么?” ,“存储我更喜欢早间会议的事实”、“回想一下我所说的关于会议偏好的话”),或者你可以在提示中使用直接工具呼叫(“使用备忘工具将我的电子邮件存储为 john@example.com”,“查看备忘录中的电子邮件地址”)。
任务工具概述
该tasks工具提供了一个 Last-In-First-Out(LIFO)堆栈,用于管理对话会话中的任务。这使您可以将任务推送到堆栈上,然后以相反的顺序弹出它们,非常适合管理嵌套工作流程、临时提醒或分层任务管理。任务会持续到整个对话会话中。堆栈状态在多次交互中保持不变。记忆仅限于当前对话。
| 参数 | Type | 必需 | 描述 |
|---|---|---|---|
operation |
字符串 | 是 | 要执行的操作:"push"或 "pop" |
description |
字符串 | 有条件 | 任务项的描述(仅在"push"操作时为必填项) |
summary |
字符串 | 否 | 有关任务项的可选摘要(仅用于"push"操作) |
你可以使用自然语言调用任务工具(例如 “添加任务以查看预算”、“推送提醒给客户打电话”、“我需要做的下一个任务是什么?”) ,“弹出最新的任务”、“从我的堆栈中获取最新任务”),或者你可以直接在提示中调用该工具(“使用任务工具推送'完成演示文稿'”、“从堆栈中弹出任务”、“将'安排会议'添加到我的任务列表”)。
服务器端工具使用与 Gateway 集成 AgentCore
Amazon Bedrock 现在支持 AgentCore Gateway 作为调用集成类型的服务器端工具。此功能允许您将模型直接连接到 AgentCore 网关端点,从而实现对通过网关基础设施管理的工具的无缝访问。
AgentCore 网关集成遵循与 Lambda 函数集成的相同模式,但有一个关键区别。
Lambda 集成:
使用 Lambda 函数 ARNs
直接调用 AWS Lambda 函数
AgentCore 网关集成:
使用 AgentCore 网关 ARNs
通过 AgentCore 网关基础设施路由工具呼叫
提供集中式工具管理和发现
配置
请求结构
将 AgentCore Gateway 配置为工具源时,请在响应 API 请求中使用tools数组中的以下结构。
{ "type":"mcp", "server_label":"agentcore_tools", "connector_id":"arn:aws:bedrock-agentcore:us-west-2:342789630635:gateway/agentcore-intro-gateway-v2-swvq44sovp", "server_description":"AgentCore Gateway providing custom tools", "require_approval":"never" }
参数
| 参数 | Type | 必需 | 描述 |
|---|---|---|---|
type |
字符串 | 是 | 必须设置为 mcp |
server_label |
字符串 | 是 | 您的请求中此工具连接器的唯一标识符 |
connector_id |
字符串 | 是 | 您的网关的 ARN AgentCore |
server_description |
字符串 | 否 | 该网关提供的工具的可读描述 |
require_approval |
字符串 | 是 | 字段必须是 "never" |
完整请求示例
{ "model":"openai.gpt-oss-120b", "stream":true, "background":false, "store":false, "tools": [ { "type":"mcp", "server_label":"agentcore_tools", "connector_id":"arn:aws:bedrock-agentcore:us-west-2:342789630635:gateway/agentcore-intro-gateway-v2-swvq44sovp", "server_description":"AgentCore Gateway providing custom tools", "require_approval":"never" } ], "input": [ { "type":"message", "role":"user", "content": [ { "type":"input_text", "text":"What is the weather in Seattle?" } ] } ] }
先决条件
在使用 AgentCore 网关集成之前,请确保您已具备以下条件:
使用已配置@@ 的 AgentCore 目标(Lambda 函数、API 网关阶段、OpenAPI 架构或 MCP 服务器)创建了网关
已配置 IAM 权限,允许您的 Bedrock 服务角色调用网关。请注意,Bedrock 仅支持采用 IAM 身份验证的网关。
格式正确的 Gateway ARN
AgentCore 网关集成的好处
集中式工具管理:通过单个网关端点管理所有工具
工具发现:代理可以通过网关动态发现可用工具
安全:通过 IAM 和网关策略进行内置身份验证和授权
可观察性:全面监控和记录工具调用
灵活性:支持多种目标类型(Lambda、API Gateway、OpenAPI、MCP 服务器)
IAM 权限
你的 Bedrock 执行角色需要权限才能调用 AgentCore 网关:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "bedrock-agentcore:InvokeGateway" ], "Resource": "arn:aws:bedrock-agentcore:us-west-2:342789630635:gateway/agentcore-intro-gateway-v2-swvq44sovp" } ] }
后续步骤
了解有关创建 AgentCore 网关的更多信息
探索网关目标类型
查看网关安全最佳实践