Agent Behavioral Contract

定义 Agent 在允许语义波动的同时必须始终满足的业务行为不变量,用 deterministic evaluator 把安全、证据、身份和权限边界固化成可验证契约。

#type / concept #status / growing #tech / ai #tech / architecture #tech / dev / test #resource / agent

[!info] related notes

Agent Behavioral Contract

一句话定义

Agent Behavioral Contract 是一组不要求模型每次逐字输出相同、但要求系统无论语义推理如何波动都不能违反的业务行为不变量

[!important] 核心目标 生产 Agent 的目标不是消灭 LLM 的非确定性,而是把非确定性限制在确定的业务契约内部。

为什么这个概念比“temperature=0”更重要

很多人第一次面对 Agent 的不稳定性,会先想到:

temperature = 0
seed = fixed
同一个 model
同一个 prompt

然后期待:

same input → exactly same output

但 production Agent 的实际运行链不只包含 model sampling:

Input snapshot
→ Context assembly
→ Model
→ Tool call
→ External API / DB / Retrieval
→ Runtime observations
→ Policy
→ Persistence
→ Delivery

任何一层都可能引入差异:

  • provider revision 更新;
  • retrieval index 变化;
  • tool response 变化;
  • timeout / retry / fallback 不同;
  • external system state 改变; -并发顺序不同。

所以生产系统真正能承诺的通常不是:

“每次 token 完全一样”

而是:

“无论内部合理波动如何,关键业务边界都不被突破”

这就是 Behavioral Contract。

为什么“输出不一样”不等于 Bug

同一输入、同一 configuration 下,LLM 可能出现:

  • 候选排序略变;
  • HIGHMEDIUM confidence 波动;
  • summary 措辞不同;
  • 检索命中顺序变化;
  • 两个语义接近的 candidate 名称不同。

如果这些变化仍满足 evidence、safety、schema、identity 和 authority 约束,就属于允许的 semantic variation

例如:

Run A
Candidate = C6 radiculopathy
confidence = HIGH
Decision = ALLOW_NORMAL

Run B
Candidate = possible C6 nerve-root involvement
confidence = MEDIUM
Decision = ALLOW_NORMAL

如果两者都没有编造事实、都满足 evidence policy、都没有 critical gap,就不应仅因文字或 confidence 不同判失败。

Behavioral Contract 的核心不是“允许不稳定”,而是“把不稳定分区”

生产设计真正要做的是把行为拆成三类:

必须一样的
允许有限变化的
完全可以自由变化的

如果不做这个分区,团队通常会落入两个极端。

极端 A:什么都锁死

summary 文案稍微变了
→ regression fail

结果是测试非常脆弱,模型升级几乎无法推进。

极端 B:什么都交给 Judge

“整体看起来差不多”
→ pass

结果是 safety / provenance / side effect 之类本来可以精确验证的东西被模糊处理。

Behavioral Contract 的价值就在于:

hard invariants → deterministic
bounded semantic behavior → rubric / semantic evaluator
presentation → 通常不作为 release gate

三层稳定性

可以把 Agent 行为分成三层:

1. Hard invariants:必须确定

例如:

criticalGapCount = 1
policy-v1
→ 不得 ALLOW_NORMAL

以及:

  • active safety blocker 不能普通 AUTO;
  • unknown policy revision 必须 fail closed;
  • executed configuration identity 必须与 selected configuration 一致;
  • durable historical artifact 不能被后续 run 原地改写;
  • user fact 不能由一般外部知识“补出来”。

这里若同样的 facts 在同一 policy 下得到不同 authority,属于真正的 contract violation。

2. Bounded behavior:允许变化,但必须在边界内

例如:

  • Candidate 内容与排序;
  • retrieval 结果;
  • semantic interpretation;
  • confidence;
  • explanation detail。

这些可以波动,但必须满足:

  • 不编造 user fact;
  • evidence identity 可追踪;
  • tool budget 不越界;
  • candidate schema 合法;
  • critical safety concern 不被遗漏或绕过。

