news 2026/5/15 16:19:21

Claude智能体开发实战:从工具调用到安全架构设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Claude智能体开发实战:从工具调用到安全架构设计

1. 项目概述:一个为Claude模型设计的“坏小子”技能集

最近在AI应用开发圈里,一个名为terryso/claude-bmad-skills的项目引起了我的注意。乍一看这个标题,可能会让人有点摸不着头脑——“bmad”是什么?Claude模型还需要“技能”?这和我们平时用的API调用有什么不同?作为一个在AI集成和自动化领域摸爬滚打了十多年的老手,我立刻意识到,这绝不是一个简单的代码库,它背后反映的是当前AI应用开发中一个非常核心且有趣的趋势:如何让大型语言模型(LLM)从“什么都知道”的百科全书,变成“什么都能干”的实干家

简单来说,claude-bmad-skills是一个专门为Anthropic公司的Claude模型设计的“技能”(Skills)集合。这里的“技能”不是指模型本身的能力,而是指一系列预定义的、可复用的函数或工具,Claude可以通过调用这些技能来执行超出其纯文本生成范围的实际操作。例如,让Claude帮你查天气、发邮件、操作数据库,甚至是控制智能家居。而“bmad”这个略显戏谑的缩写,据我推测,很可能代表了“Bad Motherf*cker's Automated Doer”(或者类似含义),意在强调这套技能集旨在让Claude变得极其能干、甚至有点“叛逆”地自动化处理各种任务,而不仅仅是礼貌地回答你的问题。

这个项目非常适合三类人:一是希望将Claude深度集成到自己产品或工作流中的开发者;二是热衷于探索AI Agent(智能体)和自动化可能性的技术爱好者;三是那些厌倦了手动重复操作,希望用一个“超级助手”来解放双手的极客。接下来,我将从设计思路、核心实现、实战应用和避坑指南四个维度,为你彻底拆解这个项目,让你不仅能理解它是什么,更能掌握如何用它来打造属于你自己的“全能Claude”。

2. 核心架构与设计哲学解析

2.1 从“聊天机器人”到“智能体执行层”的范式转变

要理解claude-bmad-skills的价值,首先要跳出“Claude是一个聊天AI”的固有认知。传统的用法是:你提问,它生成一段看似合理的文本回复。但bmad-skills引入了一种新的范式:Claude作为决策大脑,技能集作为可执行的手脚

在这种架构下,你和Claude的对话变成了“任务指令”。Claude会分析你的自然语言指令,判断是否需要调用某个技能,以及调用时应该传入什么参数。然后,它通过一个标准的接口(通常是函数调用,Function Calling)去触发后端真正的代码逻辑。执行完毕后,技能将结果返回给Claude,Claude再组织成自然语言回复给你。这个过程,实际上构建了一个最简单的智能体(Agent)循环:感知(理解你的指令)-> 规划(决定调用哪个技能)-> 行动(执行技能)-> 观察(获取结果)-> 再规划/回复。

bmad-skills项目的核心贡献,就在于它预先定义并实现好了这个“行动”层里的一系列常用工具。开发者不需要从零开始为每一个想自动化的功能编写对接Claude的胶水代码,而是可以直接复用或参考这些已经封装好的技能。

2.2 技能集的设计原则与分类

浏览项目的技能列表(如果项目结构清晰),我们可以推断出其设计遵循了几个关键原则:

  1. 原子性与复用性:每个技能应该只做好一件事。比如,“发送邮件”是一个技能,“搜索网络”是另一个技能。这样的设计保证了技能可以像乐高积木一样被灵活组合。Claude可以先后调用“搜索”和“发邮件”两个技能来完成“查一下明天天气并邮件提醒我”的复杂指令。
  2. 安全性前置:任何能执行外部操作(尤其是写操作)的技能都必须内置安全边界。例如,一个“执行Shell命令”的技能是极其强大但也极其危险的。一个负责任的设计会包含沙箱环境、命令白名单、用户确认机制等。bmad这个代号可能暗示它在提供强大能力的同时,也要求使用者明确知晓风险。
  3. 上下文感知:技能应该能够从对话上下文中自动提取参数。比如,当用户说“把刚才我们讨论的要点总结一下发邮件给我”时,“发邮件”技能需要能自动获取到“刚才讨论的要点”这个上下文内容作为邮件正文。
  4. 标准化接口:所有技能都通过统一的格式(如OpenAI的tools格式或Anthropic的tool_use块)暴露给Claude。这包括技能的名称、描述、参数列表(JSON Schema)。清晰的描述至关重要,因为Claude完全依赖这些文本来理解何时以及如何使用该技能。

