AI 浏览器智能体可观测性(二):监控与告警——HTTP 200 不代表任务成功

HTTP 状态码 200、P95 延迟正常、没有报错——但智能体提取的数据是空的。传统监控在 AI 浏览器自动化面前基本失效,需要完全不同的监控维度。

亿牛云技术团队2026年4月22日4 分钟阅读

看似正常的仪表盘

我刚接手一套 AI 浏览器自动化的生产系统时,花了两天盯着监控面板。HTTP 200 率 99.9%,P95 响应时间 200ms,无 5xx 错误——看起来一切正常。

但业务侧在抱怨:数据采集不完整、商品价格没有更新。我查了查后端的记录,发现每个任务都"成功"了,但提取的数据字段有一半是空的。

问题出在:智能体可能完成了导航(HTTP 200),但没找到目标元素(提取失败)。传统监控认为这是成功——请求发出了,响应收到了,HTTP 状态码 200。但从业务角度来看,任务失败了。

为什么传统监控指标在智能体面前失效了

HTTP 状态码反映的是服务端的健康度,不是智能体的任务完成度。一个典型的例子:

# 智能体的一个"成功"的 HTTP 请求
HTTP 200, body: {"status": "ok"}  
# 但智能体在上一步提取数据时,因为页面改版没找到价格字段
# 它重试了 10 次,每次 HTTP 都返回 200,每次都找不到

传统监控的三个失效场景:

HTTP 200 + 空数据
  → 页面加载成功,但目标元素不存在
  → 监控认为正常,业务认为失败
 
P95 延迟正常 + 步数超标
  → 单次请求不慢,但智能体在同一步循环了 20 次
  → 监控认为正常,实际任务耗时翻了 4 倍
 
无 5xx + Validator 幻觉
  → 服务器没有报错,但 Validator 误判了任务状态
  → 监控认为正常,实际上操作未生效

这些不是偶然——它们是 AI 智能体的行为模式和传统服务的本质差异。智能体不是按"请求-响应"周期运行的,它是按"目标-尝试-验证"循环运行的。对这个循环的监控,需要完全不同的指标体系。

第一步:定义任务成功率的正确口径

传统监控的成功率 = HTTP 200 / 总请求数。这对智能体没有意义。

正确的口径是业务层面的:

class TaskOutcome:
    """任务的真实结果,不是 HTTP 状态码"""
    SUCCESS = "success"           # 数据完整,操作生效
    DEGRADED = "degraded"         # 成功但有降级(命中缓存、跳过可选字段)
    EXTRACTION_EMPTY = "empty"    # 页面加载了但目标数据是空的
    LOOP_DETECTED = "loop"        # 同一步操作循环了 N 次
    TIMEOUT = "timeout"           # 超过时间限制
    VALIDATOR_ERROR = "hallucination"  # Validator 报告成功但实际未生效

你的监控系统需要知道 EXTRACTION_EMPTYVALIDATOR_ERROR 的存在——HTTP 状态码不会告诉你这些。

第二步:检测智能体"卡住"的信号

智能体卡住是最常见的故障模式,有几种不同的表现形式:

循环卡住:智能体在同一页面上重复相同的操作序列(点击→检查→再点击→再检查),每次都得到相同的结果。

class LoopDetector:
    """检测操作序列中是否存在重复模式"""
    def __init__(self, window=5):
        self.window = window
 
    def check(self, action_history):
        if len(action_history) < self.window * 2:
            return False, 0.0
        recent = action_history[-self.window:]
        previous = action_history[-self.window*2:-self.window]
        similarity = self.calc_similarity(recent, previous)
        is_looping = similarity >= 0.8
        return is_looping, similarity
 
    def calc_similarity(self, a, b):
        """计算两组操作的动作相似度"""
        matches = sum(1 for x, y in zip(a, b)
                      if x.get("action") == y.get("action")
                      and x.get("selector") == y.get("selector"))
        return matches / max(len(a), 1)

步数爆炸卡住:每一步都"成功"了,但需要的步数远超正常值。正常提取需要 5 步,但智能体已经跑了 50 步还没完成:

