重构大版本更新
一口气全面统一博客样式,移除部分冗余导航页面,更专注内容展示。
从"会聊天"到"会干活":拆解 AI Agent 的核心循环(规划-工具-记忆),并聊聊 Agent 化带来的新安全边界。
如果你问现在的 AI”帮我查下明天北京的天气”,它大概率会一本正经地编一个答案。但换成一个 Agent,它会真的去调天气 API,把结果整理好再回复你。从”会说”到”会做”,中间隔着的正是 Agent 这层架构。
一个典型的 AI Agent 由三部分组成,循环运转:
用伪代码表示这个循环:
目标: 修复 issue #123循环: 观察 <- 上一步工具的返回结果 / 初始目标 思考 <- LLM 分析观察, 决定下一步 行动 <- 调用某个工具 (读文件 / 改代码 / 跑测试) 如果 LLM 认为任务完成: 输出最终答案, 退出看起来简单,但每个环节都有大学问:规划得太细浪费 token,太粗容易跑偏;工具描述写得含糊,模型就选错工具;上下文塞太满,模型”忘了”自己最初的目标。
| 维度 | 聊天机器人 | Agent |
|---|---|---|
| 输出 | 文本 | 真实世界的动作 |
| 错误代价 | 说错话,重问一次 | 邮件已发出、文件已删除 |
| 权限需求 | 无 | 读写文件、网络访问、执行命令 |
| 攻击面 | 提示词注入只影响回答 | 提示词注入直接变成工具滥用 |
最后一行是重点:Agent 把提示词注入从”言论问题”升级成了”权限问题”。一个会被注入的 Agent 加上一把不受限的 shell,等于把服务器钥匙挂在门口。
以 OpenAI SDK 为例,一个能查时间的 Agent 核心代码不到 30 行:
from openai import OpenAIimport json, datetime
client = OpenAI()
tools = [{ "type": "function", "function": { "name": "get_time", "description": "获取当前时间", "parameters": {"type": "object", "properties": {"tz": {"type": "string"}}, "required": []}, },}]
def get_time(tz="Asia/Shanghai"): return datetime.datetime.now().astimezone().isoformat()
msgs = [{"role": "user", "content": "现在几点了?"}]while True: r = client.chat.completions.create( model="gpt-4o-mini", messages=msgs, tools=tools) m = r.choices[0].message msgs.append(m) if not m.tool_calls: print(m.content); break for call in m.tool_calls: result = get_time(**json.loads(call.function.arguments)) msgs.append({"role": "tool", "tool_call_id": call.id, "content": result})跑起来你会发现:模型自己决定”该调工具了”,拿到结果后自己组织语言回答——规划循环已经初具雏形。
既然 Agent 能动手,安全设计就必须跟着动:
这些原则和我在这台服务器上部署服务的思路一脉相承——回环绑定 + 反代 + 最小开放端口,权限永远只给刚好够用的那部分。
Agent 是 LLM 从玩具走向生产力的关键一步,但它同时把模型的不可靠性直接接到了真实世界的操作上。能力越大,越要先把”刹车”装好——先设计好权限边界和审计,再谈自动化。