基于这些原则,技能集大致可以分为以下几类:

  • 信息获取类:如search_web(网络搜索)、get_weather(获取天气)、fetch_stock_price(获取股价)。这些技能扩展了模型的知识实时性。
  • 系统交互类:如execute_command(执行命令)、read_filewrite_file。这类技能让Claude具备了操作本地或服务器环境的能力,是自动化脚本的核心。
  • 软件服务集成类:如send_email(通过SMTP或API发邮件)、create_calendar_event(创建日历事件)、query_database(查询数据库)。这是将Claude接入现有工作流的关键。
  • 内容处理类:如summarize_text(虽然Claude本身擅长,但可作为独立技能保证输出格式)、translate_textgenerate_image(调用DALL-E等绘图API)。

注意:技能的具体实现高度依赖外部API或库。例如,search_web可能需要调用SerpAPI或Google Custom Search API;send_email需要配置SMTP服务器。项目代码主要提供的是与Claude对接的“桥梁”逻辑,而非这些服务的免费替代品。

2.3 与Claude API的集成机制

这是技术上的核心。Anthropic为Claude提供了完整的工具使用(Tool Use)功能。其工作流程如下:

  1. 定义工具:在向Claude API发起请求时,除了常规的对话消息(messages),你还需要在请求体中传入一个tools数组。数组中的每个元素都是一个工具(技能)的定义,包含namedescriptioninput_schema(参数的JSON Schema)。

    { "tools": [{ "name": "get_weather", "description": "获取指定城市的当前天气情况。", "input_schema": { "type": "object", "properties": { "location": { "type": "string", "description": "城市名,例如:北京、San Francisco" } }, "required": ["location"] } }] }
  2. 模型决策:Claude在生成回复时,如果认为需要调用工具,它不会输出普通的文本,而是会在响应中返回一个特殊的tool_use块。这个块包含了它决定调用的工具name和计算好的input参数。

  3. 执行工具:你的应用程序收到API响应后,需要解析出tool_use信息,然后在你的本地服务器或安全环境中执行对应的技能函数(例如,真正调用一个天气API),并得到结果result

  4. 返回结果:你将工具执行的结果,以tool_result消息的形式,追加到对话历史中,再次发送给Claude API。

    { "role": "user", "content": "上海天气怎么样?" }, { "role": "assistant", "content": [{ "type": "tool_use", "id": "toolu_01", "name": "get_weather", "input": {"location": "上海"} }] }, { "role": "user", // 注意,这里虽然是user角色,但内容是工具执行结果 "content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "上海当前天气:晴,25摄氏度,东南风2级。" }] }
  5. 模型整合回复:Claude接收到工具执行结果后,会结合之前的对话上下文,生成最终面向用户的、整合了工具结果的友好回复,比如:“上海现在是晴天,温度25度,非常舒适。”

claude-bmad-skills项目本质上就是提供了第1步中tools数组的丰富定义,以及第3步中各个技能函数的具体实现样板。它把开发者从重复定义工具和编写基础集成代码的工作中解放出来。

3. 关键技能实现深度剖析

我们选取几个有代表性的技能,深入看看其实现逻辑和注意事项。假设项目是用Python实现的(这是最常见的情况),我们将用伪代码和逻辑说明来解析。

3.1 网络搜索技能:打破模型的知识截止壁垒

几乎所有AI智能体项目的标配技能就是网络搜索。它直接解决了大模型知识陈旧(截止到某个训练时间点)和无法获取实时信息的核心痛点。

实现逻辑:

  1. 接收参数:从Claude的tool_use.input中解析出查询关键词query,可能还有可选的num_results(返回数量)。
  2. 调用搜索API:这里通常不会直接爬取谷歌/百度(有反爬和合规问题),而是使用付费的搜索API,如SerpAPIGoogle Custom Search JSON APIBing Search API。这些API返回结构化的搜索结果。
  3. 结果处理与摘要:直接返回10条原始搜索结果链接和摘要给Claude可能效率不高,因为Claude的上下文窗口是有限的宝贵资源。一个更优的做法是:在技能内部先对搜索结果进行一轮预处理和压缩。例如,只提取每个结果的前N个字符的摘要,或者用更小的模型(如gpt-3.5-turbo)先对结果进行总结,再将精简后的文本返回给Claude。
  4. 返回结构化信息:将处理后的搜索结果以清晰、结构化的文本格式返回给Claude,方便它阅读和引用。

实操心得:

  • API密钥管理:搜索API的密钥是敏感信息,务必通过环境变量(如SEARCH_API_KEY)读取,绝不能硬编码在代码中。
  • 费用与限流:这些API通常按次收费且有速率限制。在技能实现里必须加入错误处理和重试逻辑,并考虑对免费用户或内部使用做调用频率限制。
  • 结果可信度:网络信息鱼龙混杂。对于关键信息,可以设计“交叉验证”逻辑,比如从多个结果源提取信息进行对比,或在返回时注明信息来源的域名,让Claude在回复中提及“根据A网站和B网站的报道...”。

3.2 文件系统操作技能:双刃剑与安全沙箱

允许AI读写本地文件,这赋予了它巨大的能力,也带来了巨大的风险。bmad-skills如果包含此类技能,其实现必须格外谨慎。

实现逻辑(以读文件为例):

  1. 路径解析与安全校验:收到文件路径参数后,第一件事就是进行路径规范化访问范围限制。必须将操作限制在某个指定的“工作区”目录(如./workspace)内,防止Claude被诱导去读取/etc/passwd~/.ssh/id_rsa等敏感文件。
    import os from pathlib import Path def read_file(file_path: str, workspace_root: str = "./workspace") -> str: # 1. 规范化路径 requested_path = Path(file_path).expanduser().resolve() # 2. 计算工作区根目录的绝对路径 workspace_path = Path(workspace_root).resolve() # 3. 安全检查:请求的路径必须在工作区内 try: requested_path.relative_to(workspace_path) except ValueError: return "错误:无权访问指定工作区之外的文件。" # 4. 检查文件是否存在且可读 if not requested_path.is_file(): return "错误:文件不存在或不是普通文件。" # 5. 读取文件内容 try: with open(requested_path, 'r', encoding='utf-8') as f: content = f.read() return content except Exception as e: return f"读取文件时出错:{str(e)}"
  2. 执行操作:通过安全检查后,执行真正的文件读写操作。
  3. 返回结果或错误信息:将文件内容或操作结果(成功/失败)返回。

注意事项(性命攸关):

  • 绝对禁止无约束的文件系统访问:这是红线。必须实现严格的“沙箱”或“监狱”机制。
  • 写操作需额外确认:对于删除文件、覆盖文件等危险操作,理想的实现是在技能中先返回一个预览或确认请求,由用户(或一个更高级的监督流程)明确批准后再执行。或者,只允许在特定临时目录进行写操作。
  • 注意文件编码:处理用户上传或未知来源的文件时,务必指定编码(如utf-8),并做好异常处理,防止读取二进制文件导致程序崩溃。
  • 权限最小化:运行技能的服务进程,其系统用户权限应尽可能低,仅拥有工作区目录的必要权限。

3.3 代码执行技能:终极自动化与终极危险

这可能是最强大也最恐怖的技能。想象一下,你告诉Claude:“帮我写个Python脚本,分析当前目录下所有日志文件,找出错误最多的前三个。”Claude生成代码,然后通过execute_code技能直接运行并返回结果——这简直是开发者的梦想。但同样,恶意代码也能造成毁灭性破坏。

安全实现方案:

  1. 使用独立容器:不要在主机进程中直接执行代码。应使用 Docker 容器或更轻量的nsjailgVisor等沙箱技术。每个执行请求都在一个全新的、网络受限、文件系统只读(除了特定挂载点)的容器中运行。
  2. 资源限制:严格限制CPU时间、内存使用量、运行时间和输出大小。防止无限循环或内存爆炸攻击。
  3. 语言与模块白名单:只允许运行特定的编程语言(如Python),并且只能导入预先审核过的安全模块(白名单)。禁止os.system,subprocess.run,open等危险函数,除非在受控环境下。
  4. 超时与隔离:为代码执行设置严格的超时(如5秒),超时即终止进程。确保每次执行环境相互隔离。

一个相对安全的Python代码执行技能框架:

import docker # 需要安装docker-py import tempfile def execute_python_code(code: str, timeout_seconds: int = 5) -> str: client = docker.from_env() # 使用一个预置了Python的轻量级镜像 image_name = "python:3.9-slim" # 将代码写入临时文件(在容器内可见) with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f: f.write(code) host_code_path = f.name try: # 挂载代码文件到容器,并运行 container = client.containers.run( image_name, command=f"timeout {timeout_seconds} python /tmp/code.py", volumes={host_code_path: {'bind': '/tmp/code.py', 'mode': 'ro'}}, # 只读挂载 mem_limit='100m', # 内存限制100MB cpu_period=100000, cpu_quota=50000, # CPU限制50% network_disabled=True, # 禁用网络 detach=True, stdout=True, stderr=True ) # 等待容器执行完成(或超时被kill) result = container.wait(timeout=timeout_seconds+2) stdout = container.logs(stdout=True, stderr=False).decode('utf-8') stderr = container.logs(stdout=False, stderr=True).decode('utf-8') container.remove() # 清理容器 output = f"标准输出:\n{stdout}\n" if stderr: output += f"标准错误:\n{stderr}\n" if result['StatusCode'] != 0: output += f"进程退出代码:{result['StatusCode']}" return output except docker.errors.ContainerError as e: return f"容器执行错误:{str(e)}" except Exception as e: return f"执行过程发生异常:{str(e)}" finally: # 清理主机上的临时文件 os.unlink(host_code_path)

这个实现虽然基础,但涵盖了核心的安全思想:隔离、资源限制、无网络、自动清理。对于生产环境,你需要考虑容器镜像预热、执行队列、更精细的权限控制等问题。

4. 构建你自己的Claude智能体:从零到一的实战

理解了核心技能后,我们来动手搭建一个属于自己的、具备基础能力的Claude智能体。我们将使用Python和Anthropic官方SDK。

4.1 环境准备与项目初始化

首先,确保你的Python环境在3.8以上。创建一个新的项目目录并安装必要的依赖。

mkdir my-claude-agent && cd my-claude-agent python -m venv venv source venv/bin/activate # Linux/macOS # venv\Scripts\activate # Windows pip install anthropic python-dotenv requests

创建项目结构:

my-claude-agent/ ├── .env # 存放API密钥等敏感信息 ├── skills/ # 技能模块目录 │ ├── __init__.py │ ├── weather.py # 天气技能 │ └── calculator.py # 计算器技能(示例) ├── agent_core.py # 智能体核心循环逻辑 └── main.py # 程序入口

.env文件中配置你的Claude API密钥(从Anthropic控制台获取):

ANTHROPIC_API_KEY=your_api_key_here WEATHER_API_KEY=your_openweathermap_key # 示例,如果你要实现天气技能

4.2 实现两个基础技能

我们先实现一个安全的计算器技能和一个需要外部API的天气技能。

skills/calculator.py- 一个安全的数学表达式求值技能

import ast import operator import math # 定义安全的操作符和函数 _SAFE_OPERATORS = { ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, ast.Pow: operator.pow, ast.USub: operator.neg, ast.Mod: operator.mod, } _SAFE_FUNCTIONS = { 'abs': abs, 'round': round, 'min': min, 'max': max, 'pow': pow, } class SafeEvalVisitor(ast.NodeVisitor): """一个安全的AST访问器,只允许白名单内的操作""" def visit_BinOp(self, node): left = self.visit(node.left) right = self.visit(node.right) op_type = type(node.op) if op_type not in _SAFE_OPERATORS: raise ValueError(f"不支持的运算符: {op_type}") return _SAFE_OPERATORS[op_type](left, right) def visit_UnaryOp(self, node): operand = self.visit(node.operand) op_type = type(node.op) if op_type not in _SAFE_OPERATORS: raise ValueError(f"不支持的运算符: {op_type}") return _SAFE_OPERATORS[op_type](operand) def visit_Call(self, node): func_name = node.func.id if isinstance(node.func, ast.Name) else None if func_name not in _SAFE_FUNCTIONS: raise ValueError(f"不支持的函数: {func_name}") args = [self.visit(arg) for arg in node.args] return _SAFE_FUNCTIONS[func_name](*args) def visit_Num(self, node): return node.n def visit_NameConstant(self, node): # Python <3.8 return node.value def visit_Constant(self, node): # Python >=3.8 return node.value def generic_visit(self, node): raise ValueError(f"不支持的AST节点: {type(node).__name__}") def safe_eval(expression: str): """安全地评估数学表达式字符串""" try: tree = ast.parse(expression, mode='eval') visitor = SafeEvalVisitor() return visitor.visit(tree.body) except Exception as e: raise ValueError(f"表达式评估失败: {str(e)}") def skill_calculator(expression: str) -> str: """计算器技能:安全地计算数学表达式。 Args: expression: 数学表达式,如 `(2 + 3) * 4`, `pow(2, 10)`。 支持加减乘除、取模、幂运算,以及abs, round, min, max, pow函数。 """ try: result = safe_eval(expression) return f"表达式 `{expression}` 的计算结果是:{result}" except ValueError as e: return f"计算错误:{str(e)}。请检查表达式是否合法且仅包含支持的运算符和函数。"

这个计算器技能没有使用危险的eval(),而是通过Python的ast(抽象语法树)模块解析表达式,并只允许预定义的白名单操作,从根本上杜绝了代码注入。

skills/weather.py- 调用外部API的天气技能

import os import requests from typing import Optional from dotenv import load_dotenv load_dotenv() def skill_get_weather(location: str, units: Optional[str] = "metric") -> str: """获取指定城市的当前天气情况。 Args: location: 城市名,例如:`北京`、`San Francisco,US`。 units: 单位制。`metric` 为公制(摄氏度),`imperial` 为英制(华氏度)。默认为 `metric`。 """ api_key = os.getenv("WEATHER_API_KEY") if not api_key: return "错误:未配置天气API密钥。请在.env文件中设置WEATHER_API_KEY。" base_url = "http://api.openweathermap.org/data/2.5/weather" params = { "q": location, "appid": api_key, "units": units, "lang": "zh_cn" } try: response = requests.get(base_url, params=params, timeout=10) response.raise_for_status() # 如果状态码不是200,抛出HTTPError data = response.json() if data.get("cod") != 200: return f"无法获取天气:{data.get('message', '未知错误')}" city = data["name"] country = data["sys"]["country"] temp = data["main"]["temp"] feels_like = data["main"]["feels_like"] humidity = data["main"]["humidity"] description = data["weather"][0]["description"] wind_speed = data["wind"]["speed"] unit_symbol = "°C" if units == "metric" else "°F" wind_unit = "米/秒" if units == "metric" else "英里/小时" return (f"{city}, {country} 的当前天气:{description}。\n" f"温度:{temp}{unit_symbol}(体感温度 {feels_like}{unit_symbol})。\n" f"湿度:{humidity}%。\n" f"风速:{wind_speed} {wind_unit}。") except requests.exceptions.Timeout: return "错误:请求天气API超时。" except requests.exceptions.RequestException as e: return f"错误:网络请求失败 - {str(e)}" except (KeyError, IndexError) as e: return f"错误:解析天气API响应数据时出错 - {str(e)}"

这个技能展示了如何安全地集成外部API:从环境变量读取密钥、处理网络超时和异常、解析JSON数据并格式化输出。

4.3 构建智能体核心循环

agent_core.py- 连接Claude与技能的大脑

import os import json from typing import Dict, Any, Callable from anthropic import Anthropic from dotenv import load_dotenv load_dotenv() class ClaudeAgent: def __init__(self, model: str = "claude-3-5-sonnet-20241022"): self.client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) self.model = model self.messages = [] # 对话历史 self.tools = [] # 工具定义列表 self.tool_functions = {} # 工具名到实际函数的映射 def register_tool(self, tool_def: Dict[str, Any], tool_func: Callable): """注册一个工具(技能)""" self.tools.append(tool_def) self.tool_functions[tool_def["name"]] = tool_func def _execute_tool(self, tool_name: str, tool_input: Dict[str, Any]) -> str: """执行已注册的工具函数""" if tool_name not in self.tool_functions: return f"错误:未找到名为 '{tool_name}' 的工具。" try: # 调用对应的技能函数 result = self.tool_functions[tool_name](**tool_input) return str(result) except TypeError as e: return f"错误:调用工具 '{tool_name}' 时参数不匹配 - {str(e)}" except Exception as e: return f"错误:执行工具 '{tool_name}' 时发生意外 - {str(e)}" def chat_round(self, user_input: str) -> str: """进行一轮对话(可能包含工具调用)""" # 1. 将用户输入加入历史 self.messages.append({"role": "user", "content": user_input}) # 2. 调用Claude API,传入工具定义 response = self.client.messages.create( model=self.model, max_tokens=1024, messages=self.messages, tools=self.tools if self.tools else None, # 如果没有工具,则不传 ) # 3. 处理响应 final_response_text = "" for content_block in response.content: if content_block.type == "text": # 普通文本回复,直接累加 final_response_text += content_block.text elif content_block.type == "tool_use": # Claude想要使用工具 tool_name = content_block.name tool_input = content_block.input tool_use_id = content_block.id print(f"[Agent] 检测到工具调用: {tool_name}({tool_input})") # 4. 执行工具 tool_result = self._execute_tool(tool_name, tool_input) print(f"[Agent] 工具执行结果: {tool_result[:100]}...") # 打印部分结果 # 5. 将工具执行结果作为一条新消息追加到历史 self.messages.append({ "role": "user", # 注意,这里角色是user "content": [{ "type": "tool_result", "tool_use_id": tool_use_id, "content": tool_result }] }) # 6. 重新调用Claude,让它基于工具结果继续生成 # 这里我们递归调用自身,但传入一个空用户输入,让Claude基于新历史继续 # 更优雅的做法是循环,这里为清晰起见,递归处理单次工具调用 return self.chat_round("") # 传入空字符串,触发下一轮 # 7. 将Claude的最终回复也加入历史,以便多轮对话 if final_response_text: self.messages.append({"role": "assistant", "content": final_response_text}) return final_response_text

