使用 Claude Fable 5 构建 AI Agent:实践指南
上个月,我在一个客户支持自动化项目上碰了壁。我现有的配置处理简单查询没问题,但一旦任务需要多个步骤——比如查找订单历史、检查库存并起草个性化回复——一切就全乱套了。模型会在执行到一半时丢失上下文,或者凭空捏造根本不存在的 API 响应。
就在那时,我开始尝试使用 Claude Fable 5 来构建真正的 Agent,而不仅仅是聊天机器人。经过几周的测试,我积累了足够的经验,可以和大家分享哪些方法有效,哪些无效。
Fable 5 在 Agent 工作中的不同之处
切换到 Fable 5 后,我注意到的第一件事就是它处理多步推理的方式。它不会只给出一个响应然后听天由命,而是真正地规划步骤,按顺序执行,而且最关键的是——它记得自己已经做了什么。
我用一个简单的研究任务测试了这一点:“找一个 SaaS 产品的 3 个主要竞争对手,研究他们的定价,并制作一个对比表格。”用我以前的配置,我会得到一个听起来很自信、但数字完全是捏造的表格。Fable 5 的处理方式不同——它分解了任务,在找不到具体定价时坦诚相告,并询问我是希望它根据现有信息进行估算,还是留空。
单是这种行为就为我节省了数小时的事实核查时间。
搭建你的第一个多步工作流
让我通过一个实际的例子来说明。我构建了一个处理客户退款请求的 Agent——这项任务需要检查多个系统并做出判断。
这是我最初使用的基本结构:
import anthropic
import json
client = anthropic.Anthropic(api_key="your-api-key")
# 定义我们的 agent 可以使用的工具
tools = [
{
"name": "lookup_order",
"description": "Look up order details by order ID or customer email",
"input_schema": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "The order ID to look up"},
"email": {"type": "string", "description": "Customer email address"}
},
"required": ["order_id"]
}
},
{
"name": "check_refund_policy",
"description": "Check if an order is eligible for refund based on purchase date and item category",
"input_schema": {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"reason": {"type": "string", "description": "Reason for refund request"}
},
"required": ["order_id", "reason"]
}
},
{
"name": "process_refund",
"description": "Process a refund for an eligible order",
"input_schema": {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"amount": {"type": "number"},
"reason": {"type": "string"}
},
"required": ["order_id", "amount", "reason"]
}
}
]
这里的关键洞察是,Fable 5 不会只选一个工具就完事了。它会根据每一步学到的信息将工具串联起来。
工具使用循环
这是我犯的第一个错误。我最初试图在单次传递中处理工具调用,以为模型能自己理清顺序。这行不通——Agent 会在没有首先检查资格的情况下直接调用 process_refund。
正确的方法是使用一个循环,一直运行直到 Agent 获得所需的所有信息:
def run_agent(user_message, max_turns=10):
messages = [{"role": "user", "content": user_message}]
for turn in range(max_turns):
response = client.messages.create(
model="claude-3-5-sonnet-20241022", # Fable 5 model
max_tokens=4096,
tools=tools,
messages=messages
)
# 检查是否完成
if response.stop_reason == "end_turn":
print("Agent completed the task")
print(response.content[0].text)
break
# 处理工具调用
if response.stop_reason == "tool_use":
# 将助手的响应添加到对话中
messages.append({"role": "assistant", "content": response.content})
# 处理每个工具调用
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result)
})
# 将工具结果添加回对话
messages.append({"role": "user", "content": tool_results})
return messages
def execute_tool(name, params):
"""执行实际的工具逻辑"""
if name == "lookup_order":
# 在实际代码中,这里会查询你的数据库
return {"order_id": params["order_id"], "total": 89.99, "date": "2024-01-15", "status": "delivered"}
elif name == "check_refund_policy":
# 你的业务逻辑写在这里
return {"eligible": True, "reason": "Within 30-day window"}
elif name == "process_refund":
# 调用你的支付处理系统
return {"success": True, "refund_id": "REF-12345"}
让我感到惊讶的是,看着 Agent 如何推理边缘情况。当我用 6 个月前的订单进行测试时,它正确地识别出退款可能不符合条件,并询问如何继续,而不是直接静默失败。
持久化任务执行
我以前配置中最大的痛点之一就是在长时间运行的任务中丢失上下文。Fable 5 在这方面的表现超出了我的预期,但你需要正确地构建对话历史。
这是我针对可能耗时较长的任务总结出的一种模式:
class PersistentAgent:
def __init__(self, task_id):
self.task_id = task_id
self.conversation_history = []
self.task_state = {
"status": "pending",
"steps_completed": [],
"current_step": None,
"errors": []
}
def save_state(self):
"""保存到你的数据库或文件系统"""
state = {
"task_id": self.task_id,
"conversation": self.conversation_history,
"state": self.task_state
}
# 在生产环境中,保存到 Redis、Postgres 等
with open(f"task_{self.task_id}.json", "w") as f:
json.dump(state, f)
def load_state(self):
"""从先前的状态恢复"""
try:
with open(f"task_{self.task_id}.json", "r") as f:
state = json.load(f)
self.conversation_history = state["conversation"]
self.task_state = state["state"]
return True
except FileNotFoundError:
return False
def execute_with_recovery(self, user_request):
# 尝试恢复先前的状态
if self.load_state():
print(f"Resuming task from step: {self.task_state['current_step']}")
# 继续执行
self.conversation_history.append({"role": "user", "content": user_request})
try:
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=4096,
tools=tools,
system=f"""You are working on task {self.task_id}.
Current state: {json.dumps(self.task_state)}
If this is a resumed task, continue from where you left off.""",
messages=self.conversation_history
)
# 处理响应并更新状态
self.task_state["current_step"] = "processing"
self.save_state()
return response
except Exception as e:
self.task_state["errors"].append(str(e))
self.save_state()
raise
当遇到 API 速率限制或服务器在任务执行中途重启时,这个模式已经多次救了我。
真正有效的错误恢复
我以前认为 Agent 系统中的错误处理就是写 try-catch 块。Fable 5 让我明白,更重要的是给模型足够的上下文让其自我纠正。
这是我现在处理工具失败的方式:
def execute_tool_with_retry(name, params, max_retries=2):
attempts = 0
while attempts <= max_retries:
try:
result = execute_tool(name, params)
return {"success": True, "data": result}
except Exception as e:
attempts += 1
if attempts > max_retries:
# 返回结构化错误,以便 agent 能够适应调整
return {
"success": False,
"error": str(e),
"suggestion": "The API is currently unavailable. You could try an alternative approach or inform the user."
}
# 重试前等待
time.sleep(2 ** attempts)
# 更新后的工具结果处理
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(execute_tool_with_retry(block.name, block.input))
})
区别在于 suggestion 字段。当我加上这个后,Agent 开始做出更明智的决策——比如回退到缓存数据,或者要求用户手动输入,而不是直接报错失败。
Fable 5 与 Claude Code 在构建 Agent 时的对比
这两者我都大量使用过,它们各有用途。以下是我的真实对比:
Claude Code 非常适合当你希望模型直接编写和执行代码的场景。我将其用于数据分析 Agent,模型需要即时生成 Python 脚本。代价是你需要一个沙盒执行环境,而且调试生成的代码可能会很痛苦。
Fable 5 在你拥有定义明确的工具和 API 时大放异彩。它的函数调用更可预测,而且模型在推理该使用哪些工具以及按什么顺序使用方面似乎表现更好。我很少遇到它捏造不存在函数的情况。
对于我的退款处理 Agent,Fable 5 显然是赢家。工具已经定义好了(数据库查找、支付处理),而且我需要可靠的执行,无需代码执行环境的开销。
对于需要转换任意 CSV 文件的数据管道 Agent,Claude Code 更好,因为转换逻辑是无法预先预测的。
来自我踩坑经验的实用技巧
从更少的工具开始。 我的第一个版本有 15 个工具,Agent 总是选错。我将其整合为 5 个定义明确的工具,准确率大幅提升。
明确说明失败模式。 告诉模型工具失败时该怎么做。没有这个指导,它有时会陷入循环,反复尝试同一种失败的方法。
记录一切。 你需要调试 Agent 为什么做出某些决定。我记录了每一次工具调用、推理过程和结果。这为我节省了无数小时。
对“自主”设定现实的期望。 Fable 5 能力很强,但它不是魔法。复杂任务仍然需要人工检查点。我为任何修改数据或花费金钱的操作添加了审批步骤。
需要注意的局限性
我遇到的最大局限是在超长对话中的上下文窗口管理。大约 20-30 次工具调用后,你需要总结或截断历史记录,这可能会丢失重要细节。
工具选择也并非完美。在模棱两可的情况下,模型有时会选择一个看似合理但错误的工具。我已经学会了让工具描述极其具体,并在系统提示中包含示例。
对于高并发的 Agent,速率限制也可能成为瓶颈。每一轮都是一次 API 调用,因此复杂的任务会很快耗尽你的配额。
了解更多
我在这里只触及了皮毛。要获取更深入的文档和示例,请查看 https://aiclawhot.com/zh/agents/claude-fable-5/ —— 这是我整个学习过程中的首选参考。
构建可靠的 Agent 仍然很困难,但 Fable 5 使其比以前的选择明显更容易上手。从简单的工作流开始,逐步增加复杂性,并始终为失败模式做好计划。这项技术已经足够好,可以派上用场,但要在生产环境中可靠运行,仍然需要周密的工程设计。