8.3 审计与留痕:可举证的自动化


8.3 审计与留痕:可举证的自动化

本节摘要:本节把第 8 章的立场落成数据结构。先立论:留痕不是负担而是资产——出了争议时,自动化操作者的举证责任在自己,「做了什么、为什么做、依据什么」三问都要拿记录回答;没有留痕的系统在合规问询面前等于裸奔。然后给事件溯源式的设计:每个动作是一条只追加(append-only)的事件,字段含时间戳、任务标识、动作类型、意图(为什么做)、决策依据(模型当时的思考或规则触发的条件)、结果与证据指针(第 6.1 节三件套的路径)——事件流不可改写,回放即真相。第 2 章的执行历史、第 5 章的可视化报告、第 4 章的快照 trace,在这里统一汇入同一个事件结构。再讲脱敏与保留期:留痕本身也有隐私面(页面内容、用户数据进了日志),字段级脱敏规则加保留期制度让留痕可持续。最后是三种审计查询的形态:回放(单任务复盘)、统计(群体行为画像)、追责(时间线取证)。双语实现一个最小事件日志。

学习目标

  • 说清留痕的三重价值(举证、复盘、回归素材)与举证责任的归属。
  • 设计动作事件的结构(七个字段)并解释 append-only 的意义。
  • 把三类来源(循环历史、快照 trace、视觉报告)汇入统一事件流。
  • 制定字段级脱敏规则与保留期制度。
  • 用三种查询形态(回放、统计、追责)回答审计三问。

一、为什么留痕是合规的基石

第 6.1 节的三件套解决了「失败时刻」的证据;审计留痕把覆盖面从失败时刻扩展到每一个动作。动力来自三问:

审计三问 没有留痕时的回答 有留痕时的回答 这个系统做了什么? 「大概……按设计应该……」 事件流逐条回放 它为什么这么做? 「模型决定的,我也想知道」 每条事件附决策依据 出问题的是哪一步? 「我们重新跑一遍看看?」 时间线定位到动作 ​

举证责任的归属要明确:自动化操作者自证清白。站点方或监管方看到异常流量时,你拿不出「授权范围、操作清单、决策依据」的记录,默认解释权就不在你手里。第 2.2 节的事后审计形态、第 7.1 节的凭证台账,到这里汇成完整的自证体系。工程上它还有第三重价值:事件流是最高质量的回归素材与失败样本库,第 11 章的监控与错误分类直接消费它。

二、事件结构:一个动作一条记录

事件溯源(event sourcing)思想的核心:状态是事件的折叠结果,事件本身只追加、不修改、不删除。落到浏览器智能体:

字段 内容 示例
ts 时间戳(含时区) 2026-10-16T10:30:01+08:00
run_id 任务标识 task-0417
action 动作类型与目标 click 添加按钮
intent 为什么做(任务步骤名) 提交新待办
basis 决策依据(模型思考摘要或规则条件) 模型判断表单已填完
outcome 结果状态 成功;页面出现新条目
evidence 证据指针(三件套路径) runs/task-0417/step3.*

append-only 的意义:记录一旦写入不可改——它保护的不是系统是信任。事后补记、悄悄删改在自己内部复盘里或许无伤,在争议场景里一旦被发现,整份记录的可信度清零。工程上用只追加文件或事件表实现,配合第 11 章的日志采集。

双语最小实现(JSONL 追加,字段即上表):

# audit_log.py —— 动作事件留痕(append-only,写法示意) import json import time from pathlib import Path LOG = Path("runs") / "audit.jsonl" SENSITIVE = {"password", "token", "cookie", "session"} # 脱敏字段集 def mask(payload: dict) -> dict: return {k: ("***" if k in SENSITIVE else v) for k, v in payload.items()} def append_event(action: str, intent: str, basis: str, outcome: str, evidence: str, run_id: str = "task-0000") -> None: event = { "ts": time.strftime("%Y-%m-%dT%H:%M:%S+08:00"), "run_id": run_id, "action": action, "intent": intent, "basis": basis, "outcome": outcome, "evidence": evidence, "extra": mask({"password": "never-write-real-value"}), } LOG.parent.mkdir(exist_ok=True) with LOG.open("a", encoding="utf-8") as fh: fh.write(json.dumps(event, ensure_ascii=False) + "\n") append_event( action="click(添加)", intent="提交新待办", basis="表单校验通过,模型选择主提交按钮", outcome="成功,列表出现条目", evidence="runs/task-0000/step3.*", ) ​
// audit_log.mjs —— 动作事件留痕(append-only,写法示意) import { appendFileSync, mkdirSync } from "node:fs"; const LOG = "runs/audit.jsonl"; const SENSITIVE = new Set(["password", "token", "cookie", "session"]); // 脱敏字段集 /** 字段级脱敏 @param {Record<string, unknown>} payload 附加字段 */ function mask(payload) { return Object.fromEntries( Object.entries(payload).map(([k, v]) => [k, SENSITIVE.has(k) ? "***" : v]) ); } /** * 追加一条动作事件(只追加,不修改) * @param {string} action 动作 @param {string} intent 意图 @param {string} basis 决策依据 * @param {string} outcome 结果 @param {string} evidence 证据指针 @param {string} runId 任务标识 */ function appendEvent(action, intent, basis, outcome, evidence, runId = "task-0000") { mkdirSync("runs", { recursive: true }); const event = { ts: new Date().toISOString(), run_id: runId, action, intent, basis, outcome, evidence, extra: mask({ password: "never-write-real-value" }), }; appendFileSync(LOG, JSON.stringify(event) + "\n", "utf8"); } appendEvent( "click(添加)", "提交新待办", "表单校验通过,模型选择主提交按钮", "成功,列表出现条目", "runs/task-0000/step3.*" ); ​