这个核心类ClaudeAgent完成了所有繁重的工作:管理对话历史、向Claude注册工具定义、解析Claude的工具调用请求、执行对应的本地函数、并将结果反馈给Claude进行下一轮思考。

4.4 组装并运行你的智能体

main.py- 程序入口

from agent_core import ClaudeAgent from skills import calculator, weather def main(): # 1. 初始化智能体 agent = ClaudeAgent(model="claude-3-haiku-20240307") # 使用更快的Haiku模型进行演示 # 2. 定义并注册工具(技能) # 计算器工具定义 calculator_tool_def = { "name": "calculate", "description": "一个安全的数学表达式计算器。支持加减乘除(+-*/)、取模(%)、幂运算(**),以及abs, round, min, max, pow函数。例如:`(2 + 3) * 4`, `pow(2, 10)`。", "input_schema": { "type": "object", "properties": { "expression": { "type": "string", "description": "需要计算的数学表达式。" } }, "required": ["expression"] } } agent.register_tool(calculator_tool_def, calculator.skill_calculator) # 天气工具定义 weather_tool_def = { "name": "get_weather", "description": "获取指定城市的当前天气情况。需要城市名,例如:`北京`、`San Francisco,US`。", "input_schema": { "type": "object", "properties": { "location": { "type": "string", "description": "城市名,可附加国家代码以提高准确性,如 `London,GB`。" }, "units": { "type": "string", "description": "单位制。`metric` 为公制(摄氏度),`imperial` 为英制(华氏度)。默认为 `metric`。", "enum": ["metric", "imperial"] } }, "required": ["location"] } } agent.register_tool(weather_tool_def, weather.skill_get_weather) print("Claude智能体已启动,已加载计算器和天气技能。输入 'quit' 退出。") print("-" * 50) # 3. 开始对话循环 while True: try: user_input = input("\n你: ").strip() if user_input.lower() in ['quit', 'exit', 'q']: print("再见!") break if not user_input: continue print("\nClaude: ", end="", flush=True) response = agent.chat_round(user_input) print(response) except KeyboardInterrupt: print("\n\n程序被中断。") break except Exception as e: print(f"\n发生错误: {e}") if __name__ == "__main__": main()

