【Agent Harness实战】我给 Agent 装了一套“神经系统”,它现在比我还敏感

我给 Agent 装了一套“神经系统”,它现在比我还敏感

前几篇聊了 Agent 怎么编排调度、怎么用 5W2H 和 PDCA 做认知框架、以及四层记忆系统怎么让它永不“失忆”。

但有个问题一直没展开:SA 调度器怎么知道系统出问题了?

DA 卡住了怎么办?任务超时了怎么办?输出质量越来越差怎么办?用户突然说“你搞错了”又怎么办?

答案是:感知系统。 今天聊聊我给 Agent OS 装上的这套“神经系统”——它不是简单的“如果-那么”规则,而是 10 种感知触发器、缓存去重、5W2H 约束检查、经验自动提取,组合成的一整套主动感知引擎。


一、先讲个翻车现场

假设你让 AI 分析 Q2 销售数据。

它吭哧吭哧跑了 20 分钟没动静。你以为它死机了,但其实它还在跑——只是卡在一个错误的 SQL 查询里无限重试。

再比如,它终于给你结果了,但你一看:增长率 200%?怎么可能。你追问“你确定吗?”它回“代码逻辑没问题”——其实它把 Q1 数据也加进去了。

这些问题不是 AI 笨,是它没有“自我感知”能力。 它不知道自己在兜圈子,不知道输出质量在下降,不知道你已经开始怀疑它的结果。

传统解决方案是加一堆 if-else:超时了就重试,报错了就回滚。但真实系统复杂得多——你不可能预判所有异常。

我的做法:给 SA 装上“神经系统”,让它能像人一样感知状态,而不是盲等结果。


二、10 种感知触发器:从任务开始到结束,全程无死角

感知系统不是一个大而全的“监控模块”,而是嵌在任务执行流程里的 10 个关键感知点。每个点触发时,引擎会分析当前状态,决定是否需要干预。

graph TB subgraph "任务生命周期" START["任务开始"] --> PLAN["计划完成"] PLAN --> EXEC["执行中"] EXEC --> CHECK["审查完成"] CHECK --> END["任务结束"] end subgraph "10 种感知触发器" T1["TaskStart<br/>复杂度分析 + 经验检索"] T2["PlanCompleted<br/>子任务数检查"] T3["ProgressAnomaly<br/>进度异常去重检测"] T4["CheckCompleted<br/>审查失败告警"] T5["TaskEnd<br/>经验提取"] T6["CycleTimeout<br/>周期超时"] T7["AgentBlocked<br/>Agent 阻塞"] T8["ResourceConflict<br/>资源冲突"] T9["QualityDegradation<br/>质量下降"] T10["UserFeedback<br/>用户反馈"] end START --> T1 PLAN --> T2 EXEC --> T3 & T6 & T7 & T8 & T9 CHECK --> T4 END --> T5 EXEC --> T10

这 10 种触发器覆盖了任务的完整生命周期,以及最常见的异常场景。


三、任务开始:不只启动,还要“审题”和“翻旧账”

触发器:TaskStart

SA 接到新任务时,感知引擎做的第一件事不是直接开工,而是:

  1. 复杂度分析:根据用户输入的长度自动判断

    • 少于 50 个字 → simple,推荐直接 DA 执行
    • 少于 200 个字 → medium,推荐标准 PDCA
    • 超过 200 个字 → complex,推荐递归 PDCA
  2. 经验检索:从 L0 图数据库里搜标签为 experience 的历史记录

    • 比如当前任务是“分析 Q2 销售数据”,引擎会搜“销售分析”、“Q2”、“数据分析”相关的历史经验
    • 找到历史上类似任务的成功策略、踩过的坑,注入到 SA 的决策上下文里
// 实际的复杂度判断逻辑
fn analyze_task(&self, user_input: &str) -> TaskAnalysis {
    let input_len = user_input.len();
    let (complexity, steps) = if input_len < 50 {
        ("simple", 1)       // 直接 DA
    } else if input_len < 200 {
        ("medium", 3)       // 标准 PDCA
    } else {
        ("complex", 5)      // 递归 PDCA
    };
    // ...
}

这套机制让 SA 不是“盲启”,而是带着历史经验上阵。


四、进度异常:同一个错误,别喊我两次

触发器:ProgressAnomaly

执行过程中,SA 检测到异常时触发。但这里有个关键设计:去重窗口。

如果一个 DA 在 60 秒内反复报同一个错误,感知引擎只处理第一次,后面直接标记 already_handled

为什么?防止告警风暴。 一个 Agent 卡住时可能每秒都在报同样的错,如果每次都触发干预,SA 会被淹死。

fn on_progress_anomaly(&mut self, anomaly: &Value) -> InterventionPlan {
    // 60 秒内相同异常的重复直接跳过
    if self.anomaly_history.iter().any(|(desc, time)| {
        desc == anomaly_description 
        && now - time < 60_seconds
    }) {
        return InterventionPlan::already_handled();
    }
    // 记录并处理新异常
    self.anomaly_history.push((desc, Utc::now()));
    InterventionPlan::new("重新评估计划", "考虑额外资源", priority: high)
}

去重窗口是 60 秒,超时的旧记录会被自动清理。


五、5W2H 约束检查:别光埋头干,抬头看看表

方法:check_5w2h_constraints

这可能是感知系统里最“工程化”的设计。任务创建时有 5W2H 元数据,里面包含了截止时间和 Token 预算。感知引擎会在执行过程中持续检查这两个硬约束。

截止时间检查:

  • 如果设置了截止时间 + 提醒提前量(比如提前 1 小时提醒),引擎会在快到期时自动返回 DEADLINE_APPROACHING
  • 如果已经超时,返回 DEADLINE_EXCEEDED