三、三类来源汇入:循环历史、快照、报告

事件结构的价值在统一。前半本各章已经在各自产出留痕材料,只是形态分散:

来源 已有材料(出处) 汇入方式
循环执行历史 browser-use 的动作结果序列(第 2.1 节) 每个动作映射一条事件,basis 取模型思考
快照 trace MCP 会话的快照加 ref 记录(第 4.2 节) 快照文件作为 evidence 指针
视觉中间产物 Midscene 报告的截图加坐标(第 5.2 节) 报告路径作为 evidence 指针

汇总原则:框架的原始产物保持原样存放,事件流只存指针与摘要。这样事件流轻(可长期保存、可全文索引),证据重(按需调取、占空间但有保留期)。决策依据(basis)字段的采摘要克制:模型的长思考全文不必进事件,取「选择了什么、排除了什么、为什么」三要素的摘要即可——审计要的是可解释,不是可复读。

四、脱敏与保留期:留痕自己的合规

留痕系统本身在制造新的合规面:页面内容、用户数据、会话状态都进了日志。两条制度兜住:

制度 规则(示例) 说明
字段级脱敏 敏感字段集(凭证、令牌、身份证件号)写入即掩码 上文代码的 mask;第 2.2 节占位符是上游防线
保留期分级 摘要事件流长期(一年以上),完整证据短期(两周至三个月) 证据含页面快照,隐私浓度高
访问控制 事件流只读、按角色开放查询 审计材料不能成为新的泄露源

保留期的两头都要定:太短,问询时拿不出证据;太长,存量日志变成隐私债务。分级的逻辑是「摘要不含敏感内容可长存、证据含敏感内容须短存」——与第 7.1 节状态文件的生命周期管理同一套思路。

五、三种审计查询

留痕的价值最终由查询兑现:

查询 问题 形态
回放 这一个任务当时怎么走的? 按 run_id 过滤事件流,按 ts 排序,配合证据逐条查看
统计 这类任务的群体行为画像? 聚合动作分布、成功率、失败类别(喂给第 11.2 节看板)
追责 某时刻系统对某账号做了什么? 时间线切片,account 加时间窗过滤,输出动作与依据

三种查询共享同一份事件流,不需要三套日志。工程上事件流落 JSONL 或事件表皆可,量级大了再谈时序存储——起步阶段的瓶颈从来不是存储引擎,是字段纪律:漏记 intent 或 basis 的事件,存储再先进也回答不了审计三问。

六、常见坑

坑 现象 排查与处理
只记失败不记成功 成功路径无据可查 每动作一条事件,失败只是一种 outcome
basis 记结论不记依据 「模型点击了按钮」无解释 记选择与排除的理由摘要
日志明文进敏感字段 快照里带 Cookie 值 字段级脱敏加上游占位符双保险
保留期一刀切长存 隐私债务逐年累积 摘要与证据分级保留
事后补记 记录时间戳与真实时间对不上 只追加、不可改,写入即定格

本节要点回顾

  • 举证责任在操作者:审计三问(做了什么、为什么、哪一步)都要拿记录回答,留痕三重价值是举证、复盘、回归素材。
  • 事件七字段(ts、run_id、action、intent、basis、outcome、evidence),append-only 不可改写;回放即真相。
  • 三类来源(循环历史、快照 trace、视觉报告)汇入统一事件流:原始产物原样存放,事件存指针与摘要。
  • 留痕自己的合规:字段级脱敏、保留期分级、访问控制。
  • 三种查询(回放、统计、追责)共享一份事件流;瓶颈在字段纪律不在存储引擎。

至此,验证、基建、合规三块地基全部就位。带着这套约束重新审视效率问题:哪些任务值得从「每步花 token」的路径搬到「零边际成本」的路径?下一章讲固化决策——Agent 探索在先、测试固化在后的完整管道。

作者与出处
原作者:灏天文库
整理人: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U