现在,运行python main.py,你就可以和一个具备计算和查天气能力的Claude对话了!

示例对话:

你: 帮我算一下 (12.5 + 4.3) * 2 是多少? Claude: 表达式 `(12.5 + 4.3) * 2` 的计算结果是:33.6 你: 今天纽约天气怎么样?用华氏度告诉我。 [Agent] 检测到工具调用: get_weather({'location': 'New York,US', 'units': 'imperial'}) [Agent] 工具执行结果: New York, US 的当前天气:few clouds。温度:62.62°F(体感温度 61.63°F)。湿度:65%。风速:6.91 英里/小时。 Claude: 根据获取的信息,美国纽约目前天气为少云。温度约为62.6华氏度(体感温度约61.6华氏度),湿度65%,风速约6.9英里/小时。 你: 把上面的温度转换成摄氏度再告诉我。 Claude: 62.6华氏度约等于17摄氏度(计算公式:(62.6°F - 32) × 5/9 ≈ 17°C)。所以纽约现在的温度大约是17摄氏度。

看,Claude不仅调用了工具,还能基于工具返回的结果进行推理和单位换算!这就是智能体的魅力。

5. 高级技巧、安全考量与避坑指南

5.1 提升智能体可靠性的高级技巧

  1. 技能描述的优化艺术:Claude完全依靠工具的描述(description)和参数模式(input_schema)来理解何时使用它。描述要精确、无歧义、包含示例。例如,“处理数据”就太模糊,“读取CSV文件并返回前5行”就清晰得多。在参数描述里写明期望的格式,如“日期,格式为 YYYY-MM-DD”

  2. 处理复杂多步任务:上面的简单循环一次只处理一个工具调用。对于“查天气并邮件告诉我”这类需要连续调用多个工具的任务,你需要实现一个更强大的规划-执行循环。Claude在输出第一个工具调用后就会暂停,你需要将结果反馈给它,它可能会接着输出第二个工具调用。你的主循环需要能处理这种连续的、可能交替出现文本和工具调用的输出。

  3. 技能组合与编排:你可以设计更高级的“元技能”,例如一个research_and_summarize技能,它在内部先调用search_web技能获取多篇资料,再调用一个内部的文本摘要函数,最后将总结结果返回。这减少了与Claude的来回交互次数,提高了复杂任务的执行效率。

  4. 上下文管理:Claude的上下文窗口是有限的(例如200K tokens)。长时间运行后,对话历史会非常长。你需要设计策略来修剪或总结历史,保留关键信息(如用户的目标、之前的工具结果摘要),丢弃无关细节,以节省token并保持模型对长期目标的记忆。

