首页 / 文章

为何代理日志无法满足第12条的要求:决策记录、因果关系与来源追溯

代理日志无法满足《欧盟人工智能法案》第12条的要求。应将人工智能代理的决策记录为具有因果关联、哈希链溯源机制及固定规则的持久性对象。

发布者:REACTAPP.TOP阅读约 14 分钟3244 词

来源: Your AI Agent Will Not Survive Article 12

2026年8月,一项新规正式生效,但大多数工程团队尚未感受到其影响。欧盟《人工智能法案》第12条规定,高风险人工智能系统必须在技术上允许对其整个生命周期内的事件进行自动记录,且记录的追溯程度需与系统的用途相匹配。第26条则要求系统部署方承担相应义务:至少保存这些日志六个月,若其他法律有更高要求则需更长时间。

一位阅读该条款的工程师注意到其中存在奇怪的失衡。目标被明确阐述,而所需格式却几乎未被提及。该目标是在事后能够还原某一项具体的决策。APM产品无法实现这一功能,因为它原本是为其他目的设计的;向量存储同样也无法做到。

时机很不恰当,因为相关人员刚刚停止回答问题,开始采取行动。他们批准支出、调整基础设施规模、处理保险索赔、拒绝申请者并批准释放事项。每一项决策都可能是未来有人要求公司作出解释的依据,而在当今的大多数组织中,真实的回答往往是他们无法做到。

预示该问题的一起小额索赔案

在相关法规出台之前,也即在相关人员能够采取行动之前,不列颠哥伦比亚省的一个法庭就已经在小范围内测试了同样的漏洞。这仍是目前最清晰的例证。

杰克·莫法特的祖母于2022年11月去世。同一天,他访问了加拿大航空的网站,打算预订飞往多伦多的航班。由于不清楚丧亲优惠票的规则,他向该航空公司的聊天机器人咨询。机器人告诉他可以立即购买全价机票,然后在90天内申请追溯享受折扣后的丧亲票价。在采取行动之前,莫法特做了件明智的事——他将机器人的回复截屏保存。之后他完成了购票、乘机、参加葬礼,并提交了报销申请。

加拿大航空拒绝了他的申请。称公司并无此类政策,是机器人编造的。

后续部分更具参考价值。在民事调解法庭上,该航空公司辩称自己无需为聊天机器人的发言负责,称其为独立实体,应自行承担其行为后果。法庭法官克里斯托弗·里弗斯认为这一论点十分奇怪,并指出该航空公司从未解释过为何他人应接受这一观点。聊天机器人属于网站的一部分,而公司需对其网站的行为负责。加拿大航空最终支付了812.02加元。

这个金额微不足道。真正关键的是零——即加拿大航空无法提供任何记录来证明其系统为何会说出那样的话。整个听证过程中唯一具有持久价值的证据就是顾客的截图。

同样的问题此后愈演愈烈。2025年4月,Cursor的客服机器人制定了一项政策,限制订阅只能用于单一设备。客户们开始取消订阅,而该公司之所以得知此事,只是因为一位联合创始人在了Reddit上看到了相关讨论帖。模式依旧相同,只是影响范围更广、速度更快,而且根本不需要任何仲裁机构。

现在试想,如果同样的证据缺陷出现在监管机构面前,且与处理资金流转的代理系统相关联,会怎样?

调试与问责是不同的工作

大多数技术架构从未在此处做出有意义的区分。

可观测性是以执行为中心的。它记录的是某个流程在单次运行中的表现:时间跨度、工具调用、令牌数量、重试次数以及延迟情况。它是通过抽样获取的,会在设定的保留时间后失效,且仅限于单个请求的范围内。这对于在周二找出漏洞来说确实非常合适。

责任追溯以领域为中心。它记录了组织基于何种证据、遵循何种政策得出的结论,以及之后的发展情况。即便面对框架迁移、模型淘汰、索引重建、机构重组,甚至有两名同事离职,这种记录也必须保留下来。

