Appearance
Agent 护栏与安全
本节介绍如何通过护栏(Guardrails)确保 Agent 在生产环境中安全、可预测地运行。
什么是护栏
护栏是帮助确保 Agent 在生产环境中安全、可预测运行的机制。它们充当 Agent 的防护措施,定义允许的行为边界并防止不良结果。
护栏的核心作用
| 作用 | 说明 |
|---|---|
| 定义边界 | 明确 Agent 可以和不可以做什么 |
| 防止越界 | 阻止意外或危险的操作 |
| 异常处理 | 当 Agent 行为超出预期时触发处理机制 |
护栏的两个阶段
护栏可以在两个关键阶段部署:
| 阶段 | 描述 |
|---|---|
| 输入护栏 | 在处理用户输入之前验证输入的 relevance、safety 和格式 |
| 输出护栏 | 在响应用户之前验证输出的 safety 和质量 |
用户输入 → [输入护栏检查] → Agent 处理 → [输出护栏检查] → 用户输出指令与护栏的关系
护栏是运行时防护机制,指令是静态行为规则。两者相辅相成——详见第 4 篇:Agent 设计基础的「配置指令」章节。
输入护栏
输入护栏在用户消息到达 Agent 之前对其进行评估。
实现示例
python
from agents import (
Agent,
GuardrailFunctionOutput,
InputGuardrailTripwireTriggered,
RunContextWrapper,
Runner,
TResponseInputItem,
input_guardrail,
Guardrail,
)
from pydantic import BaseModel
class ChurnDetectionOutput(BaseModel):
is_churn_risk: bool
reasoning: str
churn_detection_agent = Agent(
name="Churn Detection Agent",
instructions="Identify if the user message indicates a potential customer churn risk.",
output_type=ChurnDetectionOutput,
)
@input_guardrail
async def churn_detection_tripwire(
ctx: RunContextWrapper[None],
agent: Agent,
input: str | list[TResponseInputItem],
) -> GuardrailFunctionOutput:
result = await Runner.run(
churn_detection_agent,
input,
context=ctx.context,
)
return GuardrailFunctionOutput(
output_info=result.final_output,
tripwire_triggered=result.final_output.is_churn_risk,
)
customer_support_agent = Agent(
name="Customer Support Agent",
instructions="You are a customer support agent. You help customers with their questions.",
input_guardrails=[
Guardrail(guardrail_function=churn_detection_tripwire),
],
)
async def main():
# 正常请求应该通过
await Runner.run(customer_support_agent, "Hello!")
print("Hello message passed")
# 风险请求应该触发护栏
try:
await Runner.run(
customer_support_agent,
"I think I might cancel my subscription",
)
except GuardrailTripwireTriggered:
print("Churn detection guardrail tripped")护栏策略类型
| 策略 | 说明 |
|---|---|
| 防止越狱 | 检测和阻止试图绕过安全限制的输入 |
| 相关性验证 | 确保用户输入与 Agent 的职责相关 |
| 关键词过滤 | 检测和过滤敏感关键词 |
| 黑名单执行 | 阻止已知的恶意输入模式 |
| 安全分类 | 对输入进行安全级别分类 |
输出护栏
输出护栏在响应用户之前验证 Agent 输出的安全性和质量。
常见用途
| 用途 | 说明 |
|---|---|
| 内容审核 | 确保输出不包含不当内容 |
| 格式验证 | 确保输出符合预期格式 |
| 事实检查 | 验证输出中的关键信息准确性 |
人工干预计划
人工干预是一项关键保障,使您能够在不影响用户体验的情况下提高 Agent 的实际性能。
为什么需要人工干预
- 在部署早期尤为重要
- 帮助识别故障
- 发现边缘案例
- 建立稳健的评估周期
人工干预的触发条件
| 条件 | 说明 |
|---|---|
| 超过失败阈值 | 设置 Agent 重试或操作次数的限制。如果 Agent 超过这些限制(例如多次尝试后仍无法理解客户意图),升级进行人工干预 |
| 高风险操作 | 敏感、不可逆或高风险的操作应该触发人工监督。例如:取消用户订单、授权大额退款、进行支付 |
实现机制
┌─────────────────────────────────────┐
│ Agent 执行 │
└─────────────────┬───────────────────┘
│
▼
┌─────────────────┐
│ 风险/失败评估 │
└────────┬────────┘
│
┌─────────┴─────────┐
▼ ▼
[正常继续] [触发人工干预]
│
▼
┌─────────────┐
│ 人工审核 │
└─────────────┘Agent 自主性的权衡
Agent 的自主性意味着:
- 更高的灵活性
- 更高的成本和错误累积可能性
建议
| 建议 | 说明 |
|---|---|
| 沙盒环境测试 | 在沙盒环境中进行广泛测试 |
| 设置适当的护栏 | 限制 Agent 的行动范围 |
| 渐进式部署 | 从小处着手,用真实用户验证 |
| 持续监控 | 监控 Agent 行为并及时干预 |
Agent 评估
Agent 的非确定性行为使得评估比传统软件更复杂。以下是核心评估维度:
评估维度
| 维度 | 方法 | 指标 |
|---|---|---|
| 任务完成率 | 用标准测试用例集执行,检查是否正确完成 | 成功百分比 |
| 工具使用正确性 | 检查 Agent 是否在正确时机调用正确的工具 | 工具调用准确率 |
| 路径效率 | 检查 Agent 是否走了不必要的弯路 | 平均调用轮数 |
| 错误恢复 | 在工具失败时观察 Agent 是否尝试替代方案 | 恢复成功率 |
| 安全性 | 测试恶意输入、越狱尝试、敏感数据泄露 | 护栏触发率 |
评估流程
- 构建测试集:收集 50~200 个代表性场景及其预期结果
- 自动化运行:批量执行测试用例,记录每步输出
- 人工抽检:对运行结果进行人工评分(尤其是错误案例)
- 迭代优化:根据失败模式调整工具设计、指令或模型
工具推荐
- LangSmith / Weights & Biases:追踪 Agent 调用轨迹、可视化评估结果
- 自定义评估脚本:用断言检查 Agent 的最终输出和工具调用序列
python
def evaluate_agent(agent, test_cases: list[dict]) -> dict:
"""简单的评估函数"""
passed = 0
for case in test_cases:
result = Runner.run(agent, case["input"])
expected_tools = case["expected_tools"]
actual_tools = [step.tool_name for step in result.steps]
if set(expected_tools).issubset(set(actual_tools)):
passed += 1
return {"pass_rate": passed / len(test_cases), "passed": passed, "total": len(test_cases)}总结
构建可靠 Agent 的安全原则:
| 原则 | 说明 |
|---|---|
| 护栏全程覆盖 | 从输入过滤到工具使用再到人工干预 |
| 保持可预测性 | 确保 Agent 在明确定义的边界内运行 |
| 计划人工监督 | 为高风险操作设置人工审核机制 |
| 渐进式演进 | 从小处着手,逐步增加自主性 |
一句话总结:护栏是 Agent 的"安全带"——平时感觉不到,但关键时刻能救命。