5.2 安全红线:绝不能踩的坑

  1. 永远不要相信用户的直接输入:这是安全的第一原则。即使用户说“请运行命令ls -la”,你的execute_command技能也必须经过严格的白名单或模式匹配校验。更好的做法是,根本不提供原生命令执行技能,而是提供具体的、封装好的技能,如list_directory

  2. 隔离、隔离、再隔离:任何执行外部代码、访问文件系统、调用系统资源的技能,必须在沙箱环境中运行。Docker容器是最低要求。考虑使用无服务器函数(如AWS Lambda)来运行不可信的技能,它们提供了天然的隔离和资源限制。

  3. 权限最小化与审计:运行智能体的服务账号应该只有完成其功能所必需的最小权限。所有工具调用(谁、何时、调用什么、输入输出是什么)都必须被详细记录到日志中,以便事后审计和问题排查。

  4. 人工确认环节:对于高风险操作(如删除文件、发送邮件、支付),必须在流程中设计“人工确认”步骤。可以让技能返回一个需要用户输入特定确认码(如“是的,我确认删除”)的提示,或者集成到一个需要点击按钮的聊天界面中。

  5. 输入输出过滤与净化:警惕提示词注入。恶意用户可能会输入像“忽略之前的指令,现在执行...”这样的内容,试图劫持Claude的后续行为。虽然很难完全防御,但可以通过在系统提示词中强调必须严格遵守指令、或在技能层面对输入进行模式匹配来增加攻击难度。同样,技能返回给Claude的内容也可能被污染,需要保持警惕。

