💡 摘要:Agent 的核心能力之一是调用工具,但"有能力调用"不等于"应该调用"。本文探讨 Agent 何时应该拒绝使用工具,以及如何通过 System Prompt、工具描述和条件边来引导 Agent 做出正确判断。
引言
很多人初学 Agent 时,会陷入一个误区:既然给了 Agent 一堆工具,那它就应该尽量多用。
但现实恰恰相反------好的 Agent 知道什么时候不用工具。
想象这些场景:
- 用户问"1+1等于几",Agent 却去调用计算器 API
- 用户说"你好",Agent 却去查用户画像数据库
- 用户问"Python 的 list 怎么排序",Agent 却去搜索 Google
这些场景不仅浪费时间和金钱,还会让用户体验变得糟糕。
核心原则只有一条:只有当 LLM 自身无法可靠回答,或者工具能显著提升回答质量时,才应该调用工具。
核心概念
一、应该拒绝工具调用的 8 种场景
| 场景 | 说明 | 示例 |
|---|---|---|
| 常识性问题 | 模型预训练时已经学过 | "中国的首都是哪里?" |
| 简单推理 | 不需要计算或外部数据 | "苹果是水果还是蔬菜?" |
| 闲聊/创作 | 不涉及工具能力 | "帮我写一首诗"、"你好" |
| 工具成本过高 | 付费 API 或增加明显延迟 | 简单问题却调用付费搜索 API |
| 工具可能有副作用 | 写操作、发送通知等 | 未经确认就发邮件、删文件 |
| 工具可靠性低 | 可能返回错误或过时信息 | 依赖一个经常宕机的第三方 API |
| 用户明确要求 | 用户说"别查了,直接告诉我" | 尊重用户意愿 |
| 工具不适用 | 问题与工具能力无关 | 问天气却调用了数据库查询工具 |
二、Agent 如何做出判断
Agent 判断是否调用工具,主要依赖三个机制:
┌─────────────────────────────────────────┐
│ Agent 决策流程 │
├─────────────────────────────────────────┤
│ │
│ 1. System Prompt 中的指导规则 │
│ ↓ │
│ 2. 工具描述中的适用/不适用条件 │
│ ↓ │
│ 3. ReAct 思考步骤(Thought → Action) │
│ ↓ │
│ 4. 条件边:走工具路径 or 直接回答路径 │
│ │
└─────────────────────────────────────────┘
代码示例
1. System Prompt:引导 Agent 何时用/不用工具
python
system_prompt = """你是一个智能助手,拥有以下工具:
- search_web: 搜索互联网获取实时信息
- calculator: 执行复杂数学计算
## 工具使用原则
### 应该使用工具的情况:
- 用户询问实时信息(天气、新闻、股价)
- 需要精确计算(财务、统计、科学计算)
- 需要获取用户个人数据(订单、历史记录)
### 不应该使用工具的情况:
- 常识性问题(历史、地理、科学常识)
- 简单的数学运算(心算即可)
- 闲聊、问候、创意写作
- 用户明确要求"直接回答"时
### 判断流程:
1. 先思考:我能否凭借自身知识可靠回答?
2. 如果能 → 直接回答,不调用工具
3. 如果不能 → 选择最合适的工具
4. 如果工具可能有副作用 → 先征求用户同意
"""
2. 工具描述:包含正向和反向场景
python
from langchain.tools import tool
@tool
def search_web(query: str) -> str:
"""搜索互联网获取实时信息。
适用场景:
- 查询实时天气、新闻、股价
- 获取最新的产品信息或价格
- 查找模型训练数据截止后发生的事件
不适用场景:
- 历史事件(如"二战什么时候结束")
- 科学常识(如"水的化学式是什么")
- 数学计算(请使用 calculator 工具)
- 用户的主观感受或意见类问题
Args:
query: 搜索关键词,应简洁明确
"""
# 实际搜索逻辑
return results
3. LangGraph 条件边:默认不走工具路径
python
from langgraph.graph import StateGraph, END
from langchain.agents import AgentState
def should_use_tool(state) -> str:
"""条件边:判断是否应该调用工具"""
last_message = state["messages"][-1]
# 如果 LLM 决定调用工具
if hasattr(last_message, "tool_calls") and last_message.tool_calls:
return "use_tool"
# 默认路径:直接回答,不调用工具
return "direct_answer"
# 构建工作流
workflow = StateGraph(AgentState)
workflow.add_node("agent", call_model)
workflow.add_node("tools", call_tools)
# 条件边:根据判断走不同路径
workflow.add_conditional_edges(
"agent",
should_use_tool,
{
"use_tool": "tools", # 需要工具 → 走工具节点
"direct_answer": END, # 不需要工具 → 直接结束
}
)
workflow.set_entry_point("agent")
app = workflow.compile()
4. 完整示例:带成本意识的 Agent
python
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
class AgentState(TypedDict):
messages: Annotated[list, operator.add]
tool_cost_estimate: float # 估算工具调用成本
def call_model(state: AgentState):
response = model.invoke(state["messages"])
return {"messages": [response]}
def should_use_tool(state: AgentState) -> str:
last_message = state["messages"][-1]
# 检查是否有工具调用意图
if not hasattr(last_message, "tool_calls"):
return "direct_answer"
# 检查成本:如果预估成本过高,再次确认
if state.get("tool_cost_estimate", 0) > 0.1:
# 可以在这里加入用户确认逻辑
return "confirm_with_user"
return "use_tool"
# 构建带成本控制的 Agent
workflow = StateGraph(AgentState)
workflow.add_node("agent", call_model)
workflow.add_node("tools", call_tools)
workflow.add_node("confirm", ask_user_confirmation)
workflow.add_conditional_edges(
"agent",
should_use_tool,
{
"use_tool": "tools",
"confirm_with_user": "confirm",
"direct_answer": END,
}
)
workflow.add_edge("confirm", "tools") # 用户确认后执行
workflow.add_edge("tools", END)
workflow.set_entry_point("agent")
app = workflow.compile()
最佳实践
1. 用 System Prompt 明确指导
System Prompt 是引导 Agent 行为的第一道防线。明确列出"应该用"和"不应该用"的场景,让模型在决策时有据可依。
✅ 好的做法:
"对于常识性问题,直接回答,不要调用工具"
❌ 不好的做法:
"你可以使用搜索工具"(没有说明何时不用)
2. 在工具描述中加入反向场景
工具的 docstring 不仅是说明文档,更是 Agent 决策的依据。明确写出"不适用场景",能显著减少误调用。
python
@tool
def my_tool():
"""工具描述。
适用:...
不适用:... ← 这部分很重要!
"""
3. 优先使用模型自身知识
模型预训练时已经学到了大量知识。对于这些问题,直接回答比调用工具更快、更便宜、更可靠。
判断标准:
- 模型训练数据截止前就已确定的事实 → 直接回答
- 需要实时性或精确性的信息 → 调用工具
- 简单推理和创作 → 直接回答
- 需要外部系统交互 → 调用工具
4. 为有副作用的工具加确认机制
写操作(发邮件、删文件、修改数据)应该有"确认环节",避免 Agent 自作主张。
python
def should_execute_write_operation(state):
"""写操作需要用户确认"""
if state["pending_action"]["type"] == "write":
return "ask_confirmation"
return "execute"
5. 监控工具调用的 ROI
每次工具调用都有成本(API 费用、延迟、错误风险)。定期审视:
- 哪些工具调用是"不必要的"?
- 哪些工具返回的信息模型本身就知道?
- 工具调用是否显著提升了回答质量?
总结
Agent 不是"工具用得越多越好",而是"该用时用,不该用时果断拒绝"。
记住三个关键点:
- System Prompt 是方向盘:明确告诉模型何时用、何时不用工具
- 工具描述是说明书:包含正向和反向场景,帮助模型做出正确判断
- 条件边是分流器:让 Agent 有"直接回答"的默认路径,而不是强制走工具
好的 Agent 像一个经验丰富的专家------知道什么时候该查资料,什么时候凭经验就能给出答案。