3. Presentation:可以高度自由

例如:

  • summary 句式;
  • 解释顺序;
  • 同义措辞;
  • UI 文案风格。

除非产品层另有文案约束,否则不应把逐字一致当作可靠性指标。

一个更完整的 Contract Matrix

可以把 Contract 写成表,而不是一句“结果应该正确”。

示例 Contract推荐验证方式
Input必须 pin exact BodyState revisiondeterministic
Configrequested configuration == executed configurationdeterministic
Tooluser_information gap 不得走 generic RAGdeterministic
BudgetEvidenceBudget exhausted 后不得继续搜索deterministic
Evidencesupporting evidence ID 必须属于本轮 observed setdeterministic
Safetycritical gap unresolved 不得 normal AUTOdeterministic
Domainhistorical Analysis immutabledeterministic
SemanticsCandidate 与 evidence 应合理一致semantic evaluator
Explanation必须表达不确定性,不得绝对化semantic rubric
Presentation句式、排序、措辞通常不 gate

这张表的一个重要作用是帮助团队问:

“这个规则到底是 hard contract,还是我们只是主观希望模型这样写?”

如果连这个问题都没分清,Eval 很容易变成一堆不稳定的自然语言偏好。

“结果正确”仍可能违反 Contract

这是 Agent Eval 与普通问答 benchmark 的重要差异。

假设最终 Candidate 恰好正确,但路径是:

缺少“用户是否肌力下降”

RAG 搜到“这类患者通常会肌力下降”

把一般医学知识当成该用户真实肌力下降

Candidate 最终猜对

最终答案可能碰巧正确,但行为仍然非法,因为:

external knowledge ≠ user fact

因此:

Correct answer ≠ valid execution.

为什么“路径正确”是 Agent Eval 比普通 QA 更难的地方

传统 benchmark 常见结构:

Question
→ Answer
→ Compare answer

Agent 系统更像:

Input
→ Decide whether to use tool
→ Choose tool
→ Build arguments
→ Observe tool result
→ Possibly ask user
→ Possibly retrieve evidence
→ Produce semantic result
→ Apply policy
→ Cause/avoid side effect

因此最终 answer 只是整个轨迹的一个投影。

一个完整 Eval case 可能需要同时验证:

Expected Final Result
+ Required Tool Behavior
+ Forbidden Tool Behavior
+ Provenance Expectations
+ Decision Path
+ Side-effect Constraints

这也是为什么 Agent Evals 往往要结合 trace,而不能只做 text grader。

Contract 应该变成 Evaluator

Behavioral Contract 如果只写在设计文档里,很容易腐化。更成熟的做法是直接转成 evaluator:

ResponseContractEvaluator
→ schema/status/cardinality

EvidencePolicyEvaluator
→ user_fact 不被 retrieval 非法解决
→ EvidenceAttempt 绑定 Gap
→ budget 不超限

SafetyInvariantEvaluator
→ unresolved critical gap 不得 normal AUTO

ConfigurationProvenanceEvaluator
→ requested config == executed config

DecisionAuthorityEvaluator
→ facts + policy revision 得到预期 authority

这样:

Behavioral Contract

Executable Evaluators

Qualification Evidence

Contract-first Eval 设计方法

不要先拿一批案例跑起来,再看有什么指标可以算。

更稳的方法是:

Step 1 · 写业务 Contract

例如:

BC-01 external knowledge must not synthesize user fact
BC-02 critical unresolved gap forbids normal AUTO
BC-03 selected/executed configuration identity must match
BC-04 no side effect before authority

Step 2 · 为每条 Contract 定义最小 observable

例如 BC-02 需要:

criticalGapCount
policyRevision
decisionOutcome

Step 3 · 设计正例和反例

不仅要测:

criticalGapCount=1 → ABSTAIN

还要测:

confidence HIGH + judge HIGH + criticalGapCount=1
→ 仍然 ABSTAIN

这能证明 deny-overrides 真正成立。