在企业的其他领域,这已是常规操作。生产环境中的变更从不会仅通过应用日志来重建,因为变更记录中已包含操作人、工单编号及审批信息。财务状况也从不会通过HTTP日志来重建,因为有完整的账务记录存在。订单、付款、审批和部署都属于持久性对象,每个对象都有其生命周期、负责人及保留规则。

唯有代理决策这类具有重大影响的事件,仍以非结构化的形式存在,全靠运气来应对。

凌晨3点的版本

由于采用了合规性的表述方式,这种故障听起来似乎很罕见,但实际上十分常见,因此具体的案例能起到很好的说明作用。

发布20分钟后,结账功能开始返回5xx错误。故障处理人员将错误率与发布时间窗口进行对比,未发现任何基础设施方面的警报,于是将此事件归类为发布后的回归问题。修复人员随即将版本回滚,错误率随即恢复到正常水平。发布人员随后重新启动部署队列。有人在事件处理频道里点了赞,团队便就此结束工作。整个过程仅耗时11分钟,而且由于问题似乎已自行解决,也没有进行后续的事件审查。

但实际上问题并不出在版本本身。某个下游支付服务提供商的性能一直在下降,恰好在回滚发生时恢复了正常。两者之间的关联纯属巧合,处理人员只是在巧合的基础上编造了一个看似合理的解释。

十月份,当同样的情况再次出现时,真相浮出水面,有人开始质疑四月份的故障是否源于相同的原因。是时候去查证了。

此时那些痕迹早已过时,早在六月就被删除了。提示模板也经历了两次修改。随着嵌入模型的更替,检索索引也被重新构建,因此当时智能体读取的运行手册内容与如今它所获取的内容已不相同。请求头中指定的模型版本也已停止使用。仅剩的,是一个以点赞表情符号结尾的聊天记录。

这个问题无法得到解答。没有人疏忽,系统架构中也从未设计过用于存储答案的机制。

为何更好的内存也无法解决这个问题

人们通常的第一反应是使用内存层,而那往往指的是向量存储。但这其实是在解决另一个完全不同的问题。

嵌入搜索很好地解决了一个问题:什么内容与当前内容相似?但它无法说明系统在某天的14:02时持有什么观点,是哪个先前的结论导致了当前的结果,某个特定事实的来源是什么,或者原本旨在限制某项操作的策略是否真的被执行了。

还存在一个更为微妙的缺陷。检索结果并非始终可复现。使用更新的模型重新对语料库进行嵌入后,相同的查询会得到不同的相似内容,这意味着原本被视为记录的内容其实已经在背后悄然发生了变化。如果通过升级依赖项就能悄无声息地修改审计轨迹,那它就不再是真正的审计轨迹了。

