Agent 是什么
Agent = LLM + 工具 + 循环。
普通调用:你问一次,它答一次。 Agent:它能自己决定"我要先查搜索引擎,再读文件,最后总结"——多步推理 + 工具使用 + 反思。
ReAct:思考 → 行动 → 观察的循环
Thought: 我需要查一下今天天气
Action: get_weather(city="北京")
Observation: 晴 25 度
Thought: 已知天气,可以回答用户了
Final Answer: 北京今天晴,25 度
LLM 在每一步输出 Thought 和 Action,外部代码执行 Action 拿到 Observation,再反馈给 LLM。
自己写一个最小 Agent(80 行)
import json
from anthropic import Anthropic
client = Anthropic()
# 工具实现
def get_weather(city: str) -> str:
return f"{city} 晴 25 度"
def search_web(query: str) -> str:
return f"关于 {query} 的搜索结果:[模拟]"
def calculate(expression: str) -> str:
# ⚠ 演示用:eval 即使禁了 builtins 也能被精心构造的字符串绕过沙箱。
# 生产请用 ast.parse 自己写计算器,或用 simpleeval / numexpr 等库。
try:
return str(eval(expression, {"__builtins__": {}}))
except Exception as e:
return f"计算错误: {e}"
TOOLS = {"get_weather": get_weather, "search_web": search_web, "calculate": calculate}
# 工具描述
TOOL_SCHEMAS = [
{
"name": "get_weather",
"description": "查询某城市天气",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
{
"name": "search_web",
"description": "搜索网络信息",
"input_schema": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"],
},
},
{
"name": "calculate",
"description": "计算数学表达式",
"input_schema": {
"type": "object",
"properties": {"expression": {"type": "string"}},
"required": ["expression"],
},
},
]
def run_agent(user_input: str, max_steps: int = 5):
messages = [{"role": "user", "content": user_input}]
for step in range(max_steps):
msg = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=TOOL_SCHEMAS,
messages=messages,
)
# 没有工具调用 → 终止
if msg.stop_reason == "end_turn":
for b in msg.content:
if b.type == "text":
return b.text
# 有工具调用 → 执行 → 反馈
messages.append({"role": "assistant", "content": msg.content})
results = []
for b in msg.content:
if b.type == "tool_use":
func = TOOLS[b.name]
result = func(**b.input)
print(f"[{b.name}]({b.input}) → {result}")
results.append({
"type": "tool_result",
"tool_use_id": b.id,
"content": result,
})
messages.append({"role": "user", "content": results})
return "(达到最大步数)"
print(run_agent("北京今天天气?另外帮我算一下 12345 × 6789"))
LLM 会自己决定先调 get_weather 还是 calculate,调几次工具,最后总结。
加点"记忆"
简单做法:把对话历史塞进 messages 即可。 高级做法:用向量库存历史,按相关度检索("长期记忆")。
class Memory:
def __init__(self, kb):
self.kb = kb # 向量库
self.recent = [] # 最近 N 轮
def add(self, text):
self.kb.add(text)
self.recent.append(text)
if len(self.recent) > 10:
self.recent.pop(0)
def relevant(self, query):
return self.kb.search(query, k=3)
每次对话开头注入 relevant(query) + recent——这就是 ChatGPT 的"记忆"功能本质。
Agent 的三大坑
1. 死循环
LLM 反复调同一个工具——加 max_steps 兜底。
2. 工具描述写得不清
LLM 调错参数 / 选错工具——把 description 写得超清楚(带例子)。
3. 任务太大不分解
让 Agent 一步做"建一个完整网站"——它会迷路。分阶段 + 子 agent。
框架推荐
写自己的 Agent → 80 行就够(上面那种)。 要多 agent 协作 → 看看 CrewAI / AutoGen / LangGraph。 不复杂场景 → 直接 SDK 自己写。
Claude Agent SDK
Anthropic 出了官方 Agent SDK,专门做这个:
pip install claude-agent-sdk
把上面的 80 行变成 5 行——Tool use 循环 / 错误处理 / 流式输出 全包好。
下一篇讲微调。