agents
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuilding Agents
构建Agent
Agents are systems where LLMs dynamically direct their own processes and tool usage. This skill covers when to use agents vs workflows, common architectural patterns, and practical implementation guidance.
Agent是由LLM动态引导自身流程和工具调用的系统。本内容涵盖了Agent与工作流的适用场景、常见架构模式以及实际实施指导。
Table of Contents
目录
Agents vs Workflows
Agent与工作流对比
| Aspect | Workflows | Agents |
|---|---|---|
| Control flow | Predefined code paths | LLM determines next step |
| Predictability | High - deterministic steps | Lower - dynamic decisions |
| Complexity | Simpler to debug and test | More complex, harder to predict |
| Best for | Well-defined, repeatable tasks | Open-ended, adaptive problems |
Key principle: Start with the simplest solution. Use workflows when the task is predictable; use agents when flexibility is required.
| 维度 | 工作流 | Agent |
|---|---|---|
| 控制流 | 预定义代码路径 | 由LLM决定下一步操作 |
| 可预测性 | 高 - 步骤确定性强 | 较低 - 决策动态变化 |
| 复杂度 | 调试和测试更简单 | 更复杂,难以预测 |
| 最佳适用场景 | 定义明确、可重复的任务 | 开放式、需要自适应的问题 |
核心原则:从最简单的解决方案入手。当任务可预测时使用工作流;当需要灵活性时使用Agent。
Workflow Patterns
工作流模式
1. Prompt Chaining
1. 提示词链
Decompose tasks into sequential LLM calls, where each step's output feeds the next.
python
async def prompt_chain(input_text):
# Step 1: Extract key information
extracted = await llm.generate(
"Extract the main entities and relationships from: " + input_text
)
# Step 2: Analyze
analysis = await llm.generate(
"Analyze these entities for patterns: " + extracted
)
# Step 3: Generate output
return await llm.generate(
"Based on this analysis, provide recommendations: " + analysis
)Use when: Tasks naturally decompose into fixed sequential steps.
将任务分解为连续的LLM调用,每一步的输出作为下一步的输入。
python
async def prompt_chain(input_text):
# Step 1: Extract key information
extracted = await llm.generate(
"Extract the main entities and relationships from: " + input_text
)
# Step 2: Analyze
analysis = await llm.generate(
"Analyze these entities for patterns: " + extracted
)
# Step 3: Generate output
return await llm.generate(
"Based on this analysis, provide recommendations: " + analysis
)适用场景:任务可自然分解为固定的连续步骤。
2. Routing
2. 路由
Classify inputs and direct them to specialized handlers.
python
async def route_request(user_input):
# Classify the input
category = await llm.generate(
f"Classify this request into one of: [billing, technical, general]\n{user_input}"
)
handlers = {
"billing": handle_billing,
"technical": handle_technical,
"general": handle_general,
}
return await handlers[category.strip()](user_input)Use when: Different input types need fundamentally different processing.
对输入进行分类,并将其导向专门的处理程序。
python
async def route_request(user_input):
# Classify the input
category = await llm.generate(
f"Classify this request into one of: [billing, technical, general]\n{user_input}"
)
handlers = {
"billing": handle_billing,
"technical": handle_technical,
"general": handle_general,
}
return await handlers[category.strip()](user_input)适用场景:不同类型的输入需要完全不同的处理方式。
3. Parallelization
3. 并行化
Run multiple LLM calls concurrently for independent subtasks.
python
import asyncio
async def parallel_analysis(document):
# Run independent analyses in parallel
results = await asyncio.gather(
llm.generate(f"Summarize: {document}"),
llm.generate(f"Extract key facts: {document}"),
llm.generate(f"Identify sentiment: {document}"),
)
summary, facts, sentiment = results
return {"summary": summary, "facts": facts, "sentiment": sentiment}Variants:
- Sectioning: Break task into parallel subtasks
- Voting: Run same prompt multiple times, aggregate results
为独立的子任务同时运行多个LLM调用。
python
import asyncio
async def parallel_analysis(document):
# Run independent analyses in parallel
results = await asyncio.gather(
llm.generate(f"Summarize: {document}"),
llm.generate(f"Extract key facts: {document}"),
llm.generate(f"Identify sentiment: {document}"),
)
summary, facts, sentiment = results
return {"summary": summary, "facts": facts, "sentiment": sentiment}变体:
- 分段处理:将任务拆分为并行子任务
- 投票机制:多次运行相同提示词,汇总结果
4. Orchestrator-Workers
4. 编排器-工作者模式
Central LLM decomposes tasks and delegates to worker LLMs.
python
class Orchestrator:
async def run(self, task):
# Break down the task
subtasks = await self.plan(task)
# Delegate to workers
results = []
for subtask in subtasks:
worker_result = await self.delegate(subtask)
results.append(worker_result)
# Synthesize results
return await self.synthesize(results)
async def plan(self, task):
response = await llm.generate(
f"Break this task into subtasks:\n{task}\n\nReturn as JSON array."
)
return json.loads(response)
async def delegate(self, subtask):
return await llm.generate(f"Complete this subtask:\n{subtask}")
async def synthesize(self, results):
return await llm.generate(
f"Combine these results into a coherent response:\n{results}"
)Use when: Tasks require dynamic decomposition that can't be predetermined.
中心LLM分解任务,并将其委托给工作者LLM处理。
python
class Orchestrator:
async def run(self, task):
# Break down the task
subtasks = await self.plan(task)
# Delegate to workers
results = []
for subtask in subtasks:
worker_result = await self.delegate(subtask)
results.append(worker_result)
# Synthesize results
return await self.synthesize(results)
async def plan(self, task):
response = await llm.generate(
f"Break this task into subtasks:\n{task}\n\nReturn as JSON array."
)
return json.loads(response)
async def delegate(self, subtask):
return await llm.generate(f"Complete this subtask:\n{subtask}")
async def synthesize(self, results):
return await llm.generate(
f"Combine these results into a coherent response:\n{results}"
)适用场景:任务需要动态分解,无法预先确定分解方式。
5. Evaluator-Optimizer
5. 评估器-优化器模式
One LLM generates, another evaluates and requests improvements.
python
async def generate_with_feedback(task, max_iterations=3):
response = await llm.generate(f"Complete this task:\n{task}")
for _ in range(max_iterations):
evaluation = await llm.generate(
f"Evaluate this response for quality and correctness:\n{response}\n"
"If improvements needed, specify them. Otherwise respond 'APPROVED'."
)
if "APPROVED" in evaluation:
return response
response = await llm.generate(
f"Improve this response based on feedback:\n"
f"Original: {response}\nFeedback: {evaluation}"
)
return responseUse when: Output quality is critical and can be objectively evaluated.
一个LLM生成结果,另一个LLM进行评估并要求改进。
python
async def generate_with_feedback(task, max_iterations=3):
response = await llm.generate(f"Complete this task:\n{task}")
for _ in range(max_iterations):
evaluation = await llm.generate(
f"Evaluate this response for quality and correctness:\n{response}\n"
"If improvements needed, specify them. Otherwise respond 'APPROVED'."
)
if "APPROVED" in evaluation:
return response
response = await llm.generate(
f"Improve this response based on feedback:\n"
f"Original: {response}\nFeedback: {evaluation}"
)
return response适用场景:输出质量至关重要,且可进行客观评估。
Agent Architectures
Agent架构
Autonomous Agent Loop
自主Agent循环
Agents operate in a loop: observe, think, act, repeat.
python
class Agent:
def __init__(self, tools: list, system_prompt: str):
self.tools = {t.name: t for t in tools}
self.system_prompt = system_prompt
async def run(self, task: str, max_steps: int = 10):
messages = [
{"role": "system", "content": self.system_prompt},
{"role": "user", "content": task},
]
for step in range(max_steps):
response = await llm.generate(messages, tools=self.tools)
messages.append({"role": "assistant", "content": response})
if response.tool_calls:
for call in response.tool_calls:
result = await self.execute_tool(call)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": result
})
else:
# No tool calls - agent is done
return response.content
return "Max steps reached"
async def execute_tool(self, call):
tool = self.tools[call.name]
return await tool.execute(**call.arguments)Agent以循环方式运行:观察、思考、行动、重复。
python
class Agent:
def __init__(self, tools: list, system_prompt: str):
self.tools = {t.name: t for t in tools}
self.system_prompt = system_prompt
async def run(self, task: str, max_steps: int = 10):
messages = [
{"role": "system", "content": self.system_prompt},
{"role": "user", "content": task},
]
for step in range(max_steps):
response = await llm.generate(messages, tools=self.tools)
messages.append({"role": "assistant", "content": response})
if response.tool_calls:
for call in response.tool_calls:
result = await self.execute_tool(call)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": result
})
else:
# No tool calls - agent is done
return response.content
return "Max steps reached"
async def execute_tool(self, call):
tool = self.tools[call.name]
return await tool.execute(**call.arguments)Human-in-the-Loop
人机协同循环
Pause for human approval at critical checkpoints.
python
class HumanInLoopAgent(Agent):
def __init__(self, tools, system_prompt, approval_required: list):
super().__init__(tools, system_prompt)
self.approval_required = set(approval_required)
async def execute_tool(self, call):
if call.name in self.approval_required:
approved = await self.request_approval(call)
if not approved:
return "Action cancelled by user"
return await super().execute_tool(call)
async def request_approval(self, call):
print(f"Agent wants to execute: {call.name}({call.arguments})")
response = input("Approve? (y/n): ")
return response.lower() == "y"在关键检查点暂停,等待人工批准。
python
class HumanInLoopAgent(Agent):
def __init__(self, tools, system_prompt, approval_required: list):
super().__init__(tools, system_prompt)
self.approval_required = set(approval_required)
async def execute_tool(self, call):
if call.name in self.approval_required:
approved = await self.request_approval(call)
if not approved:
return "Action cancelled by user"
return await super().execute_tool(call)
async def request_approval(self, call):
print(f"Agent wants to execute: {call.name}({call.arguments})")
response = input("Approve? (y/n): ")
return response.lower() == "y"ReAct Pattern
ReAct模式
ReAct (Reasoning and Acting) alternates between thinking and taking actions.
python
REACT_PROMPT = """Answer the question using the available tools.
For each step:
1. Thought: Reason about what to do next
2. Action: Choose a tool and inputs
3. Observation: See the result
4. Repeat until you have the answer
Available tools: {tools}
Question: {question}
"""
async def react_agent(question, tools):
prompt = REACT_PROMPT.format(
tools=format_tools(tools),
question=question
)
messages = [{"role": "user", "content": prompt}]
while True:
response = await llm.generate(messages)
messages.append({"role": "assistant", "content": response})
if "Final Answer:" in response:
return extract_final_answer(response)
action = parse_action(response)
if action:
observation = await execute_tool(action, tools)
messages.append({
"role": "user",
"content": f"Observation: {observation}"
})Advantages:
- Explicit reasoning traces aid debugging
- More interpretable decision-making
- Better handling of complex multi-step tasks
ReAct(推理与行动)模式在思考和行动之间交替进行。
python
REACT_PROMPT = """Answer the question using the available tools.
For each step:
1. Thought: Reason about what to do next
2. Action: Choose a tool and inputs
3. Observation: See the result
4. Repeat until you have the answer
Available tools: {tools}
Question: {question}
"""
async def react_agent(question, tools):
prompt = REACT_PROMPT.format(
tools=format_tools(tools),
question=question
)
messages = [{"role": "user", "content": prompt}]
while True:
response = await llm.generate(messages)
messages.append({"role": "assistant", "content": response})
if "Final Answer:" in response:
return extract_final_answer(response)
action = parse_action(response)
if action:
observation = await execute_tool(action, tools)
messages.append({
"role": "user",
"content": f"Observation: {observation}"
})优势:
- 明确的推理轨迹有助于调试
- 决策过程更具可解释性
- 更擅长处理复杂的多步骤任务
Tool Design
工具设计
Principles
设计原则
- Self-contained: Tools return complete, usable information
- Scoped: Each tool does one thing well
- Descriptive: Clear names and descriptions guide the LLM
- Error-robust: Return informative errors, not exceptions
- 独立完整:工具返回完整、可用的信息
- 职责单一:每个工具专注做好一件事
- 描述清晰:明确的名称和描述引导LLM正确调用
- 容错性强:返回有信息量的错误信息,而非抛出异常
Tool Definition Pattern
工具定义模式
python
class Tool:
def __init__(self, name: str, description: str, parameters: dict, fn):
self.name = name
self.description = description
self.parameters = parameters
self.fn = fn
async def execute(self, **kwargs):
try:
return await self.fn(**kwargs)
except Exception as e:
return f"Error: {str(e)}"python
class Tool:
def __init__(self, name: str, description: str, parameters: dict, fn):
self.name = name
self.description = description
self.parameters = parameters
self.fn = fn
async def execute(self, **kwargs):
try:
return await self.fn(**kwargs)
except Exception as e:
return f"Error: {str(e)}"Example tool
Example tool
search_tool = Tool(
name="search_database",
description="Search the database for records matching a query. "
"Returns up to 10 matching records with their IDs and summaries.",
parameters={
"query": {"type": "string", "description": "Search query"},
"limit": {"type": "integer", "description": "Max results (default 10)"},
},
fn=search_database
)
undefinedsearch_tool = Tool(
name="search_database",
description="Search the database for records matching a query. "
"Returns up to 10 matching records with their IDs and summaries.",
parameters={
"query": {"type": "string", "description": "Search query"},
"limit": {"type": "integer", "description": "Max results (default 10)"},
},
fn=search_database
)
undefinedTool Interface Guidelines
工具接口指南
- Prefer text inputs/outputs over complex structured data
- Include usage examples in descriptions for ambiguous tools
- Return truncated results when output could be large
- Provide clear feedback on what the tool did
- 优先使用文本输入/输出,而非复杂的结构化数据
- 对于模糊的工具,在描述中包含使用示例
- 当输出可能过大时,返回截断后的结果
- 清晰反馈工具执行的操作
Best Practices
最佳实践
-
Start simple: Begin with the simplest architecture that could work. Add complexity only when it demonstrably improves outcomes.
-
Maintain transparency: Ensure the agent's planning steps are visible. This aids debugging and builds user trust.
-
Design for failure: Agents will make mistakes. Include guardrails, retries, and graceful degradation.
-
Test extensively: Use sandboxed environments. Test edge cases and failure modes, not just happy paths.
-
Limit tool proliferation: More tools means more confusion. Keep the tool set focused and well-documented.
-
Implement checkpoints: For long-running tasks, save state periodically to enable recovery.
-
Set resource limits: Cap iterations, token usage, and tool calls to prevent runaway agents.
-
Log everything: Record all LLM calls, tool executions, and decisions for debugging and improvement.
-
Handle ambiguity: When uncertain, have the agent ask for clarification rather than guessing.
-
Measure outcomes: Track task completion rates, accuracy, and efficiency to guide improvements.
-
从简入手:从最简单的可行架构开始。仅当复杂度能切实提升效果时,再逐步增加。
-
保持透明:确保Agent的规划步骤可见。这有助于调试并建立用户信任。
-
容错设计:Agent会犯错。需包含防护措施、重试机制和优雅降级方案。
-
全面测试:使用沙箱环境。测试边缘情况和故障模式,而非仅测试正常流程。
-
限制工具数量:工具越多越容易混淆。保持工具集聚焦且文档完善。
-
实现检查点:对于长时间运行的任务,定期保存状态以支持恢复。
-
设置资源限制:限制迭代次数、Token使用量和工具调用次数,防止Agent失控。
-
完整日志:记录所有LLM调用、工具执行和决策,用于调试和改进。
-
处理歧义:当不确定时,让Agent请求澄清而非猜测。
-
衡量结果:跟踪任务完成率、准确性和效率,以指导优化。
References
参考资料
- Building Effective Agents - Anthropic's guide to agent patterns and best practices
- LangGraph Workflows & Agents - LangGraph documentation on agent architectures
- ReAct: Synergizing Reasoning and Acting - Paper introducing the ReAct prompting pattern
- Building Effective Agents - Anthropic关于Agent模式和最佳实践的指南
- LangGraph Workflows & Agents - LangGraph关于Agent架构的文档
- ReAct: Synergizing Reasoning and Acting - 介绍ReAct提示词模式的论文