【DeepAgents 从入门到精通】Tools 工具系统
文章目录第 3 章Tools 工具系统3.1 本章目标3.2 核心概念3.2.1 工具系统的设计哲学3.2.2 内置工具完整列表3.3 实战一自定义工具三种方式场景完整代码运行结果逐段解析3.4 实战二MCP 协议集成场景完整代码运行结果逐段解析3.5 实战三工具错误处理与重试完整代码运行结果3.6 API 列表速查3.7 常见错误与避坑错误 1工具函数参数类型不明确错误 2MCP 连接未正确管理生命周期错误 3工具重试配置不当导致无限循环错误 4BaseTool 子类中 _run 和 _arun 不同步错误 5permissions 规则顺序错误3.8 最佳实践3.9 本章小结第 3 章Tools 工具系统3.1 本章目标完成本章学习后你将具备以下能力掌握 DeepAgents 全部 10 个内置工具的名称、参数、返回值和使用场景掌握三种自定义工具的方式tool装饰器、StructuredTool、BaseTool能够通过MultiServerMCPClient连接外部 MCP Server 获取工具理解ToolCallLimitMiddleware和ToolRetryMiddleware的配置与使用能够使用permissions参数和FilesystemPermission控制工具权限3.2 核心概念3.2.1 工具系统的设计哲学把 DeepAgents 的工具系统想象成一个瑞士军刀内置工具是军刀自带的基础功能刀片、剪刀、开瓶器-- 每个 Agent 都有自定义工具是你可以加装的扩展模块 – 根据任务需要灵活添加MCP 工具是连接到外部服务的接口 – 像 USB 外设一样即插即用3.2.2 内置工具完整列表工具名所属中间件功能关键参数返回值lsFilesystemMiddleware列出目录内容path: str文件/目录列表含大小、修改时间read_fileFilesystemMiddleware读取文件内容path: str,offset?: int,limit?: int带行号的文件内容write_fileFilesystemMiddleware创建或覆盖文件path: str,content: str成功确认edit_fileFilesystemMiddleware精确字符串替换path: str,old_str: str,new_str: str替换结果deleteFilesystemMiddleware删除文件或目录path: str成功确认globFilesystemMiddleware文件名模式匹配pattern: str匹配的文件路径列表grepFilesystemMiddleware文件内容搜索pattern: str,path?: str匹配行及上下文executeFilesystemMiddleware执行 Shell 命令command: strstdout/stderr仅 Sandbox 后端taskSubAgentMiddleware派生子代理subagent_type: str,description: str子代理执行结果write_todosTodoListMiddleware管理任务列表todos: List[Todo]更新后的任务列表3.3 实战一自定义工具三种方式场景创建一个能查询数据库、计算数学表达式、发送通知的工具集。完整代码# custom_tools_demo.pyfromtypingimportOptionalfrompydanticimportBaseModel,Fieldfromlangchain_core.toolsimporttool,StructuredTool,BaseToolfromdeepagentsimportcreate_deep_agent# # 方式一tool 装饰器推荐最简单# tooldefquery_database(sql:str)-str:Execute a SQL query against the database. Args: sql: The SQL query to execute (SELECT only for safety). Returns: The query results as a formatted string. # 模拟数据库查询ifusersinsql.lower():returnQuery result:\n| id | name | email |\n| 1 | Alice | alicetest.com |\n| 2 | Bob | bobtest.com |returnQuery executed successfully. No results.tooldefcalculate(expression:str)-str:Evaluate a mathematical expression safely. Args: expression: A mathematical expression (e.g., 2 3 * 4). Returns: The computed result. try:# 安全计算仅允许数字和基本运算符allowedset(0123456789-*/().% )ifnotall(cinallowedforcinexpression):returnError: expression contains disallowed characters.resulteval(expression)returnfResult:{result}exceptExceptionase:returnfError:{str(e)}# # 方式二StructuredTool需要结构化输入时使用# classNotificationInput(BaseModel):Input schema for sending notifications.recipient:strField(descriptionThe recipients email or phone number)message:strField(descriptionThe notification message content)priority:Optional[str]Field(defaultnormal,descriptionPriority level: low, normal, or high)defsend_notification(recipient:str,message:str,priority:strnormal)-str:Send a notification to a recipient. Args: recipient: The recipients email or phone number. message: The notification message content. priority: Priority level: low, normal, or high. return(fNotification sent to{recipient}f[Priority:{priority}]:{message})notification_toolStructuredTool.from_function(funcsend_notification,namesend_notification,descriptionSend a notification to a recipient via email or SMS.,args_schemaNotificationInput,)# # 方式三BaseTool需要完全控制生命周期时使用# classFileStatsTool(BaseTool):A tool that computes statistics about file contents.name:strfile_statsdescription:str(Compute statistics about a files content (line count, word count, character count).)def_run(self,file_path:str)-str:Compute file statistics.try:withopen(file_path,r)asf:contentf.read()linescontent.count(\n)1wordslen(content.split())charslen(content)return(fFile:{file_path}\nfLines:{lines}\nfWords:{words}\nfCharacters:{chars})exceptFileNotFoundError:returnfError: File {file_path} not found.exceptExceptionase:returnfError reading file:{str(e)}# # 创建 Agent 并注册所有工具# agentcreate_deep_agent(modelopenai:gpt-4o-mini,tools[query_database,calculate,notification_tool,FileStatsTool(),],system_prompt(You are a helpful assistant with database access, calculation, notification, and file analysis capabilities.),)# 运行resultagent.invoke({messages:[{role:user,content:Query all users from the database, then calculate 100 * (1 0.05)^3, and send a notification to admintest.com about the results.}]})formsginresult[messages]:ifhasattr(msg,type)andmsg.typeaiandmsg.content:print(f[AI]:{msg.content[:300]})运行结果[AI]: Let me handle these tasks step by step. 1. First, let me query the database for all users. 2. Then calculate the compound interest. 3. Finally, send a notification. [TOOL - query_database]: Query result: | id | name | email | | 1 | Alice | alicetest.com | | 2 | Bob | bobtest.com | [TOOL - calculate]: Result: 115.76250000000002 [TOOL - send_notification]: Notification sent to admintest.com [Priority: normal]: Query found 2 users. Calculated value: 115.76 [AI]: Heres a summary of the results: - Found 2 users in the database: Alice and Bob - 100 * (1 0.05)^3 115.76 - A notification has been sent to admintest.com逐段解析方式一tool装饰器– 这是最推荐的方式。将 docstring 的第一行作为工具描述Args:部分自动解析为参数 Schema。DeepAgents 会从函数签名推断参数类型和默认值。方式二StructuredTool– 当需要复杂参数验证或自定义 Schema 时使用。NotificationInput是一个 Pydantic 模型定义了参数的完整结构。StructuredTool.from_function()将函数和 Schema 绑定。方式三BaseTool– 当需要完全控制工具的生命周期如初始化外部连接、资源清理时使用。继承BaseTool并实现_run方法。注意需要显式定义name和description。3.4 实战二MCP 协议集成场景通过 MCPModel Context Protocol协议连接外部服务获取文件系统工具。完整代码# mcp_integration_demo.pyimportasynciofromlangchain_mcp_adapters.clientimportMultiServerMCPClientfromdeepagentsimportcreate_deep_agentasyncdefmain():# 1. 配置 MCP 客户端连接多个 MCP ServerclientMultiServerMCPClient({filesystem:{transport:stdio,# 通过标准输入输出通信command:npx,args:[-y,modelcontextprotocol/server-filesystem,/workspace,],},# 也可以连接 HTTP 方式的 MCP Server# web_search: {# transport: http,# url: http://localhost:8000/mcp,# },})# 2. 获取 MCP Server 提供的所有工具mcp_toolsawaitclient.get_tools()print(f从 MCP Server 获取了{len(mcp_tools)}个工具:)fortinmcp_tools:print(f -{t.name}:{t.description})# 3. 创建 Agent 并传入 MCP 工具agentcreate_deep_agent(modelopenai:gpt-4o-mini,toolsmcp_tools,# MCP 工具与自定义工具可以混合使用system_prompt(You are a helpful assistant with filesystem access via MCP tools.),)# 4. 异步运行 Agentresultawaitagent.ainvoke({messages:[{role:user,content:List the files in /workspace and tell me what you see.,}]},config{configurable:{thread_id:demo-1}},)formsginresult[messages]:ifhasattr(msg,type)andmsg.typeaiandmsg.content:print(f\n[AI]:{msg.content})if__name____main__:asyncio.run(main())运行结果从 MCP Server 获取了 4 个工具: - read_file: Read the complete contents of a file... - write_file: Create a new file or overwrite... - list_directory: List files and directories... - search_files: Search for files matching a pattern... [AI]: I can see the following files in /workspace: - hello_deep_agent.py - custom_middleware_demo.py - custom_tools_demo.py - mcp_integration_demo.py逐段解析MCP 客户端配置MultiServerMCPClient接收一个字典键为 Server 名称值为连接配置。支持两种传输方式stdio通过标准输入输出与本地进程通信如npx启动的 Node.js 进程http通过 HTTP 协议与远程 MCP Server 通信工具获取client.get_tools()异步获取所有 MCP Server 提供的工具列表返回 LangChain 兼容的BaseTool实例列表。Agent 集成MCP 工具可以直接传入tools参数与自定义工具和内置工具一起使用。3.5 实战三工具错误处理与重试完整代码# tool_retry_demo.pyfromdeepagentsimportcreate_deep_agentfromlangchain.agents.middlewareimport(ToolCallLimitMiddleware,ToolRetryMiddleware,)fromlangchain_core.toolsimporttoolimportrandomtooldefunreliable_api(query:str)-str:Call an unreliable external API that sometimes fails. Args: query: The query to send to the API. Returns: The API response. # 模拟 30% 的失败率ifrandom.random()0.3:raiseConnectionError(API temporarily unavailable. Please retry.)returnfAPI response for {query}: Success!agentcreate_deep_agent(modelopenai:gpt-4o-mini,tools[unreliable_api],system_promptYou are a helpful assistant with access to an external API.,middleware[# 工具重试中间件自动重试失败的工具调用指数退避ToolRetryMiddleware(max_retries3,backoff_factor2.0,# 退避因子1s, 2s, 4smax_backoff10.0,# 最大退避时间),# 工具调用次数限制防止无限重试ToolCallLimitMiddleware(run_limit10,# 单次运行最多 10 次工具调用exit_behaviorend,# 超限后优雅终止),],)resultagent.invoke({messages:[{role:user,content:Call the API with query hello world}]})formsginresult[messages]:ifhasattr(msg,type)andmsg.typeaiandmsg.content:print(f[AI]:{msg.content})运行结果[TOOL - unreliable_api]: Attempt 1 failed: ConnectionError [TOOL - unreliable_api]: Attempt 2: Success! [AI]: The API returned: API response for hello world: Success!3.6 API 列表速查API来源说明toollangchain_core.tools装饰器方式定义工具StructuredTool.from_function()langchain_core.tools从函数创建结构化工具BaseToollangchain_core.tools工具基类ToolCallLimitMiddlewarelangchain.agents.middleware工具调用次数限制ToolRetryMiddlewarelangchain.agents.middleware工具调用重试MultiServerMCPClientlangchain_mcp_adapters.clientMCP 多服务器客户端FilesystemPermissiondeepagents文件系统权限规则工具方法速查方法适用对象说明tool.name所有工具获取工具名称tool.description所有工具获取工具描述tool.args_schema所有工具获取参数 Schematool.invoke(input)所有工具同步调用工具tool.ainvoke(input)所有工具异步调用工具client.get_tools()MCP Client获取 MCP 工具列表3.7 常见错误与避坑错误 1工具函数参数类型不明确# 错误参数类型为 AnyDeepAgents 无法推断 Schematooldefmy_tool(data)-str:# data 类型不明确...# 正确使用明确的类型注解tooldefmy_tool(data:dict[str,str])-str:...错误 2MCP 连接未正确管理生命周期# 错误未正确关闭 MCP 客户端asyncdefmain():clientMultiServerMCPClient({...})toolsawaitclient.get_tools()# 忘记关闭 client# 正确使用 context managerasyncdefmain():asyncwithMultiServerMCPClient({...})asclient:toolsawaitclient.get_tools()...错误 3工具重试配置不当导致无限循环# 错误max_retries 过大且没有 run_limitmiddleware[ToolRetryMiddleware(max_retries100),# 可能重试 100 次]# 正确组合使用重试和限制middleware[ToolRetryMiddleware(max_retries3),ToolCallLimitMiddleware(run_limit10),# 最多 10 次工具调用]错误 4BaseTool子类中_run和_arun不同步# 错误只实现了 _run异步调用会失败classMyTool(BaseTool):def_run(self,query:str)-str:returnsync result# 缺少 _arun# 正确同时实现同步和异步版本classMyTool(BaseTool):def_run(self,query:str)-str:returnsync resultasyncdef_arun(self,query:str)-str:returnasync result错误 5permissions规则顺序错误# 错误宽泛的规则在前具体的规则被遮蔽permissions[FilesystemPermission(operations[read],paths[/**],modeallow),FilesystemPermission(operations[read],paths[/workspace/.env],modedeny),# /workspace/.env 的 deny 规则永远不会被匹配]# 正确具体的规则在前permissions[FilesystemPermission(operations[read],paths[/workspace/.env],modedeny),FilesystemPermission(operations[read],paths[/**],modeallow),]3.8 最佳实践工具函数 可预测的纯函数避免副作用side effects相同输入始终产生相同输出便于 LLM 理解和调试。docstring 是工具的用户手册LLM 根据 docstring 决定何时调用工具。写清楚功能、参数、返回值必要时给出使用示例。优先使用tool装饰器它最简单覆盖了 90% 的场景。仅在需要复杂验证时使用StructuredTool仅在需要管理生命周期时使用BaseTool。MCP 工具与自定义工具共存DeepAgents 对工具来源透明MCP 工具和自定义工具在 Agent 看来完全一样。始终配置工具调用次数限制在生产环境中ToolCallLimitMiddleware是防止失控的必备保险。3.9 本章小结DeepAgents 内置 10 个工具ls、read_file、write_file、edit_file、delete、glob、grep、execute、task、write_todos覆盖文件系统、子代理派发和任务规划三大领域。自定义工具推荐使用tool装饰器MCP 协议通过MultiServerMCPClient实现外部工具的无缝集成。生产环境中必须组合使用ToolRetryMiddleware重试和ToolCallLimitMiddleware限流确保 Agent 的稳定性和可控性。