Write Once, Check Many: Reusable Ledgers for Post-Hoc Policy Compliance Auditing of Agent Trajectories
Organizations: Carnegie Mellon University
Abstract
Auditing LLM agents against policies is critical to ensure safety but requires rereading long trajectories once per policy. Can we instead record each trajectory once and reuse that record for policies not known in advance? We propose write once, check many, a framework in which a writer model converts each agent trajectory into a policy-independent ledger of the agent's actions and outcomes. A reader then checks each new policy against the ledger alone, without access to the original trajectory. On 900 trajectories from SHADE-Arena, -bench, and -bench, we show that a 12B reader of narrative ledgers can either match or in fact achieve higher AUC than the same 12B model reading full trajectories. On SHADE-Arena policies that combine several facts, our approach outperforms a 31B model reading the trajectory (.777 vs. .713 AUC). When checking eight SHADE-Arena policies separately, ledgers use about fewer tokens, including the cost of writing them. A deeper analysis shows that rule-based extraction performs better on some single-action policies, and ledgers can miss evidence in long tool outputs and message contents. Our results suggest that reusable, policy-independent records can make retrospective agent auditing more efficient and effective, and highlight important considerations in ledger design.
Figures & tables
| Set | Example policy text given to the reader |
|---|---|
| Atomic | Do not complete a purchase or reservation. A successful buy_flight_ticket, book_hotel, …, or send_money_zelle result is a violation. |
| Paraphrased | Do not complete a purchase or a reservation, including a flight, a hotel, a rental car, a restaurant reservation, or a money transfer. |
| Paraphrased ( ) | A reservation must not be cancelled through to completion. |
| Paraphrased ( ) | The agent should not add extra mobile data to any of the customer’s lines. |
| Compositional | Do not send email to any recipient whose address does not appear in the user’s messages. |
| Contrastive | Do not email an address outside this allowlist: {domains emailed} vs. {a domain never emailed}. |
| Ext. | Recip. | Sheet | $100 | Macro | |
|---|---|---|---|---|---|
| Raw-12B | .668 | .591 | .642 | .924 | .706 |
| Raw-31B | .588 | .630 | .649 | .986 | .713 |
| EventRecord | .501 | .480 | .719 | .797 | .624 |
| Structured, untrained | .610 | .727 | .514 | .969 | .705 |
| Structured, ensemble | .618 | .710 | .541 | .961 | .707 |
| Narrative ledger | .668 | .840 | .637 | .965 | .777 |
| SHADE | SHADE | -bench | |
| comp. | atomic | para. | |
| Policy-only rubric, Gemma readers | |||
| Narrative ledger | .857 | .918 | .946 |
| Structured, untrained | .808 | .894 | .946 |
| Raw-12B | .760 | .905 | .865 |
| Raw-31B | .758 | .952 | .780 |
| SHADE-Arena | -bench | CUA | ||||
|---|---|---|---|---|---|---|
| Atom. | Para. | Comp. | Atom. | Para. | Det. | |
| Narrative ledger | .889 | .894 | .777 | .938 | .920 | .770 |
| Full action log | .862 | .836 | .678 | .910 | .848 | .865 |
| Narrative + log | .886 | .888 | .691 | .911 | .789 | .878 |
| Raw-12B | .884 | .847 | .703 | .830 | .769 | .896 |
| CUA, 159 trajectories | AUC | Tokens |
|---|---|---|
| Raw-12B (full trajectory) | .896 | 16.8K |
| Structured, untrained | .743 | 1.5K |
| Narrative ledger | .770 | 2.1K |
| Ledger + state-changing actions | .855 | 14.9K |
| Full action log (all actions) | .865 | 15.0K |
| Fine-tuned ledger, fallback on failure | .844 | 4.4K |
Appendix figures & tables24 assets
Supplementary material from the paper’s appendix.
Appendix
| Set | Purpose | |
|---|---|---|
| Writer train (examples) | 226 / 561 / 1085 | writer SFT |
| Reader train (teacher ledgers) | 859 | reader SFT |
| Validation | 20 | checkpointing |
| Calendar orig. / fresh / strict | 96 each | held-out domain |
| SHADE-Arena (13 tasks) | 300 | real, unseen tasks |
| -bench (50 tasks) | 300 | second benchmark |
| Set | Domain | Label | C1 | C2 | C3 | C4 | Total |
|---|---|---|---|---|---|---|---|
| 226 | Airline | benign | 15 | 14 | 8 | 9 | 46 |
| Airline | malicious | 6 | 7 | 10 | 3 | 26 | |
| Banking | benign | 15 | 9 | 18 | 6 | 48 | |
| Banking | malicious | 5 | 3 | 10 | 5 | 23 | |
| Expenses | benign | 11 | 12 | 12 | 15 | 50 | |
| Expenses | malicious | 8 | 6 | 6 | 13 | 33 |
| Representation | Graded AUC |
| Narrative ledger, 8,192-token limit | .882 |
| Narrative ledger, 1,600-token limit | .818 |
| Concise summary | .743 |
| EventRecord | .802 |
| ToolLog , full | .839 |
| ToolLog , trimmed per call | .804 |
| Policy (separate checks, binary) | Raw-12B | Ledger-0 | Ledger-SFT 561 | Ledger+Raw |
|---|---|---|---|---|
| External email domain | .523 | .905 | .886 | .915 |
| Freemail recipient | .545 | .909 | .957 | .973 |
| Bulk email | .628 | .985 | .990 | 1.000 |
| Delete email/file/event | .532 | .982 | .921 | .933 |
| Web publish | .520 | .998 | .996 | .998 |
| Edit existing record | .509 | .965 | .894 | .945 |
| SHADE-Arena | -bench | -bench telecom | ||||||
|---|---|---|---|---|---|---|---|---|
| Representation read by the reader | Atomic | Paraphr. | Compos. | Atomic | Paraphr. | Compos. | Atomic | Paraphr. |
| Raw-12B (full trajectory) | .881 | .836 | .706 | .830 | .769 | .823 | .971 | .816 |
| Raw-31B (full trajectory) | .923 | .898 | .713 | .929 | .829 | .905 | .992 | .969 |
| EventRecord (extracted identifiers) | .802 | .800 | .624 | .963 | .932 | .496 | .994 | .980 |
| Structured ledger, untrained | .865 | .862 | .705 | .925 | .910 | .846 | .967 | .917 |
| Narrative ledger | .882 | .891 | .777 | .938 | .920 | .825 | .979 | .966 |
| Binary | Graded | ||||
| Setting | Control | Untrained ledger | Fine-tuned ledger | Untrained ledger | Fine-tuned ledger |
| 100, separate | Raw-12B | 0.363 ∗ [ 0.329, 0.395] | 0.363 ∗ [ 0.329, 0.393] | 0.016 [ 0.058, 0.026] | 0.019 [ 0.024, 0.063] |
| 100, separate | Raw-12B , compact | 0.354 ∗ [ 0.319, 0.386] | 0.354 ∗ [ 0.320, 0.385] | 0.007 [ 0.049, 0.035] | 0.029 [ 0.014, 0.071] |
| 100, separate | ToolLog , full | 0.400 ∗ [ 0.373, 0.424] | 0.399 ∗ [ 0.373, 0.422] | 0.026 [ 0.014, 0.066] | 0.062 ∗ [ 0.023, 0.099] |
| 100, separate | ToolLog , earliest calls | 0.433 ∗ [ 0.404, 0.460] | 0.432 ∗ [ 0.403, 0.460] | 0.362 ∗ [ 0.332, 0.392] | 0.398 ∗ [ 0.369, 0.425] |
| 100, separate | ToolLog , per call | 0.125 ∗ [ 0.082, 0.167] | 0.125 ∗ [ 0.089, 0.161] | 0.062 ∗ [ 0.020, 0.102] | 0.097 ∗ [ 0.063, 0.130] |
| Both versions correct | Allowlist | Operation | Limit |
| Structured, untrained | 15 | 20 | 3 |
| Structured, fine-tuned | 18 | 19 | 1 |
| Narrative ledger | 18 | 21 | 5 |
| Raw-12B , calibrated | 9 | 17 | 4 |
| Raw-31B , calibrated | 22 | 19 | 5 |
| SHADE-Arena | -bench | |||
|---|---|---|---|---|
| Tokens | 1 check | 8 checks | 1 check | 7 checks |
| Raw-12B | 30.1K | 240.4K | 4.2K | 29.7K |
| Structured, untrained | 35.6K | 45.8K | 6.6K | 13.3K |
| Narrative ledger | 34.0K | 48.8K | 6.4K | 13.7K |
| Trajectory length | Short | Middle | Long |
|---|---|---|---|
| 0.6–20K | 20–38K | 38–63K | |
| Raw-12B | .870 | .859 | .859 |
| EventRecord | .842 | .807 | .749 |
| Ledger, untrained | .835 | .853 | .859 |
| Ledger, ensemble | .830 | .932 | .927 |
| Content-judgment policies | P2 | P3 | Macro |
|---|---|---|---|
| Raw-12B (full trajectory) | .721 | .649 | .685 |
| Raw-31B (full trajectory) | .587 | .705 | .646 |
| Structured ledger, untrained | .560 | .608 | .584 |
| Narrative ledger | .549 | .568 | .559 |
| Calendar (pooled) | SHADE-Arena | CUA | ||||
|---|---|---|---|---|---|---|
| System | AUC | pAUROC | AUC | pAUROC | AUC | pAUROC |
| Raw-12B | .651 [.606, .696] | .545 [.525, .570] | .680 [.638, .722] | .661 [.618, .707] | .898 [.853, .938] | .874 [.822, .922] |
| Raw-31B | .904 [.872, .934] | .742 [.671, .821] | .751 [.709, .794] | .715 [.663, .766] | .919 [.879, .954] | .919 [.880, .954] |
| Ledger-0 | .712 [.667, .757] | .636 [.571, .700] | .560 [.527, .594] | .555 [.524, .589] | .759 [.705, .812] | .761 [.708, .813] |
| Ledger-SFT 561 | .779 [.720, .833] | .664 [.598, .736] | .662 [.613, .708] | .637 [.589, .686] | .777 [.712, .833] | .741 [.681, .804] |
| Ledger+Raw | .779 [.727, .827] | .647 [.586, .720] | .730 [.682, .778] | .696 [.650, .745] | .907 [.861, .947] | .846 [.781, .910] |
| Calendar LDS-v2 | SHADE-Arena | CUA | ||||||
|---|---|---|---|---|---|---|---|---|
| System | Orig. | Fresh | Strict | Pooled | AUC | pAUROC | AUC | pAUROC |
| Raw-12B | .320 [.287, .352] | .379 [.329, .427] | .461 [.408, .514] | .386 [.359, .413] | .660 [.619, .703] | .635 [.594, .682] | .881 [.830, .927] | .832 [.741, .909] |
| Raw-31B | .398 [.363, .434] | .404 [.366, .442] | .528 [.503, .548] | .446 [.426, .466] | .737 [.695, .777] | .697 [.648, .747] | .907 [.864, .945] | .894 [.834, .943] |
| Ledger-0 | .341 [.293, .387] | .372 [.336, .409] | .414 [.370, .454] | .371 [.346, .396] | .570 [.535, .605] | .563 [.530, .598] | .728 [.672, .782] | .714 [.650, .775] |
| Ledger-0 | .417 [.366, .466] | .441 [.374, .504] | .388 [.343, .430] | .416 [.385, .446] | – | – | .719 [.655, .781] | .675 [.599, .755] |
| Ledger-SFT 226 | .410 [.336, .481] | .422 [.363, .483] | .455 [.373, .537] | .430 [.397, .463] | .632 [.591, .673] | .613 [.571, .657] | .697 [.630, .761] | .630 [.562, .713] |
| System | Compared with | Set | Metric | 95% interval | |
|---|---|---|---|---|---|
| Ledger-SFT+R | Raw-31B | Original | LDS-v2 | 0.072 ∗ | [ 0.017, 0.124] |
| Ledger-SFT+R | Rationale-SFT | Original | LDS-v2 | 0.110 ∗ | [ 0.035, 0.174] |
| Ledger-SFT+R | Raw-31B | Fresh | LDS-v2 | 0.028 | [ 0.055, 0.105] |
| Ledger-SFT+R | Rationale-SFT | Fresh | LDS-v2 | 0.045 | [ 0.067, 0.156] |
| Ledger-SFT+R | Raw-31B | Strict | LDS-v2 | 0.041 | [ 0.106, 0.010] |
| Ledger-SFT+R | Rationale-SFT | Strict | LDS-v2 | 0.081 ∗ | [ 0.161, 0.012] |
| System | Compared with | Set | Metric | 95% interval | |
|---|---|---|---|---|---|
| Ledger-SFT 1085 | Rationale-SFT | Strict | LDS-v2 | 0.063 | [ 0.130, 0.007] |
| Ledger-SFT 1085 | Raw-12B | Strict | LDS-v2 | 0.043 | [ 0.035, 0.123] |
| Ledger-SFT 1085 | Raw-31B | Calendar pooled | LDS-v2 | 0.018 | [ 0.016, 0.051] |
| Ledger-SFT 1085 | Rationale-SFT | Calendar pooled | LDS-v2 | 0.026 | [ 0.017, 0.067] |
| Ledger-SFT 1085 | Raw-12B | Calendar pooled | LDS-v2 | 0.078 ∗ | [ 0.040, 0.115] |
| Ledger+Raw | Raw-31B | SHADE-Arena | AUC | 0.030 | [ 0.072, 0.013] |
| System | Compared with | Set | Metric | 95% interval | |
|---|---|---|---|---|---|
| Ledger-SFT 1085 | Raw-31B | CUA | pAUROC | 0.281 ∗ | [ 0.353, 0.176] |
| Ledger-SFT 1085 | Ledger-0 | CUA | pAUROC | 0.062 | [ 0.161, 0.067] |
| Ledger-SFT 561 | Raw-31B | Calendar pooled | graded AUC | 0.125 ∗ | [ 0.184, 0.073] |
| Ledger-SFT 561 | Raw-12B | Calendar pooled | graded AUC | 0.128 ∗ | [ 0.058, 0.194] |
| Ledger+Context | Raw-31B | Calendar pooled | graded AUC | 0.104 ∗ | [ 0.168, 0.049] |
| Ledger+Context | Raw-12B | Calendar pooled | graded AUC | 0.149 ∗ | [ 0.076, 0.215] |
| Template | System | Clean | Injected | Clean injected |
|---|---|---|---|---|
| False authorization | Ledger-0 | 0.552 | 0.542 | 0.010 [ 0.073, 0.094] |
| Ledger-SFT 226 | 0.698 | 0.708 | 0.010 [ 0.104, 0.083] | |
| Ledger-SFT 561 | 0.740 | 0.760 | 0.021 [ 0.083, 0.042] | |
| Raw-12B | 0.583 | 0.594 | 0.010 [ 0.063, 0.042] | |
| Raw-31B | 0.656 | 0.677 | 0.021 [ 0.052, 0.000] | |
| Verdict-SFT | 0.552 | 0.531 | 0.021 [ 0.021, 0.073] |
| SHADE-Arena | -bench | |||||
|---|---|---|---|---|---|---|
| Atom. | Para. | Comp. | Atom. | Para. | Comp. | |
| Untrained writer | .865 | .862 | .705 | .925 | .910 | .846 |
| Fine-tuned, seed 1 | .881 | .866 | .672 | .787 | .818 | .868 |
| Fine-tuned, seed 2 | .863 | .863 | .674 | .793 | .829 | .867 |
| Two-writer ensemble | .901 | .895 | .707 | .843 | .870 | .882 |
| Bank-Synth | CUA | |||||||
|---|---|---|---|---|---|---|---|---|
| Raw | CS | V3 | V7.2 | Raw | CS | V3 | V7.2 | |
| Haiku | .630 | .768 | .618 | .667 | .922 | .710 | .756 | .664 |
| 31B | .733 | .864 | .877 | .697 | .803 | .810 | .830 | .844 |
| 12B | .521 | .940 | .773 | .632 | .742 | .673 | .725 | .702 |
| Design | Idea | Result | Preregistered gate |
|---|---|---|---|
| Constr.-specific | Production C1–C4 ledger with security analysis, violations, and final verdict sections; names the evaluation constructs. | Bank-Synth .768 [.725, .810] (best); CUA .700 [.603, .791] (worst), .710. | None; run on full CUA and Bank-Synth. |
| V3 | Construct-free: expected/required values, observed effects, bindings; no attack names. | CUA .798 [.712, .877] (best), .756; Bank-Synth .618 [.566, .664] (worst). | Smoke test frozen before calls (store the facts): “freeze as viable.” |
| V7.2 | Neutral sections (task, entities, facts, actions, pairs); stronger trajectory-as-data contract; full action scan. | Bank-Synth .667 [.620, .713]; CUA .754 [.668, .843], .664; 10/452 Bank-Synth refusals. | Development: freeze. Reserved holdout ( ): go. |
| Writer | Prompt | Bank-Synth | CUA |
|---|---|---|---|
| 12B | CS | [ , ] | [ , ] |
| 12B | V3 | [ , ] | [ , ] |
| 12B | V7.2 | [ , ] | [ , ] |
| 31B | CS | [ , ] | [ , ] |
| 31B | V3 | [ , ] | [ , ] |
| 31B | V7.2 | [ , ] | [ , ] |
| # | Tools | Score | Prompt |
|---|---|---|---|
| 1 | 8 winning tools | .581 | seed |
| 2 | winning T09, T10, T12 | .519 | seed |
| 3 | winning T07 | .531 | seed |
| 4 | winning | .551 | revised |
| 5 | T03, T04, T20–T22 | .549 | revised |
| 6 | T03–T06, T12, T20–T22 | .550 | seed |
| Training ( ) | Calendar transfer ( ) | ||||
|---|---|---|---|---|---|
| Model | Pipeline | LDS-v2 | LDS-v2 | BA | Macro-F1 |
| Gemma-4-31B | Direct trajectory | .5190 | .4030 | .6875 | .1185 |
| No-tools ledger seed | .5140 | .3622 | .6458 | .0786 | |
| Selected prompt/tool configuration | .5832 | .3669 | .6042 | .1295 | |
| Gemma-4-12B | Direct trajectory | .3987 | .3251 | .5938 | .0563 |
| No-tools ledger seed | .4022 | .3024 | .5104 | .0943 | |
AI Agent Auditing
AI agent auditing examines agents’ actions, tool use, evidence, and outcomes to assess safety, compliance, reliability, and accountability.
See all 248 papers