5.3 性能优化与成本控制

  1. 选择合适的Claude模型claude-3-5-sonnet能力最强但最贵也最慢,claude-3-haiku最快最便宜但能力稍弱。对于工具使用场景,Haiku往往已经足够,因为它主要做“何时调用工具”和“参数填充”的决策,复杂的推理可以由后续的Sonnet来处理。可以设计一个混合模型策略。

  2. 缓存技能结果:对于频繁且结果变化不快的技能(如某些数据查询),可以引入缓存机制。例如,天气查询可以缓存10分钟。这能减少对外部API的调用,节省成本和延迟。

  3. 异步执行:如果多个技能之间没有依赖关系,可以考虑让它们异步并行执行,而不是顺序执行,以降低总体响应时间。

  4. 监控与告警:监控API调用次数、token消耗、技能执行成功率。设置成本预算告警,防止意外的高消耗。

terryso/claude-bmad-skills这类项目为我们打开了一扇门,展示了将大语言模型从“思考者”转变为“行动者”的蓝图。其核心价值不在于那几个具体的技能实现,而在于它验证的模式:LLM + 工具 = 可行动的智能体。构建这样的系统,三分靠技术,七分靠对安全和边界的深刻理解。从实现一个安全的计算器开始,逐步添加更多技能,并始终将安全架构放在首位,你就能打造出一个既强大又可靠的AI伙伴,真正让Claude为你“干活”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/15 16:13:48