每一层都负责回答自己的问题:

  • 向量搜索:哪些项目与当前项目相似?
  • 知识图谱:有哪些内容与它相关联?
  • 来源追溯:它的起源是什么,且是否仍然有效?
  • 决策记录:得出了什么结论,依据是什么?
  • 因果关系:哪个事件影响了哪个结果?
  • 规则:是什么政策决定了最终结果?
  • 时间状态:3月14日时系统处于何种状态?
  • 真正意义上的“为何如此”调查需要这些信息中的大部分。其中只有一项属于向量存储。

    将决策转化为对象

    这时 Semantica 就显得很有价值了。它是一个基于 MIT 许可的 Python 层,运行在智能体框架之下,将上下文视为图结构而非一段文本。图的构建、推理及溯源过程都是确定性的,不涉及大型语言模型,这对于需要将输出作为证据的情况尤为重要。

    核心思想很简单:决策应当被明确记录下来,而非随意丢进日志中。

    from semantica.context import ContextGraph
    
    ctx = ContextGraph(advanced_analytics=True)
    decision_id = ctx.record_decision(
        category="incident_triage",
        scenario="Checkout 5xx elevated 20 minutes after release 2026.31",
        reasoning="Error onset correlates with rollout window; no infra alerts; "
                  "no dependency alarms visible at time of assessment",
        outcome="classified_as_release_regression",
        confidence=0.83,
    )
    

    其机制很简单。变化在于作者必须详细说明的内容。不再是简单的文本记录,而必须明确指定类别、场景、依据、结果以及置信度数值。所有这些信息在18个月后依然可以查询到,而普通文本则无法做到。

    以10月场景中的reasoning字段为例。其中提到在进行评估时并未出现任何依赖性警报。这一句话就让整个事件的性质从“操作员犯错”转变为“操作员根据不完整的信号得出了合理的结论”,从而指出存在需要弥补的监控漏洞。这两种理解方式会导致截然不同的会议讨论结果。

    关于那个字段需要特别注意的是:它并非用于记录模型原始的思维过程,因为这种过程往往不稳定、有时甚至是编造的,而且在外人面前无法逐条为其辩护。应当记录下机构愿意承担责任的依据:经过权衡的证据、达到的临界标准、所适用的政策,以及最终推翻该决策的人。无论如何,这样对实际应用更有帮助。

    单条记录相当于日志行,而链条则是基础设施

    真实的智能体工作流程是分支式的,其危害很少只集中在某个节点上,而是体现在所有后续默默接受了错误结论的环节中。

    最著名的人工智能出现前的案例是Knight Capital。2012年的一次错误部署导致过时的代码路径仍在运行,大约45分钟内该公司就损失了约4.4亿美元。没人怀疑软件的功能,每笔订单都有记录在案。但问题在于,人们无法在后果迅速蔓延时及时手动追踪其发展态势。

    Semantica允许在编写代码时就明确指定各决策之间的关联关系:

    triage_id = ctx.record_decision(
        category="incident_triage",
        scenario="Checkout 5xx elevated after release 2026.31",
        reasoning="Error onset correlates with rollout window; no infra alerts",
        outcome="classified_as_release_regression",
        confidence=0.83,
    )
    
    rollback_id = ctx.record_decision(
        category="remediation",
        scenario="Contain checkout 5xx",
        reasoning="Regression attributed to release; rollback is lowest-risk action",
        outcome="rolled_back_to_2026.30",
        confidence=0.91,
    )
    unblock_id = ctx.record_decision(
        category="release_gate",
        scenario="Resume deploy queue after containment",
        reasoning="Error rate normal for 30 minutes post-rollback",
        outcome="deploy_queue_reopened",
        confidence=0.86,
    )
    ctx.add_causal_relationship(triage_id, rollback_id, relationship_type="CAUSED")
    ctx.add_causal_relationship(rollback_id, unblock_id, relationship_type="INFLUENCED")
    why = ctx.trace_decision_chain(unblock_id)
    blast_radius = ctx.analyze_decision_impact(triage_id)
    

    存在三种关系类型:CAUSED、INFLUENCED和PRECEDENT_FOR。这类词汇量很小,这是可以接受的。几乎所有的信息都来自单一操作。

    10月发现分类有误后,问题就变了。询问哪些追踪记录提到了结账退回会得到四万行结果;而询问哪些决策继承了该结论,则会得到一个简短且有限的列表:回滚操作、队列重新开启、发送给客户的消息,以及没人撰写的事后分析报告。这就是决策所带来的影响范围,也是当客服人员停止提出建议而开始实际操作时所必需进行的操作。

    find_similar_decisions()的作用方向相反,它用于查找先例。该系统之前是否处理过此类请求?它采取了什么措施?正是这样,那些每隔第三个星期二就自相矛盾的系统才会被发现,这是一种真正的故障,但由于没有相应的评估指标,因此无人关注。

    因果关系不等同于来源

    这两者经常被混为一谈,但实际上它们回答的是不同的问题。即便知道决策C依赖于决策A,若不清楚决策A所依据的证据是什么,这也几乎毫无用处。

    Semantica中的来源追踪模块遵循W3C PROV-O标准。虽然它已过时,但却是正确的。

    from semantica.provenance import ProvenanceManager
    
    prov = ProvenanceManager(storage_path="./provenance.db")
    prov.track_entity(
        entity_id="release_2026_31",
        source="ci/pipeline_runs/2026-31/manifest.json",
        metadata={"stage": "canary", "extractor": "ManifestParser", "confidence": 0.99},
    )
    lineage = prov.get_lineage("release_2026_31")
    

    这里有两种设计思路,即便那些从不安装该库的团队也值得借鉴。

    首先,来源记录会形成一条哈希链。每条记录都包含一个序列号以及一个校验和,用以将其与前一条记录关联起来,而verify_chain()函数则可以判断历史记录是否被修改或遗漏。这正是能够防止任何人擅自UPDATE数据的同时,确保数据可作为有效证据的关键。

    其次,错误信息会被标记为无效,而非直接删除。当某条信息不再准确时,它会被连同操作者及原因一起替换:

    prov.invalidate(
        "release_2026_31",
        agent_id="human_sre_lead",
        reason="Error attribution corrected; degradation traced to payments provider",
    )
    

    一个可修改的 valid=false 字段用于显示当前状态。而账本则会记录该状态曾经的变更情况,包括谁进行了更改、何时更改以及为何更改。回到加拿大航空的听证会,询问航空公司需要哪一种记录方式即可,答案显而易见。

    将政策规则移出提示框

    另一个隐性的优势是 Semantica 搭载了真正的推理引擎:前向链接、Rete、Datalog 和 SPARQL。其逻辑十分简单:如果某个机构已经知晓某条规则,就没有必要每次都要求语言模型用英语即兴生成该规则。

    from semantica.reasoning import ReteEngine, Rule, Fact, RuleType
    
    engine = ReteEngine()
    engine.build_network([
        Rule(
            rule_id="dual_control_prod",
            name="Human approval required for high blast-radius prod changes",
            conditions=[
                {"field": "env", "operator": "==", "value": "production"},
                {"field": "blast_radius", "operator": "in", "value": ["high", "critical"]},
            ],
            conclusion="require_human_approval",
            rule_type=RuleType.IMPLICATION,
        )
    ])
    engine.add_fact(Fact("chg_014", "change", [{"env": "production", "blast_radius": "high"}]))
    matches = engine.match_patterns()
    

    该模型依然能够处理混乱的输入并给出相应建议。变化在于用于批准或阻止该建议的校验机制:它不再是一个存在于系统提示语中的、可能被措辞巧妙的边缘案例绕过的希望性描述。由于rule_id可以存储在决策记录中,因此确定适用了哪条规则只需简单查询,而无需两个团队之间进行争论。

    需要注意的是:条件匹配器被刻意设计得较为基础。在将其用于代理与任何受监管操作之间之前,应先使用实际规则集对其进行压力测试。演示用的规则引擎并不能替代合规控制手段,而在审计过程中才发现漏洞会带来高昂的代价。

    枯燥的标准比框架更持久

    PROV-O能够处理来源信息、RDF表示形式、SPARQL查询、SHACL约束以及OWL本体。这些功能并无什么令人兴奋之处,而这正是它的设计初衷。

    智能体框架的生命周期大约为18个月,而审计要求则没有这样的限制。2030年的审核人员不会关心做出决策时哪种编排库最为流行,而且也没人希望将永久性记录封存在一家已经改变发展方向的初创公司的专有导出格式中。

    还有一个通过 python -m semantica.mcp_server 启动的MCP服务器,其工具涵盖数据提取、决策记录、先例查询、因果链分析以及推理功能。有了它,智能体就可以通过普通的工具调用来记录自己的决策,无需额外添加智能体可能绕过的日志封装层。

    真正的代价

    这些成本需要明确说明。

    首要成本在于需要一个新的有状态服务,以及相应的备份、迁移、架构设计和访问控制。其次是需要投入精力进行建模,因为没人能确定哪些决策值得记录下来。记录每一步只会产生更多的日志,且成本更高;而记录不足则会在关键环节留下漏洞。

    还存在文化层面的成本,这一点往往被低估。决策图能让人们轻易发现某个操作员在四个月里一直错误地执行某项操作。尽管这是该工具的用途,但相关会议仍会让人感到不适。

    该项目的发展速度也很快。应锁定已通过验证的版本。那些需要未发布功能的人应从锁定在特定提交版本的源代码中获取。应将其视为基础设施,而非方便的导入工具。

    从一种工作流程开始

    将所有内容都绘制成图表是个错误。只绘制那些需要被解释的内容。

    选择一种不良决策会带来实际经济损失或信任损失的流程。仅在行使决策权的节点记录决策,比如批准、拒绝、支出、发送到生产环境或向客户承诺等。同时保存决策所依据的证据,以及涉及确定性策略时的规则编号。以异步方式将数据写入图表,这样写入操作就不会阻塞用户正在等待的路径。

    三十天后,尝试仅凭该图表来回答“为何会如此处理”这类问题。立刻就会出现漏洞,而且这些漏洞并非预期的那种。这样的练习比任何事先进行的架构设计都更有教育意义。

    需要记住的事项

    为追求可解释性,我们花了两年时间,主要做法就是试图探究模型的内部结构。但这个目标本身就是错误的,而且我们始终没有接近它。模型依然具有概率性,无论使用何种巧妙的提示方式,都无法让它的内部机制在关键领域变得可被接受。

    可问责性才是可行的替代方案,其所有组成部分都存在于模型之外:决策本身、决定该决策的因果因素、相关证据、数据来源、所应用的政策、后续产生的影响以及后续的修正措施。这些都是普通的结构化数据。从复式记账法出现起,人们就一直在记录这类信息。只是当决策者变成语言模型后,这种习惯便消失了,仿佛这改变了记录的用途一般。

    去掉那些法律术语后,第12条的要求其实相当温和。它并未要求提供更多日志,只是要求保留一份记录,即便在相关框架已被废弃、索引已重建两次、原始提示的创建者也已离开之后,这份记录仍能保持其意义。

    相比监管层面的测试,更好的办法是重新审视那起凌晨3点的事件。当时并没有人犯错,工作人员根据手头的信息得出了合理的结论,该事件在11分钟内就得到了处理,然而相关的解释却在四分之一个小时内就消失了。如果平常的周二就能让人们丧失解释决策的能力,审计人员自然会最先发现这一问题。几个月后的会议上,当所有人都逐渐意识到在场的人其实都不知道发生了什么时,团队自己也会意识到这一点。

    对加拿大航空来说,真正的损失并非812加元。问题在于,在听证会上他们无法解释自身系统的工作情况,反而将责任推给软件供应商。尽管只涉及一张机票和一名遇难乘客,而且该乘客还试图截取聊天记录,但他们的辩护依然站不住脚。

    如今的客服人员审批、支出、部署操作以及拒绝请求的速度都快过任何人检查的速度,却没人会截取这些操作的屏幕截图。应在有人提出要求之前先记录下来。问题总是在最糟糕的时刻出现,而到那时,答案要么存储在数据库中,要么就已永久丢失。

    相关阅读

  • 利用智能体、工具与技能从零构建迷你 AI 助手 — 一个简单的 Python 项目,它可将提示语转发给智能体,调用计算器及单位转换工具,运行摘要生成功能,再将处理后的提示语发送给大型语言模型。
  • Agent Harnesses:用于存储技能与参考资料的文件夹标准 — 通过 HARNESS.md 文件、技能与参考资料目录、渐进式展示方式以及嵌套布局,了解如何扩展智能体的功能以应对大型智能体的需求。
  • 为什么长时间运行的智能体需要状态机:领导者、执行者和验证者角色 — 单一智能体循环在处理长时间任务时会出现的四种故障,以及由确定性引擎驱动的领导者、执行者和验证者团队如何解决这些问题,还有何时可以跳过该机制。
  • 为什么语音智能体会听起来像机器人在等待:级联处理、对话检测与TEN框架 — STT-LLM-TTS级联流程如何导致沉默期和不良中断,语音智能体的四种类型,以及TEN框架如何处理对话检测与并行图结构。
  • 为什么AI智能体在实际应用中会失败:解析Harness工程 —— 当问题出在模型周围的系统中时,智能体的处理效率仅能达到70%。本文将探讨提示词、上下文以及Harness工程,还包括六层Harness架构和生成器-评估器的分工。