class StepAnomalyDetector:
    """通过步数偏离检测智能体是否遇到困难"""
    def __init__(self):
        self.baseline_steps = {}  # task_type -> median_steps
 
    def record_step(self, task_type, step_count, success):
        if task_type not in self.baseline_steps:
            self.baseline_steps[task_type] = []
        self.baseline_steps[task_type].append(step_count)
 
    def is_anomalous(self, task_type, current_steps):
        baseline = self.baseline_steps.get(task_type, [])
        if len(baseline) < 10:
            return False  # 数据不够,不做判断
        median = sorted(baseline)[len(baseline) // 2]
        # 超过基线 3 倍视为异常
        return current_steps > median * 3, median

基线数据需要从历史任务中积累。如果某个任务类型的正常步数是 5-8 步,但当前任务跑了 30 步还没结束,说明智能体遇到了某种困难。

静默失败卡住:最危险的一种——智能体报告"成功"但什么都没做。开头说的"HTTP 200 + 空数据"就属于这一类。

第三步:给告警分级而不是一刀切

传统监控的告警逻辑通常是:出错就告警。对智能体来说,这个逻辑太粗暴了——AI 重试的成功率远高于传统服务。

class AlertManager:
    def __init__(self):
        self.alerts = []
 
    def evaluate(self, task_outcome):
        """根据任务结果决定告警级别和渠道"""
        if task_outcome == "loop":
            # 循环卡住:发到工作群,但不 pager
            self.notify_slack(f"任务进入循环: {task_outcome.task_id}")
            return "warning"
 
        if task_outcome == "extraction_empty":
            # 提取为空:自动重试,连续 fail 再告警
            self.record_empty(task_outcome.task_id)
            if self.consecutive_empties >= 3:
                self.notify_slack(f"连续 3 次提取为空: {task_outcome.url}")
                return "warning"
            return "info"
 
        if task_outcome == "validator_error":
            # Validator 误判:需要人工确认数据的正确性
            self.notify_pager(f"可能的数据错误: {task_outcome.task_id}")
            return "critical"
 
        return "ok"

告警分级的核心思想:不是所有失败都值得叫醒一个人,但有些"成功"值得。

第四步:成本监控——Browy 事件的教训

Browy 的 Copilot Metered Billing 事件证明,AI 浏览器自动化的成本是不可预测的——一次配置错误或模型选择不当,就会导致 Token 消耗爆炸。

class CostTracker:
    def __init__(self, budget_per_task=0.10, daily_budget=50.0):
        self.budget_per_task = budget_per_task
        self.daily_budget = daily_budget
        self.daily_total = 0.0
        self.spikes = []
 
    def record_task(self, task_id, tokens, model_price):
        cost = (tokens / 1000) * model_price
        self.daily_total += cost
 
        if cost > self.budget_per_task:
            self.spikes.append((task_id, cost))
            self.notify_spike(task_id, cost)
 
    def check_daily(self):
        if self.daily_total > self.daily_budget:
            self.halt_new_tasks(f"日预算超限: {self.daily_total}")

成本监控不是"优化"层面的需求——它是"防止破产"层面的需求。在 Browy 事件中,一个用户的单次任务花了 30 美元。没有成本监控的话,你只能在月底看到账单时才知道出了问题。

总结

AI 浏览器智能体的监控和传统 Web 服务完全不同。不能用 HTTP 状态码来理解智能体的健康度。

四个必须监控的维度,按优先级排列:

  1. 任务完成状态——SUCCESS / EXTRACTION_EMPTY / LOOP_DETECTED / VALIDATOR_ERROR
  2. 步数偏离——当前步数与历史基线的差距,超过 3x 告警
  3. 循环检测——操作序列中是否存在重复模式,超过 80% 相似度告警
  4. 成本异常——单任务成本和日预算,超过阈值自动熔断

四个监控维度从业务到成本涵盖了一个 AI 任务的完整生命周期。它们不是并列的关系——任务完成状态是最上游的信号,成本和步数是它的下游影响。如果任务状态正常,成本和步数通常也不会出问题。

需要企业代理方案?

我们可根据目标站点、并发规模与稳定性目标提供定制方案。