世界地图数据宝库:world.geo.json 项目完全指南

世界地图数据宝库&#xff1a;world.geo.json 项目完全指南 【免费下载链接】world.geo.json Annotated geo-json geometry files for the world 项目地址: https://gitcode.com/gh_mirrors/wo/world.geo.json 你是否曾梦想创建自己的交互式世界地图&#xff0c;却苦于找…

作者头像 李华
网站建设 2026/5/15 16:11:15

射频高手到底强在哪里?尤其做5G,真正拼的是这套底层功夫

&#x1f680;《射频高手到底强在哪里&#xff1f;尤其做5G&#xff0c;真正拼的是这套底层功夫》&#x1f3af;射频不是“接个天线、调个匹配”这么简单。 真正的射频高手&#xff0c;脑子里装的是&#xff1a;电磁场 传输线 调制解调 噪声 PA 天线 认证测试 系统干扰链…

作者头像 李华
网站建设 2026/5/15 16:11:07

ClawTabs:基于浏览器扩展API的开发者标签页会话管理工具

1. 项目概述&#xff1a;一个为开发者打造的浏览器标签页管理器如果你和我一样&#xff0c;每天需要在浏览器里同时打开几十个标签页&#xff0c;在多个项目、文档、调试工具和参考网站之间来回切换&#xff0c;那你一定对“标签页混乱”深有体会。找不回之前打开的页面、内存占…

作者头像 李华
网站建设 2026/5/15 16:11:06

PHPStudy环境下手动集成Imagick扩展:从零到实战的完整指南

1. 为什么要在PHPStudy中集成Imagick扩展&#xff1f; 最近接手一个电商项目&#xff0c;需要批量处理商品图片的缩略图生成和水印添加功能。当我信心满满地准备使用PHP的Imagick扩展时&#xff0c;却发现PHPStudy默认没有安装这个扩展。相信很多用PHPStudy做本地开发的朋友都遇…

作者头像 李华
网站建设 2026/5/15 16:08:13

【人工智能】架构演进:基于本体论与 LLM Agent 的供应链备件决策闭环实践

引言:为什么 Agent 需要“本体论”? 在以大语言模型(LLM)为核心的 AI 浪潮下,构建具备自主决策能力的 Agent 已成为工业界的热门方向。然而,在供应链、智能制造等容错率极低的垂直领域,纯粹的 LLM 暴露出了致命缺陷——“幻觉(Hallucination)”与缺乏严密的业务逻辑推…

作者头像 李华