Step 4 · 再加 semantic quality

只有 hard contract 已经锁住后,才讨论:

候选是否足够完整?
解释是否清晰?

这样 Eval 才不会把最重要的 safety contract 淹没在平均语义分数里。

为什么 deterministic evaluator 优先于 LLM Judge

可以确定表达的规则,不应交给 Judge 猜。

例如:

critical_gap_count > 0
→ ALLOW_NORMAL forbidden

这是 deterministic evaluator 的工作。

而下面这些才更适合 semantic validator / LLM Judge:

  • reasoning 是否充分;
  • candidate 是否和 evidence 语义一致;
  • summary 是否准确表达不确定性。

推荐层级:

Deterministic Invariants

Structured Semantic Checks

LLM-as-a-Judge

为什么不能用一个总分覆盖所有 Contract

假设 Eval 最终给:

overall_score = 0.94

但其中一个 case 发生:

critical red flag
→ ALLOW_NORMAL

即使其他 99 个 case 都很好,平均分仍可能很高。

所以 qualification 应同时有:

Hard Guardrails
+ Aggregate Quality Metrics

例如:

critical safety regression count == 0
AND
semantic pass rate >= threshold
AND
latency/cost within budget

而不是:

weighted overall score > 0.9

Behavioral Contract 天然适合 hard guardrail。

Behavioral Contract 与 Replay

Replay 不应主要追求逐 token 一致,而应验证 Behavioral Contract:

same critical fact
→ same hard authority boundary

same policy revision
→ same deterministic transition

same evidence identity
→ provenance 可追踪

因此即使 replay 的 summary 文案不同,只要关键 invariant 一致,也可以视为行为等价。

Replay Comparison 应该区分 Hard / Semantic / Presentation Drift

例如 historical run 与 counterfactual run:

Historical:
Candidate A, confidence HIGH, ALLOW_NORMAL

Counterfactual:
Candidate A, confidence MEDIUM, ALLOW_NORMAL

这可能只是 semantic drift。

而:

Historical:
critical gap → ABSTAIN

Counterfactual:
critical gap → ALLOW_NORMAL

这是 hard drift。

再比如:

“可能与 C6 神经根相关”
vs
“C6 神经根受累是一个可能解释”

通常只是 presentation drift。

所以 replay comparator 不应把所有 diff 同等对待。

Configuration 变化会改变 Contract 吗

会。

如果 Prompt、Model、Evidence Policy、Decision Policy 或 Tool Policy 变化,使系统允许的行为范围发生改变,就应该产生新的 Configuration identity,并重新 qualification。

不能在 production 某个 case 中让模型临时宣布:

“这次我很自信,所以我决定扩大规则。”

正确路径是:

production evidence
→ new eval cases
→ policy/config revision
→ qualification
→ shadow/canary
→ promotion

Contract Revision 与 Configuration Revision 的关系

如果只是增加一个测试来更好地验证原有 contract,可能不需要改变 production configuration。

但如果改变了真正的业务行为,例如:

v1:
reasoning=PREFERRED

v2:
reasoning=REQUIRED

或者:

critical diagnostic gap
从 ABSTAIN 改成 ALLOW_DEGRADED

那就是行为契约变化,应该进入新的 configuration/policy revision。

要区分:

Evaluator improved
≠ necessarily behavior changed

Business contract changed
→ behavior identity changed

BodySense 示例

BodySense Diagnosis 可以把这些视为 hard behavioral invariants:

BC-01 external knowledge 不得自动变成 user fact
BC-02 unresolved critical EvidenceGap 不得 ALLOW_NORMAL
BC-03 active safety blocker 必须抑制普通 candidate delivery
BC-04 EvidenceBudget exhausted 后不得继续偷偷检索
BC-05 unknown policy state 必须 fail closed
BC-06 Python 不拥有 durable business IDs
BC-07 immutable DiagnosisAnalysis 不被未来 run 改写
BC-08 selected configuration 与 execution provenance 必须一致