预算检查:

  • 如果任务定义了 Token 预算,引擎会对比实际消耗
  • 消耗超过预算的 80% 时,返回 BUDGET_EXCEEDED
fn check_5w2h_constraints(&self, five_w2h_iri: &str) -> Option<String> {
    let node = self.l0.load_node(five_w2h_iri)?;
    
    // 检查截止时间
    if let (Some(deadline), Some(reminder)) = 
       (node.get("task:when/task:deadline"), node.get("task:when/task:reminderBefore")) {
        let remaining = deadline - Utc::now();
        let reminder_duration = parse_iso8601_duration(reminder);
        if remaining < Duration::zero() {
            return Some("DEADLINE_EXCEEDED");
        } else if remaining < reminder_duration {
            return Some("DEADLINE_APPROACHING");
        }
    }
    
    // 检查预算
    if let (Some(budget), Some(used)) = 
       (node.get("task:howMuch/task:tokenBudget"), node.get("task:howMuch/task:actualCost/tokensUsed")) {
        if used > budget * 0.8 {
            return Some("BUDGET_EXCEEDED");
        }
    }
    
    None
}

这套约束检查让 Agent 不是“闷头干活”,而是时刻知道自己还剩多少时间、多少预算。


六、质量下降:当输出越来越水

触发器:QualityDegradation

执行过程中,如果检测到输出质量在下降(比如连续几轮 CA 审查都不通过、错误率上升),触发此感知。

引擎会生成干预计划,建议:

  • 回滚到上一个检查点
  • 使用不同方法重试
  • 通知用户介入

这就像健身时教练突然喊停——“你这个姿势不对,换一个。”


七、任务结束:不止交差,还要“写总结”

触发器:TaskEnd

任务结束时(不管是成功还是失败),感知引擎会自动提取经验

  • 从任务结果中抽取场景摘要
  • 创建 Experience 对象,成功给 0.9 分,失败给 0.1 分
  • 打上标签(experiencetask:任务IDstatus:success/failed
  • 存入 L0 图数据库

下次同类任务启动时,TaskStart 触发器会自动检索这些经验,注入给 SA。 整个系统形成了一个“经验 → 检索 → 应用 → 再提取经验”的正向循环。

{
  "@id": "experience:task-042",
  "@type": "Experience",
  "scenario": "Q2 销售数据分析,使用 Python 分析 + 预测模型",
  "success_rating": 0.9,
  "tags": ["experience", "task:sales-q2", "status:success", "data-analysis"]
}

八、缓存与去重:告警不刷屏,经验不重复

感知系统有两个重要的性能设计:

结果缓存:

  • 分析结果默认缓存 5 分钟(300 秒)
  • 同一个 TaskStart 在 5 分钟内重复触发,直接返回缓存结果
  • 最大缓存 1000 条,超过就淘汰最老的

异常去重:

  • 60 秒内相同的异常只处理一次
  • 旧异常记录 2 分钟后自动清理

为什么这么设计? 感知引擎不是监控系统,不需要每秒钟都分析。它只需要在关键节点状态变化时介入。


九、完整工作流:感知系统 + SA 的配合

sequenceDiagram participant SA participant PE as 感知引擎 participant LLM participant L0 SA->>PE: on_task_start(任务输入) PE-->>SA: TaskAnalysis {复杂度, 经验提示} SA->>PE: on_plan_completed(计划) PE-->>SA: AdvisoryNode 列表 loop 步骤执行中 SA->>PE: check_5w2h_constraints(任务IRI) alt 截止时间快到了 PE-->>SA: "DEADLINE_APPROACHING" SA->>SA: 调整策略,加速执行 end alt Token 快花完了 PE-->>SA: "BUDGET_EXCEEDED" SA->>SA: 启用更省 Token 的模式 end end 事件触发->>PE: 进度异常 PE-->>SA: InterventionPlan(含建议动作) SA->>LLM: 将干预建议转为决策 LLM-->>SA: 选择最佳干预动作 SA->>SA: 执行干预 SA->>PE: on_check_completed(审查结果) PE-->>SA: 告警或通过 SA->>PE: on_task_end(任务结果) PE->>L0: 存储经验 PE-->>SA: 经验对象

十、总结:感知系统给 Agent OS 带来的三个质变

  1. 从“盲等”到“感知”:SA 不是等 DA 自己汇报,而是在关键节点主动检查——进度、质量、资源,全在掌控中
  2. 从“一次性”到“持续进化”:每次任务结束后自动提取经验,下次同类任务自动注入,系统越用越聪明
  3. 从“崩溃后补救”到“提前干预”:截止时间快到了就加速,Token 快花完了就切换模式,质量下降了就换方法——不是等死了再抢救

这套感知系统的本质,是把 Agent 从“一次性提示工程对象”变成了“有自我意识的长期运行进程”。 它知道自己在做什么、还剩多少资源、质量是好是坏、历史上类似任务是怎么做的。


十一、预告

下一篇聊 Skill Graph——技能不是 Markdown 文件,而是 JSON-LD 图节点。200 多个 Skill 怎么互相发现、怎么组合、怎么自动找到替代方案。这是一个把 Skills 从“死文档”变成“活网络”的设计。


我这套系统叫 Gliding Horse(流马),所有代码都在 GitHub 上:https://github.com/doiito/gliding_horse

设计细节系列持续更新中。前面聊了编排调度、认知框架、记忆系统,这篇聊了感知系统,下一篇聊 Skill Graph。想看什么在 Issue 里说。

posted @ 2026-06-14 10:50  doiito  阅读(0)  评论(0)    收藏  举报