开源 人工智能 工具链开发与轻量化 智能体 产品设计:把经验沉淀成下一次的规则

一个常见的 Agent 失败模式是:工具返回错误后,模型持续生成相同或近似的调用,直到耗尽调用预算。仅靠临时调整 Prompt 往往难以避免下一次出现相似问题。
更可持续的做法是把故障样本转为规则、回归用例和运行时限制,让每次复盘都能影响后续行为。
线上 Agent 异常的归因与规则化演进
Agent 故障通常不是模型能力单独造成的,而是工具链的输入输出约束和决策边界存在缺口。
典型的死循环往往发生在以下场景:Agent 调用的第三方 API 格式变更、用户输入了超出预期的结构化数据、或者 Tool 返回的错误信息过于模糊。模型收到的 Error Message 没有明确指示“停止”或“调整策略”,导致它按照固有逻辑不断重试。
传统的软件工程依靠“单元测试 + Code Review”保证稳定性。而轻量化 Agent 的稳定性,很大程度上取决于 Prompt 规则、Tool 契约与运行时拦截闸门三者的配合。我们需要把每次线上捕获的异常,转化成可自动化校验的规则约束。
线上日志先用于异常归因,再将可复现的问题写入版本化规则库,并让规则在后续发布中自动校验。
这套流程的关键在于:不要把规则散落写在代码的各个角落,而是构建集中化的规则契约库。每次复盘出的 Bad Case,都要编写一个对应的回归测试用例,确保后续调整 Prompt 时不会引发旧问题的复发。
生产级 Agent 规则版本化管理与防死循环闸门
为了在运行时彻底防止 Agent 盲目重试和 Tool Calling 滥用,我们在 Agent 工具链的 Gateway 层实现了一套规则管理器。
下面的 TypeScript 代码展示了如何管理动态规则、检测规则冲突,并在 Agent 执行工具调用时提供确定性的重试与断路防护。
import { EventEmitter } from 'events';
// 规则定义接口
export interface AgentRule {
id: string;
description: string;
maxToolCalls: number;
forbiddenPatterns: RegExp[];
fallbackResponse: string;
version: string;
}
// 执行上下文
export interface ExecutionContext {
sessionId: string;
toolCallCount: Map<string, number>;
historyInput: string[];
}
export class AgentRuleEngine extends EventEmitter {
private rules: Map<string, AgentRule> = new Map();
constructor() {
super();
}
// 注册新规则,带版本控制与冲突检测
public registerRule(rule: AgentRule): void {
if (!rule.id || rule.maxToolCalls <= 0) {
throw new Error(`[RuleEngine] 无效的规则配置: ${JSON.stringify(rule)}`);
}
if (this.rules.has(rule.id)) {
const existing = this.rules.get(rule.id)!;
console.warn(`[RuleEngine] 覆写已存在的规则 [${rule.id}] v${existing.version} -> v${rule.version}`);
}
this.rules.set(rule.id, rule);
this.emit('rule_updated', rule);
}
// 检查 Agent 当前行为是否触犯规则防护网
public validateToolCall(
ruleId: string,
toolName: string,
inputPayload: string,
ctx: ExecutionContext
): { allowed: boolean; reason?: string; fallback?: string } {
const rule = this.rules.get(ruleId);
if (!rule) {
// 找不到规则时默认放行,但记录告警
console.error(`[RuleEngine] 未找到指定规则: ${ruleId}`);
return { allowed: true };
}
// 1. 检查输入是否命中禁忌模式(例如 SQL 注入风险或非法字符)
for (const pattern of rule.forbiddenPatterns) {
if (pattern.test(inputPayload)) {
this.emit('rule_violation', { ruleId, toolName, type: 'FORBIDDEN_PATTERN', inputPayload });
return {
allowed: false,
reason: `输入命中了安全禁忌规则: ${pattern.toString()}`,
fallback: rule.fallbackResponse,
};
}
}
// 2. 检查特定 Tool 的调用次数上限,防止死循环
const currentCalls = ctx.toolCallCount.get(toolName) || 0;
if (currentCalls >= rule.maxToolCalls) {
this.emit('rule_violation', { ruleId, toolName, type: 'EXCEEDED_MAX_CALLS', count: currentCalls });
return {
allowed: false,
reason: `工具 [${toolName}] 调用次数已达上限 (${rule.maxToolCalls} 次),已强制截断`,
fallback: rule.fallbackResponse,
};
}
// 记录递增
ctx.toolCallCount.set(toolName, currentCalls + 1);
return { allowed: true };
}
}
// 生产使用示例
const engine = new AgentRuleEngine();
// 注册从月度复盘中沉淀出的日志查询规则
engine.registerRule({
id: 'log_analysis_safety_v2',
description: '限制日志分析 Tool 的重复调用,禁止执行恶意删除语法',
maxToolCalls: 3,
forbiddenPatterns: [/DROP\\s+TABLE/i, /DELETE\\s+FROM/i, /rm\\s+-rf/i],
fallbackResponse: '系统检测到操作包含高危指令或频繁重试,任务已安全的降级停止。',
version: '2.1.0',
});
// 模拟 agent 运行上下文
const context: ExecutionContext = {
sessionId: 'sess_102948',
toolCallCount: new Map(),
historyInput: [],
};
// 模拟连续触发死循环调用
for (let i = 1; i <= 4; i++) {
const result = engine.validateToolCall('log_analysis_safety_v2', 'query_log_db', 'SELECT * FROM logs', context);
if (!result.allowed) {
console.log(`第 ${i} 次调用拦截: ${result.reason}`);
console.log(`输出降级响应: ${result.fallback}`);
break;
} else {
console.log(`第 ${i} 次调用通过`);
}
}
代码里有两个核心取舍:首先,不把重试控制权完全交给大模型。模型在面对复杂 Error 时很难自发停止,必须由外部 Engine 维护计次与匹配。其次,规则支持独立加载与版本追踪。每月的月度复盘后,团队只需要增加或更新规则配置文件,无需重构整个 Agent 的主体架构。
建立月度回顾机制的具体操作建议
要把经验长效沉淀下来,团队需要固定一套轻量级的月度回顾流程:
轻量 Agent 产品设计的核心,不在于第一版有多聪明,而在于它是否具备快速消化线上踩坑经验的能力。用规则库锁住下限,模型才能安心发挥上限。