这些规则比“每次输出一样”更接近生产可靠性真正需要的稳定性。

把 Contract 映射到 L2 Treatment

Treatment 在 Diagnosis Contract 基础上增加 action-specific invariants:

TC-01 AI output 永远 proposal-only
TC-02 proposal generation 不等于 acceptance
TC-03 acceptance 必须重新检查 current BodyState / freshness / safety
TC-04 accepted revision immutable
TC-05 Intervention 必须来自 accepted revision
TC-06 Outcome 必须绑定明确 Intervention identity
TC-07 association_only 不能自动升级为 causal claim

这里最重要的变化是:

Diagnosis contract
主要保护“系统如何判断”

Treatment contract
还必须保护“系统何时允许改变现实世界”

把 Contract 映射到 L3 Consultation

Consultation 增加 runtime/protocol invariants:

CC-01 untrusted network JSON 必须经过 runtime validation
CC-02 event seq/idempotency contract 不得重复投影 side effect
CC-03 live/replay 应使用同一 semantic event contract
CC-04 transport disconnect 不等于 durable run cancellation
CC-05 interrupt answer 是 resume input,不是普通新消息
CC-06 resume 必须继续 exact execution/config identity

因此 Behavioral Contract 不只针对 LLM output,也覆盖:

protocol
runtime
persistence
authority
UI projection

只要某层行为会影响业务正确性,它就可以有 contract。

Production Incident 如何反哺 Contract

一次线上事故的理想闭环:

Incident
→ 找到第一个 contract violation
→ 冻结成 regression case
→ 补 deterministic/semantic evaluator
→ 修 implementation/config
→ qualification
→ release

例如发现:

Decision=ABSTAIN
但前端仍通过 stale cache 显示 candidate

这不应该只修一个 React 条件判断。

还应该新增跨层 contract:

Authorized candidates=[]
→ public read model / UI must not resurrect suppressed candidate

这样事故知识真正进入系统能力,而不是停留在一次 hotfix。

怎样判断一条规则值不值得成为 Hard Contract

可以问四个问题:

  1. 违反后是否可能造成安全、权限、审计或数据一致性问题?
  2. 是否能够从结构化事实精确判断?
  3. 是否希望任何模型/Prompt/Provider 都必须遵守?
  4. 是否应该在新 configuration promotion 前作为阻断条件?

如果答案大多为“是”,它通常应该成为 hard invariant,而不是只写在 prompt 里。

自测题

  1. 为什么 temperature=0 仍不能证明 Agent deterministic?
  2. Hard invariant、bounded semantic behavior、presentation variation 有什么差异?
  3. 为什么“最终答案猜对”仍可能是 Eval FAIL?
  4. 为什么 tool path / evidence path 也属于 Behavioral Contract?
  5. deterministic evaluator 和 LLM Judge 应怎样分工?
  6. 为什么不能用一个 overall score 覆盖 critical safety regression?
  7. Replay 为什么更应该比较 contract drift,而不是逐 token diff?
  8. Contract 变化与 evaluator 改进为什么不是同一件事?
  9. Treatment 相比 Diagnosis 会新增哪些 action contract?
  10. Production incident 怎样转成未来 qualification 的 regression evidence?

常见误解

  • 同输入结果不同就是 Bug:先看 execution observations 是否不同、contract 是否仍满足。
  • temperature=0 就等于 deterministic Agent:provider/model/retrieval/runtime 仍可能变化;真正关键是 hard business transitions 可重复。
  • Judge 高分可以覆盖 hard invariant:Judge 是语义信号,不是 authority。
  • 只测最终答案就够了:必须同时测试 forbidden behavior、trace、provenance 和 policy path。
  • Behavioral Contract 只是 Prompt 规范:真正的 contract 应落到 runtime enforcement、deterministic policy 和 evaluator。
  • 所有变化都应该 regression fail:presentation/允许的 semantic variation 不应和 hard violation 混为一谈。
创建于 2026/8/22 更新于 2026/8/23