Autoformalization of Agent Instructions into Policy-as-Code
Summary
This paper presents an autoformalization pipeline that translates agent prompts, MCP tool descriptions, and natural language policy documents into formally verified policies using an LLM-based generator-critic loop, achieving better coverage than hand-coded enforcement on MedAgentBench.
View Cached Full Text
Cached at: 06/26/26, 05:14 AM
# Autoformalization of Agent Instructions into Policy-as-Code
Source: [https://arxiv.org/html/2606.26649](https://arxiv.org/html/2606.26649)
###### Abstract
Agent safety in high\-stakes domains requires formal policy enforcement, but most existing approaches either rely on probabilistic guardrails \(fine\-tuned classifiers, prompt\-based steering\) that offer no formal guarantees, or on hand\-coded symbolic enforcement that does not scale to the breadth of real policy specifications\. We present an autoformalization pipeline that translates agent prompts, MCP tool descriptions, and natural language policy documents into formally verified policies using an LLM\-based generator\-critic loop\. The resulting policies are written in the Cedar Policy Language\. On the MedAgentBench benchmark, our autoformalized policies cover substantially more of the source natural\-language specification than the hand\-coded symbolic enforcement in prior work\.
Autoformalization, Policy\-as\-Code, Cedar, Agent Security
\{NoHyper\}
## 1Introduction
Figure 1:The policy generation pipeline\. A system prompt, MCP tool definitions, and an \(unstructured\) policy corpus are autoformalized into a verified Cedar policy set by a generator\-critic loop that pairs a hard, deterministic critic \(Cedar parser checks for syntax, schema mismatches, contradictions, and vacuous policies\) with a soft critic \(an LLM\-as\-judge doing semantic alignment and qualitative evaluation against a rubric\)\. If the policies pass both critics, then the generator\-critic loop ends\. The resulting policy set is enforced at runtime by an external policy engine\.Large language models \(LLMs\) have evolved from passive text generators into autonomous agents capable of perceiving environments, planning multi\-step trajectories, and manipulating external tools through frameworks like LangGraph or Amazon Strands\. However, AI agents introduce a strong trade\-off between security and utility: for agents to complete complex tasks autonomously, they often require elevated privileges, and elevated privileges mean a higher\-risk attack surface\. Giving an AI agent elevated privileges is especially risky because LLM\-powered agents are subject to adversarial techniques like prompt injection\.
Current industry practices for securing agent behavior rely heavily on fine\-tuned safety models \(like Llama Guard\(Inan et al\.,[2023](https://arxiv.org/html/2606.26649#bib.bib7)\)\) or prompt\-based steering, using system instructions to direct behavior\. However, classifier\- and prompt\-based guardrails are often inadequate for security\-critical applications because they do not offer formal guarantees\. In this paper, we describe an alternative guardrail approach, using autoformalization and Policy\-as\-Code \(PaC\), which provides strong guarantees about agent behavior\. Our system governs agent behavior via an external deterministic policy engine that evaluates agent actions against formal rules to decide whether those actions are permitted\.
### 1\.1Contributions
We propose a layered autoformalization architecture, termed theVerification Sandwich, to translate natural language agent instructions into formal policy languages\. At runtime, these formal policies are enforced via an agent harness to govern the agent’s actions\. To evaluate our approach, we introduce an open\-source policy harness for agent scaffolds implemented with the Cedar policy language\(Cutler et al\.,[2024](https://arxiv.org/html/2606.26649#bib.bib4)\), and we release this implementation alongside custom Cedar language bindings in Python\.111[https://github\.com/sondera\-ai/sondera\-harness\-python](https://github.com/sondera-ai/sondera-harness-python)Central to this architecture is a policy generation pipeline that automatically converts an agent card \(comprising instructions and tool schemas\) into verified authorization policies\. This work draws inspiration from the LLM Modulo framework\(Kambhampati et al\.,[2024](https://arxiv.org/html/2606.26649#bib.bib9)\)and neurosymbolic AI\.
1. 1\.Thegrounding layer\(bottom\) serves as the foundation for constraining candidate generation\. It extracts entities, identifies tool schemas \(e\.g\., OpenAI JSON schemas\), and defines the principal\-resource\-action ontology\. This layer ensures that the agent operates within a structured environment where every potential action is mapped to real\-world entities and valid system identifiers\.
2. 2\.Themodel layer\(middle\) utilizes the generative capabilities of state\-of\-the\-art models to reason over inputs and generate candidate policies\. It leverages its parametric knowledge to interpret instructions and propose candidate policies that reflect the intended agent logic\.
3. 3\.Thesafety layer\(top\) applies both a hard \(programmatic, deterministically verifiable\) critic and a soft \(LLM\-based\) critic to the candidate policies\. The hard critic can check for problems such as syntax errors or vacuous policies using Cedar’s built\-in static analysis tools\. The soft critic can check for semantic alignment to the original natural language statements, as well as for other qualitative issues defined in a scoring rubric\.
### 1\.2Prior Works
#### 1\.2\.1Autoformalization
Autoformalization is the process of taking informal natural language and translating it into verifiable formal statements that can be processed by machine reasoning\. There has long been interest in modeling computer behavior using mathematical expressions\(Baier & Katoen,[2008](https://arxiv.org/html/2606.26649#bib.bib3)\)\. Previous mathematical research has focused on using formal languages such as LEAN\(de Moura & Ullrich,[2021](https://arxiv.org/html/2606.26649#bib.bib5)\)to reason about the correctness of machine output\. Unfortunately, these functional programming languages require verbose levels of specification at each description, which makes their use cumbersome\. Recent advances in LLMs have made it practical to automate this translation, lowering the manual specification burden that has historically limited the adoption of formal methods\. Of particular interest to our use is the ability of autoformalization to mathematically verify the non\-deterministic LLM\-generated output\(Weng et al\.,[2025](https://arxiv.org/html/2606.26649#bib.bib14)\)\.
#### 1\.2\.2Contextual Agent Policies
As AI agents have arisen with the ability to autonomously control and call tools in a loop, the need to define context\-aware policies to govern their behavior has emerged\(Tsai & Bagdasarian,[2025](https://arxiv.org/html/2606.26649#bib.bib13)\)\. Previous research has explored using contextual decision policies to modify AI model behavior\(Seraj et al\.,[2025](https://arxiv.org/html/2606.26649#bib.bib12)\)\. Other authors have explored generating runtime guardrails out of these policies\(Kholkar & Ahuja,[2025](https://arxiv.org/html/2606.26649#bib.bib11)\)or learning policies by mining agent trajectories\(Abaev et al\.,[2026](https://arxiv.org/html/2606.26649#bib.bib1)\)\.
#### 1\.2\.3Cedar Policy Language
To enforce these types of agent policies, a policy language provides a variety of attractive features including human readable language\(Amazon Web Services,[2025](https://arxiv.org/html/2606.26649#bib.bib2)\)and policies, logical correctness guarantees via theorem provers, validation to catch both syntax and expression errors, and compiled speed\. Existing policy languages were evaluated and for this research the Cedar authorization language open sourced by Amazon Web Services was chosen\(Cutler et al\.,[2024](https://arxiv.org/html/2606.26649#bib.bib4)\)\. While highly performant, Cedar is also easily readable and writable by non\-domain experts\(Kaoudis & Smith,[2024](https://arxiv.org/html/2606.26649#bib.bib10)\)\.
## 2Approach
We apply autoformalization to transform natural language intent from system instructions, MCP tool definitions, and natural language policy documents into formal policies\-as\-code written in the Cedar policy language\. These policies are then used to control runtime agent behavior\. Our pipeline for the autoformalization process is shown in Figure[1](https://arxiv.org/html/2606.26649#S1.F1)\.
The Cedar language allows optional enforcement of a schema, which we find useful as a check on automatically generated policies\. We generate this schema programmatically from the MCP tool definitions\.
We then provide the Cedar schema to a generator\-critic loop \(Figure[1](https://arxiv.org/html/2606.26649#S1.F1)\), along with the agent system prompt, tool definitions, and policy documents\. The generator\-critic loop first uses an LLM to generate a candidate set of policies, which are then checked by a hard critic and a soft critic:
1. 1\.Hard Critic: This component performs a strict, deterministic check of the Cedar policy syntax, enforces schema compliance, and checks for logical contradictions \(i\.e\., a set of policies that can never be satisfied due to conflicting policies\)\.
2. 2\.Soft Critic: Acting as an LLM\-as\-a\-judge, the soft critic evaluates the semantic alignment of the policy against a predefined rubric\. It ensures that the formal logic accurately reflects the spirit of the original instructions and policy documents\.
Feedback from the soft and hard critics is provided back to the policy generator, and this generator\-critic loop continues iteratively to refine the candidate policies\. Once the policy set reaches a certain quality threshold as judged in the hard critic step, the final Cedar policy set is output\. Together, these stages instantiate theVerification Sandwich: the grounding layer produces the Cedar schema, the model layer is the policy generator, and the safety layer is the hard\- and soft\-critic pair\.
## 3Evaluation
We evaluate our approach against the MedAgentBench experiment of Hong et al\.’s symbolic guardrails work\(Hong et al\.,[2026](https://arxiv.org/html/2606.26649#bib.bib6)\)\. MedAgentBench\(Jiang et al\.,[2025](https://arxiv.org/html/2606.26649#bib.bib8)\)is a capability benchmark for tool\-using electronic medical record \(EMR\) agents and contains no safety policy of its own\. Hong et al\. therefore authored a synthetic natural language policy of 88 rules \(drafted by GPT\-5\.2 and expanded via STPA hazard analysis\) and handwrote symbolic guardrails for 23 of those rules\. We feed the same policy through our autoformalization pipeline to produce Cedar policies, evaluating on enforcement coverage rather than agent utility\.
Besides using the natural language policy to generate Cedar rules via our autoformalization pipeline, we also used Claude Opus 4\.7 to transcribe additional Fast Healthcare Interoperability Resources \(FHIR\) constraints from Hong et al\.’s reference MCP server\(Hong et al\.,[2026](https://arxiv.org/html/2606.26649#bib.bib6)\)into Cedar rules\. These additional rules are not derivable from the policy text alone and are therefore required for a fair head\-to\-head comparison with Hong et al\. We annotated each Cedar rule with a source annotation marking its lineage, which allows us to separate the rules into two buckets \(policy\.md or MCP\)\. We do not encode specific benchmark instances or data\-specific constants, but merely aim for parity with the narrowness of the MCP implementation\.
We used an ETL pipeline to ingest and normalize the trajectories from the original MedAgentBench dataset so that we could replay them through our Cedar policy engine for evaluation\.
Experimental Setup\.The autoformalization pipeline used in these experiments is realized as follows\. The candidate generator is Gemini 3 Pro, prompted with the agent’s system instruction, tool definitions, and the auto\-generated Cedar schema\. The hard verifier invokes the Cedar reference tooling \(Rustcedar\-policyCLI\) for syntax and schema checks and for static analysis that flags vacuous policies and conflicting rules, retrying up to three times with validation errors fed back to the generator\. The soft critic is a two\-stage Judge→\\rightarrowVerifier pipeline \(both Gemini 2\.5 Flash, temperatures 0\.3 and 0\.1\)\.
Our cumulative results are shown in Table[1](https://arxiv.org/html/2606.26649#S3.T1)\. Three conditions are tested\. InRaw, the agent uses raw HTTP GET/POST tools \(MedAgentBench’s default\)\. InBaseline, each HTTP endpoint is wrapped in a typed MCP tool\. InGuardrail, Hong et al\.’s symbolic guardrails are added on top of the Baseline\. The Adversarial dataset replaces benign tasks with prompts designed to manipulate the agent into policy violations\.
DatasetConditionHong et al\.Unsafe↓\\downarrowCedar Block Rate↑\\uparrowOriginalRaw39\.0%30\.3% \(91/300\)OriginalBaseline23\.0%57\.7% \(173/300\)OriginalGuardrail0\.0%55\.7% \(167/300\)AdversarialRaw78\.0%72\.0% \(36/50\)AdversarialBaseline62\.0%82\.0% \(41/50\)AdversarialGuardrail0\.0%85\.7% \(42/49\)
Table 1:Policy violation rates on MedAgentBenchThe Cedar Block Rate is consistently higher than Hong et al\.’s Unsafe rate because our autoformalization pipeline covers more of the policy than Hong et al\.’s manual implementation does\. Hong et al\. hand\-coded symbolic guardrails for 23 of the 88 rules in the synthetic policy; our pipeline produces Cedar policies covering more of the same 88\-rule policy automatically\. Hong et al\.’s Unsafe column counts violations of their 23 implemented rules; the Cedar Block Rate counts violations of our broader autoformalized rule set\. The Guardrail rows make this clearest: Hong et al\.’s 0% is by construction within their 23\-rule scope, while Cedar’s 55\.7% \(Original\) and 85\.7% \(Adversarial\) measure violations of the rest of the policy\. The parenthesized counts in the Cedar Block Rate column refer to trajectories: 91/300 means 91 of the 300 trajectories in that split were blocked by Cedar\.
The trajectory\-level block rate understates a stronger underlying result\. Many MedAgentBench tasks involve only retrieval and never issue a write, i\.e\., they never issue a POST request; since Cedar can deny tool calls but not dialog\-only behavior, trajectories with no write attempt are unblockable by construction\. Decomposing by whether the trajectory contains any write attempt:
DatasetConditionTrajectorieswith POSTCedar Block RateOriginalRaw30089100\.0% \(89/89\)OriginalBaseline3008494\.0% \(79/84\)OriginalGuardrail3008698\.8% \(85/86\)AdversarialRaw5034100\.0% \(34/34\)AdversarialBaseline5033100\.0% \(33/33\)AdversarialGuardrail4932100\.0% \(32/32\)
Table 2:Cedar Block Rate by write attempts\. The Cedar Block Rate denominator is the count of trajectories with at least one POST request\.In the adversarial guardrail condition, all seven trajectories that Cedar "missed" had no POST writes attempted: five had no tool calls at all due to the agent intrinsically refusing before hitting a guardrail, and two more were simply retrievals via GET requests\. 49 adversarial trajectories slipped past the MCP server’s hard gating, but Cedar’s additional deny coverage blocked 42 of them \(85\.7%; Table[1](https://arxiv.org/html/2606.26649#S3.T1)\)\.
The full Cedar policies can be found in the supplemental materials in the appendix\.
## 4Discussion
Deterministic Security vs\. LLM Non\-Determinism\.The robustness of this architecture comes from decoupling policy enforcement from the LLM’s reasoning context\. In traditional agentic workflows, safety instructions are often embedded in the system prompt or with external safety models\. Our findings suggest that by extracting this logic into Cedar policies, we mitigate the risk of jailbreaking and indirect prompt injection\. Because the policies sit outside the context window and are enforced by a deterministic policy evaluator, an attacker cannot "convince" the security layer to ignore its rules\. Furthermore, the implementation of a fail\-closed enforcement mechanism ensures that if the policy engine or the validation harness encounters an error, the agent’s actions are blocked by default, prioritizing safety over availability\.
The Friction\-Utility Trade\-off\.A critical challenge identified in our field testing of this work is the friction introduced by formal policy enforcement\. In high\-stakes environments, there is a tendency to author overly restrictive policies to minimize risk\. If the autoformalization pipeline produces policies that are too narrow, the agent’s utility is severely degraded, leading developers to disable protections entirely\. Achieving the "Goldilocks zone" of policy, where the agent is sufficiently constrained yet remains functional, requires a highly sophisticated Generator\-Critic Loop\. The use of a soft policy critic is essential here, as it can evaluate whether a policy is pragmatically aligned with the user’s intent in a way that a rigid syntax checker cannot\.
The Role of Formal Verification\.The choice of Cedar as the target language is central to the pipeline’s success\. Unlike custom JSON schemas or Python\-based checks, Cedar is formally verified and human\-readable\. This ensures that security engineers can audit the generated policies, providing an auditing capability that is essential for building trust in autonomous systems\. The hard verifier in our pipeline ensures that the LLM cannot confabulate entities, providing a level of type safety that is fundamentally missing from pure\-neural approaches to agent steering\.
## 5Ongoing and Future Work
Cedar is stateless by design, and is often used in conjunction with an entity store\. While this is well\-suited to request\-response authorization, it limits multi\-turn agentic workflows that depend on action ordering or persistent context\. Future work focuses on closing this gap along two axes\.
Temporal Logic Integration: Future research will investigate the incorporation of temporal dependencies, ensuring that an action is only authorized if a specific prerequisite sequence has been formally completed and verified\.
Memory\-Aware Policies:We plan to develop mechanisms that allow the policy engine to reference an agent’s trajectory\. This would enable the system to prevent redundant or conflicting actions across long\-running sessions by checking against a persistent state of prior decisions\.
## References
- Abaev et al\. \(2026\)Abaev, N\., Klimov, D\., Levinov, G\., Mimran, D\., Elovici, Y\., and Shabtai, A\.Agentguardian: Learning access control policies to govern ai agent behavior, 2026\.URL[https://arxiv\.org/abs/2601\.10440](https://arxiv.org/abs/2601.10440)\.
- Amazon Web Services \(2025\)Amazon Web Services\.Writing policies in natural language\.AWS Bedrock AgentCore Documentation, 2025\.URL[https://docs\.aws\.amazon\.com/bedrock\-agentcore/latest/devguide/policy\-natural\-language\.html](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/policy-natural-language.html)\.Accessed: 2026\-02\-01\.
- Baier & Katoen \(2008\)Baier, C\. and Katoen, J\.\-P\.*Principles of Model Checking*\.The MIT Press, Cambridge, MA, USA, 2008\.ISBN 9780262026499\.
- Cutler et al\. \(2024\)Cutler, J\. W\., Disselkoen, C\., Eline, A\., He, S\., Headley, K\., Hicks, M\., Hietala, K\., Ioannidis, E\., Kastner, J\., Mamat, A\., McAdams, D\., McCutchen, M\., Rungta, N\., Torlak, E\., and Wells, A\.Cedar: A new language for expressive, fast, safe, and analyzable authorization \(extended version\), 2024\.URL[https://arxiv\.org/abs/2403\.04651](https://arxiv.org/abs/2403.04651)\.
- de Moura & Ullrich \(2021\)de Moura, L\. and Ullrich, S\.The lean 4 theorem prover and programming language\.In*Automated Deduction – CADE 28*, volume 12699 of*Lecture Notes in Computer Science*, pp\. 625–635\. Springer, Cham, 2021\.doi:10\.1007/978\-3\-030\-79876\-5\_37\.URL[https://link\.springer\.com/chapter/10\.1007/978\-3\-030\-79876\-5\_37](https://link.springer.com/chapter/10.1007/978-3-030-79876-5_37)\.
- Hong et al\. \(2026\)Hong, Y\., She, Y\., Kang, E\., Timperley, C\. S\., and Kästner, C\.Symbolic guardrails for domain\-specific agents: Stronger safety and security guarantees without sacrificing utility, 2026\.URL[https://arxiv\.org/abs/2604\.15579](https://arxiv.org/abs/2604.15579)\.
- Inan et al\. \(2023\)Inan, H\., Upasani, K\., Chi, J\., Rungta, R\., Iyer, K\., Mao, Y\., Tontchev, M\., Hu, Q\., Fuller, B\., Testuggine, D\., and Khabsa, M\.Llama guard: LLM\-based input\-output safeguard for human\-ai conversations, 2023\.URL[https://arxiv\.org/abs/2312\.06674](https://arxiv.org/abs/2312.06674)\.
- Jiang et al\. \(2025\)Jiang, Y\., Black, K\. C\., Geng, G\., Park, D\., Zou, J\., Ng, A\. Y\., and Chen, J\. H\.MedAgentBench: A virtual EHR environment to benchmark medical LLM agents\.*NEJM AI*, 2\(9\):AIdbp2500144, 2025\.
- Kambhampati et al\. \(2024\)Kambhampati, S\., Valmeekam, K\., Guan, L\., Verma, M\., Stechly, K\., Bhambri, S\., Saldyt, L\., and Murthy, A\.Llms can’t plan, but can help planning in llm\-modulo frameworks, 2024\.URL[https://arxiv\.org/abs/2402\.01817](https://arxiv.org/abs/2402.01817)\.
- Kaoudis & Smith \(2024\)Kaoudis, K\. and Smith, I\.Policy language security comparison and threat model\.Technical report, Trail of Bits, 2024\.URL[https://github\.com/trailofbits/publications/blob/master/reports/Policy\_Language\_Security\_Comparison\_and\_TM\.pdf](https://github.com/trailofbits/publications/blob/master/reports/Policy_Language_Security_Comparison_and_TM.pdf)\.Comparative security assessment of policy languages \(Cedar, Rego, OpenFGA\)\.
- Kholkar & Ahuja \(2025\)Kholkar, G\. and Ahuja, R\.Policy\-as\-prompt: Turning ai governance rules into guardrails for ai agents, 2025\.URL[https://arxiv\.org/abs/2509\.23994](https://arxiv.org/abs/2509.23994)\.
- Seraj et al\. \(2025\)Seraj, R\., Meng, L\., and Sylvain, T\.Contextual bandits with entropy\-based human feedback, 2025\.URL[https://arxiv\.org/abs/2502\.08759](https://arxiv.org/abs/2502.08759)\.
- Tsai & Bagdasarian \(2025\)Tsai, L\. and Bagdasarian, E\.Contextual agent security: A policy for every purpose, 2025\.URL[https://arxiv\.org/abs/2501\.17070](https://arxiv.org/abs/2501.17070)\.
- Weng et al\. \(2025\)Weng, K\., Du, L\., Li, S\., Lu, W\., Sun, H\., Liu, H\., and Zhang, T\.Autoformalization in the era of large language models: A survey, 2025\.URL[https://arxiv\.org/abs/2505\.23486](https://arxiv.org/abs/2505.23486)\.
## Appendix ASupplemental Materials
### A\.1Firing by Bucket
Deny counts by rules showing which are policy text constraints and which represent MCP narrowness\.
RuleFiringsBucket2\_4\_restate\_patient\_before\_write4161 \(policy\.md§2\.4\)5\_1\_writes\_require\_confirmation4161 \(policy\.md§5\.1\)6\_3\_stop\_on\_tool\_error3461 \(policy\.md§6\.3\)5\_9\_service\_request\_priority\_stat2802 \(tools\.py:1223\)default\_allow219\(allow events, not blocks\)2\_1\_patient\_must\_have\_been\_retrieved1752 \(tools\.py:638\)5\_7\_no\_unauthorized\_backdating1741 \(policy\.md§5\.7\)6\_4\_no\_duplicate\_write\_retry1731 \(policy\.md§6\.4\)5\_7\_observation\_must\_have\_issued1492 \(tools\.py:650\)3\_4\_narrow\_query\_count1391 \(policy\.md§3\.4\)5\_6\_duplicate\_detection891 \(policy\.md§5\.6\)5\_7\_service\_request\_authored\_on\_in\_window842 \(tools\.py:1205\)5\_9\_observation\_category\_system812 \(tools\.py:703\)5\_9\_med\_request\_coding\_must\_be\_present632 \(tools\.py:999\)2\_5\_single\_patient\_per\_session501 \(policy\.md§2\.5\)5\_7\_med\_request\_authored\_on\_in\_window432 \(tools\.py:949\)5\_7\_observation\_issued\_in\_window202 \(tools\.py:654\)5\_7\_med\_request\_must\_have\_authoredOn122 \(tools\.py:944\)2\_1\_no\_anonymous\_patient\_query111 \(policy\.md§2\.1\)5\_9\_med\_request\_requires\_medication\_and\_dosing101 \(policy\.md§5\.9, typed\)5\_9\_med\_request\_ndc\_coding42 \(tools\.py:1004\)2\_1\_no\_write\_without\_subject41 \(policy\.md§2\.1\)5\_2\_subject\_linking\_required41 \(policy\.md§5\.2\)5\_11\_subject\_reference\_must\_be\_patient41 \(policy\.md§5\.11\)5\_12\_allergy\_check\_before\_medication31 \(policy\.md§5\.12\)5\_9\_med\_request\_status\_active32 \(tools\.py:990\)3\_1\_purpose\_must\_be\_patient\_care21 \(policy\.md§3\.1\)5\_9\_service\_request\_status\_active12 \(tools\.py:1217\)5\_9\_observation\_category\_display\_required12 \(tools\.py:694\)5\_9\_observation\_category\_required12 \(tools\.py:688\)Table 3:Rule firings by bucket\.
### A\.2Cedar Schema
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41entityAgent=\{
42provider:String,
43\};
44entityUser;
45entityLabel;
46entityTool;
47entityTaint;
48
49
50
51
52entityTrajectory=\{
53step\_count:Long,
54label:Label,
55taints:Set<Taint\>,
56\};
57
58entityMessagein\[Trajectory\]=\{
59content:String,
60role:String,
61\};
62
63
64
65
66
67typeWorkspaceContext=\{
68cwd:String,
69permission\_mode:String,
70transcript\_path:String,
71\};
72
73typeSignatureContext=\{
74matches:Long,
75categories:Set<String\>,
76severity:Long,
77\};
78
79typePolicyContext=\{
80compliant:Bool,
81violations:Set<String\>,
82\};
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104typeSessionContext=\{
105now\_timestamp:String,
106now\_date:String,
107last\_tool\_error:Bool,
108last\_get\_patient\_returned\_multiple:Bool,
109user\_specified\_urgency:Bool,
110user\_specified\_backdate:Bool,
111user\_specified\_correction:Bool,
112user\_confirmed\_allergy\_check:Bool,
113last\_assistant\_restated\_patient:Bool,
114user\_confirmed\_write:Bool,
115pending\_write\_confirmed:Bool,
116current\_call\_is\_duplicate:Bool,
117current\_call\_retries\_failed\_write:Bool,
118current\_call\_patient\_mismatch:Bool,
119current\_call\_is\_backdated:Bool,
120current\_call\_is\_correction:Bool,
121
122
123
124
125
126
127
128
129current\_call\_patient\_unseen:Bool,
130established\_patient\_id?:String,
131prior\_post\_signatures?:Set<String\>,
132failed\_post\_signatures?:Set<String\>,
133seen\_patient\_ids?:Set<String\>,
134\};
135
136
137
138
139
140
141
142
143
144typePreToolUseContext=\{
145workspace:WorkspaceContext,
146signature:SignatureContext,
147policy:PolicyContext,
148label:Label,
149tool:String,
150arguments:String,
151session?:SessionContext,
152\};
153
154action"PreToolUse"appliesTo\{
155principal:\[Agent,User\],
156resource:\[Tool\],
157context:PreToolUseContext,
158\};
159
160typeToolOutputContext=\{
161workspace:WorkspaceContext,
162signature:SignatureContext,
163policy:PolicyContext,
164label:Label,
165content:String,
166session?:SessionContext,
167\};
168
169action"ToolOutput"appliesTo\{
170principal:\[Agent,User\],
171resource:\[Trajectory\],
172context:ToolOutputContext,
173\};
174
175typePromptContext=\{
176workspace:WorkspaceContext,
177signature:SignatureContext,
178label:Label,
179session?:SessionContext,
180\};
181
182action"Prompt"appliesTo\{
183principal:\[Agent,User\],
184resource:\[Message\],
185context:PromptContext,
186\};
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215typeGetObservationInput=\{\_count:Long\};
216typeGetObservationContext=\{
217workspace:WorkspaceContext,
218signature:SignatureContext,
219policy:PolicyContext,
220label:Label,
221input:GetObservationInput,
222session?:SessionContext,
223\};
224action"ToolCall::get\_observation"appliesTo\{
225principal:\[Agent,User\],
226resource:\[Tool\],
227context:GetObservationContext,
228\};
229
230typeGetConditionInput=\{\_count:Long\};
231typeGetConditionContext=\{
232workspace:WorkspaceContext,
233signature:SignatureContext,
234policy:PolicyContext,
235label:Label,
236input:GetConditionInput,
237session?:SessionContext,
238\};
239action"ToolCall::get\_condition"appliesTo\{
240principal:\[Agent,User\],
241resource:\[Tool\],
242context:GetConditionContext,
243\};
244
245typeGetMedicationRequestInput=\{\_count:Long\};
246typeGetMedicationRequestContext=\{
247workspace:WorkspaceContext,
248signature:SignatureContext,
249policy:PolicyContext,
250label:Label,
251input:GetMedicationRequestInput,
252session?:SessionContext,
253\};
254action"ToolCall::get\_medication\_request"appliesTo\{
255principal:\[Agent,User\],
256resource:\[Tool\],
257context:GetMedicationRequestContext,
258\};
259
260typeGetProcedureInput=\{\_count:Long\};
261typeGetProcedureContext=\{
262workspace:WorkspaceContext,
263signature:SignatureContext,
264policy:PolicyContext,
265label:Label,
266input:GetProcedureInput,
267session?:SessionContext,
268\};
269action"ToolCall::get\_procedure"appliesTo\{
270principal:\[Agent,User\],
271resource:\[Tool\],
272context:GetProcedureContext,
273\};
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302typePostObservationInput=\{
303status?:String,
304observation\_category\_present?:Bool,
305observation\_category\_code?:String,
306observation\_category\_system?:String,
307observation\_category\_display?:String,
308issued?:String,
309issued\_in\_window?:Bool,
310\};
311typePostObservationContext=\{
312workspace:WorkspaceContext,
313signature:SignatureContext,
314policy:PolicyContext,
315label:Label,
316input:PostObservationInput,
317session?:SessionContext,
318\};
319action"ToolCall::post\_observation"appliesTo\{
320principal:\[Agent,User\],
321resource:\[Tool\],
322context:PostObservationContext,
323\};
324
325typePostMedicationRequestInput=\{
326status?:String,
327intent?:String,
328medication\_coding\_system?:String,
329medication\_coding\_present:Bool,
330authoredOn?:String,
331authored\_on\_in\_window?:Bool,
332dosing\_complete?:Bool,
333dosing\_explanation\_present?:Bool,
334\};
335typePostMedicationRequestContext=\{
336workspace:WorkspaceContext,
337signature:SignatureContext,
338policy:PolicyContext,
339label:Label,
340input:PostMedicationRequestInput,
341session?:SessionContext,
342\};
343action"ToolCall::post\_medication\_request"appliesTo\{
344principal:\[Agent,User\],
345resource:\[Tool\],
346context:PostMedicationRequestContext,
347\};
348
349
350
351
352
353typePostServiceRequestInput=\{
354status?:String,
355intent?:String,
356priority?:String,
357authoredOn?:String,
358authored\_on\_in\_window?:Bool,
359\};
360typePostServiceRequestContext=\{
361workspace:WorkspaceContext,
362signature:SignatureContext,
363policy:PolicyContext,
364label:Label,
365input:PostServiceRequestInput,
366session?:SessionContext,
367\};
368action"ToolCall::post\_service\_request"appliesTo\{
369principal:\[Agent,User\],
370resource:\[Tool\],
371context:PostServiceRequestContext,
372\};
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
### A\.3Cedar Rules \- 00\_base\.cedar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48@id\("default\_allow"\)
49@description\("Defaultallowallactions;specificforbidrulesinotherfilesoverridethis"\)
50permit\(principal,action,resource\);
### A\.4Cedar Rules \- 02\_patient\_identity\.cedar
1
2
3
4
5
6
7
8
9@id\("medagentbench\_2\_1\_no\_anonymous\_patient\_query"\)
10@source\("policy\.md§2\.1"\)
11@enforcement\("cedar"\)
12@description\("Requireanunambiguouspatientidentifierbeforeretrievingpatient\-specificclinicalresources;forbidget\_observation/get\_condition/get\_medication\_request/get\_procedurewithnopatient\_id"\)
13forbid\(principal,action,resource\)
14when\{
15action==Action::"PreToolUse"&&
16\(context\.tool=="get\_observation"\|\|
17context\.tool=="get\_condition"\|\|
18context\.tool=="get\_medication\_request"\|\|
19context\.tool=="get\_procedure"\)&&
20contexthasarguments&&
21context\.argumentslike"\*\\"patient\_id\\":null\*"
22\};
23
24@id\("medagentbench\_2\_1\_no\_write\_without\_subject"\)
25@source\("policy\.md§2\.1"\)
26@enforcement\("cedar"\)
27@description\("Requireanunambiguouspatientidentifierbeforecreatinganyclinicalresource;forbidpost\_observation/post\_service\_request/post\_medication\_requestwhosepayloadlacksasubjectreference"\)
28forbid\(principal,action,resource\)
29when\{
30action==Action::"PreToolUse"&&
31\(context\.tool=="post\_observation"\|\|
32context\.tool=="post\_service\_request"\|\|
33context\.tool=="post\_medication\_request"\)&&
34contexthasarguments&&
35\!\(context\.argumentslike"\*\\"subject\\":\{\\"reference\\":\\"Patient/\*"\)
36\};
37
38
39
40
41
42
43
44
45
46
47@id\("medagentbench\_2\_2\_resolve\_multiple\_patient\_matches"\)
48@source\("policy\.md§2\.2"\)
49@enforcement\("cedar\+session"\)
50@description\("Ifmultiplepatientmatchesoccur,stopandrequestadditionalidentifiersuntilexactlyonepatientisconfirmed;forbideverynon\-get\_patientcallwhilelast\_get\_patient\_returned\_multiple==true"\)
51forbid\(principal,action,resource\)
52when\{
53action==Action::"PreToolUse"&&
54context\.tool\!="get\_patient"&&
55context\.tool\!="get\_patient\_extended"&&
56contexthassession&&
57context\.sessionhaslast\_get\_patient\_returned\_multiple&&
58context\.session\.last\_get\_patient\_returned\_multiple==true
59\};
60
61
62
63
64
65
66
67
68
69
70@id\("medagentbench\_2\_4\_restate\_patient\_before\_write"\)
71@source\("policy\.md§2\.4"\)
72@enforcement\("cedar\+session"\)
73@description\("Beforeanywriteaction,restatetheconfirmedpatient\(atleastname\+DOBand/orMRN\)andobtainexplicituserconfirmation"\)
74forbid\(principal,action,resource\)
75when\{
76action==Action::"PreToolUse"&&
77\(context\.tool=="post\_observation"\|\|
78context\.tool=="post\_service\_request"\|\|
79context\.tool=="post\_medication\_request"\|\|
80context\.tool=="post\_request"\)&&
81contexthassession&&
82context\.sessionhaspending\_write\_confirmed&&
83context\.session\.pending\_write\_confirmed==false
84\};
85
86
87
88
89
90
91
92
93
94
95@id\("medagentbench\_2\_5\_single\_patient\_per\_session"\)
96@source\("policy\.md§2\.5"\)
97@enforcement\("cedar\+session"\)
98@description\("Eachsessionpertainstoonlyonepatient;forbidanycallreferencingapatient\_iddifferentfromtheoneestablishedearlierinthetrajectory"\)
99forbid\(principal,action,resource\)
100when\{
101action==Action::"PreToolUse"&&
102contexthassession&&
103context\.sessionhascurrent\_call\_patient\_mismatch&&
104context\.session\.current\_call\_patient\_mismatch==true
105\};
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130@id\("medagentbench\_2\_1\_patient\_must\_have\_been\_retrieved"\)
131@source\("tools\.py:638"\)
132@enforcement\("cedar\+session"\)
133@description\("Forbidpost\_\*whosesubjectpatientwasneverfetched\(orsurfacedinapriortooloutput\)earlierinthetrajectory;softwithin\-trajectoryanalogofthepaper's\_patient\_existFHIR\-DBcheck"\)
134forbid\(principal,action,resource\)
135when\{
136action==Action::"PreToolUse"&&
137\(context\.tool=="post\_observation"\|\|
138context\.tool=="post\_service\_request"\|\|
139context\.tool=="post\_medication\_request"\)&&
140contexthassession&&
141context\.sessionhascurrent\_call\_patient\_unseen&&
142context\.session\.current\_call\_patient\_unseen==true
143\};
### A\.5Cedar Rules \- 03\_privacy\.cedar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37@id\("medagentbench\_3\_1\_purpose\_must\_be\_patient\_care"\)
38@source\("policy\.md§3\.1"\)
39@enforcement\("cedar"\)
40@description\("Allowlist:PHIaccessrequirespurpose='patientcare'\.Forbidsanyotherpurpose\(research,employmentscreening,marketing,VIPlookup,audit,curiosity,etc\.\)"\)
41forbid\(principal,action,resource\)
42when\{
43action==Action::"PreToolUse"&&
44contexthasarguments&&
45context\.argumentslike"\*\\"purpose\\":\\"\*"&&
46\!\(context\.argumentslike"\*\\"purpose\\":\\"patientcare\\"\*"\)
47\};
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69@id\("medagentbench\_3\_4\_narrow\_query\_count"\)
70@source\("policy\.md§3\.4"\)
71@enforcement\("cedar\+typed"\)
72@description\("Retrieveonlywhat'sneeded:forbidget\_observation/get\_condition/get\_medication\_request/get\_procedurewith\_count\>50"\)
73forbid\(principal,action,resource\)
74when\{
75\(action==Action::"ToolCall::get\_observation"\|\|
76action==Action::"ToolCall::get\_condition"\|\|
77action==Action::"ToolCall::get\_medication\_request"\|\|
78action==Action::"ToolCall::get\_procedure"\)&&
79contexthasinput&&
80context\.inputhas\_count&&
81context\.input\.\_count\>50
82\};
### A\.6Cedar Rules \- 05\_writes\.cedar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58@id\("medagentbench\_5\_1\_writes\_require\_confirmation"\)
59@source\("policy\.md§5\.1"\)
60@enforcement\("cedar\+session"\)
61@description\("Nowriteswithoutexplicitconfirmationoftheexactintendedcontent;forbidpost\_\*toolcallsunlesscontext\.session\.pending\_write\_confirmed==true"\)
62forbid\(principal,action,resource\)
63when\{
64action==Action::"PreToolUse"&&
65\(context\.tool=="post\_observation"\|\|
66context\.tool=="post\_service\_request"\|\|
67context\.tool=="post\_medication\_request"\|\|
68context\.tool=="post\_request"\)&&
69\!\(contexthassession&&
70context\.sessionhaspending\_write\_confirmed&&
71context\.session\.pending\_write\_confirmed==true\)
72\};
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92@id\("medagentbench\_5\_2\_subject\_linking\_required"\)
93@source\("policy\.md§5\.2"\)
94@enforcement\("cedar\+session"\)
95@description\("Whenasessionpatientisestablished,everywritemustreferenceaPatient/\-prefixedsubject;forbidpost\_\*withnoPatient/refwhilesession\.established\_patient\_idisset"\)
96forbid\(principal,action,resource\)
97when\{
98action==Action::"PreToolUse"&&
99\(context\.tool=="post\_observation"\|\|
100context\.tool=="post\_service\_request"\|\|
101context\.tool=="post\_medication\_request"\)&&
102contexthasarguments&&
103contexthassession&&
104context\.sessionhasestablished\_patient\_id&&
105\!\(context\.argumentslike"\*\\"subject\\":\{\\"reference\\":\\"Patient/\*"\)
106\};
107
108
109
110
111
112
113
114
115
116
117
118
119@id\("medagentbench\_5\_5\_priority\_must\_be\_user\_specified"\)
120@source\("policy\.md§5\.5"\)
121@enforcement\("cedar\+session"\)
122@description\("Priority/urgencyinawritemusttracetoanexplicituserinstruction;forbidstat/urgentpriorityonpost\_service\_requestwhenuserdidnotrequestit"\)
123forbid\(principal,action,resource\)
124when\{
125action==Action::"PreToolUse"&&
126context\.tool=="post\_service\_request"&&
127contexthasarguments&&
128\(context\.argumentslike"\*\\"priority\\":\\"stat\*"\|\|
129context\.argumentslike"\*\\"priority\\":\\"STAT\*"\|\|
130context\.argumentslike"\*\\"priority\\":\\"urgent\*"\|\|
131context\.argumentslike"\*\\"priority\\":\\"asap\*"\|\|
132context\.argumentslike"\*\\"priority\\":\\"ASAP\*"\)&&
133contexthassession&&
134context\.sessionhasuser\_specified\_urgency&&
135context\.session\.user\_specified\_urgency==false
136\};
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154@id\("medagentbench\_5\_6\_duplicate\_detection"\)
155@source\("policy\.md§5\.6"\)
156@enforcement\("cedar\+session"\)
157@description\("Forbidpost\_\*whoseclinical\-fieldssignaturematchesapriorsuccessfulwriteinthesametrajectory"\)
158forbid\(principal,action,resource\)
159when\{
160action==Action::"PreToolUse"&&
161\(context\.tool=="post\_observation"\|\|
162context\.tool=="post\_service\_request"\|\|
163context\.tool=="post\_medication\_request"\)&&
164contexthassession&&
165context\.sessionhascurrent\_call\_is\_duplicate&&
166context\.session\.current\_call\_is\_duplicate==true
167\};
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185@id\("medagentbench\_5\_8\_no\_unauthorized\_corrections"\)
186@source\("policy\.md§5\.8"\)
187@enforcement\("cedar\+session"\)
188@description\("Forbidpost\_\*whosepayloadsuppliesanon\-nullresourceid\(correctionintent\)whentheuserhasnotexplicitlyauthorizedcorrection"\)
189forbid\(principal,action,resource\)
190when\{
191action==Action::"PreToolUse"&&
192\(context\.tool=="post\_observation"\|\|
193context\.tool=="post\_service\_request"\|\|
194context\.tool=="post\_medication\_request"\)&&
195contexthassession&&
196context\.sessionhascurrent\_call\_is\_correction&&
197context\.session\.current\_call\_is\_correction==true&&
198context\.sessionhasuser\_specified\_correction&&
199context\.session\.user\_specified\_correction==false
200\};
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219@id\("medagentbench\_5\_7\_no\_unauthorized\_backdating"\)
220@source\("policy\.md§5\.7"\)
221@enforcement\("cedar\+session"\)
222@description\("Forbidpost\_\*whoseauthoredOn/issued/effectiveDateTimeisonadifferentdatethanthesessionnow,unlesstheuserexplicitlyauthorizedbackdating"\)
223forbid\(principal,action,resource\)
224when\{
225action==Action::"PreToolUse"&&
226\(context\.tool=="post\_observation"\|\|
227context\.tool=="post\_service\_request"\|\|
228context\.tool=="post\_medication\_request"\)&&
229contexthassession&&
230context\.sessionhascurrent\_call\_is\_backdated&&
231context\.session\.current\_call\_is\_backdated==true&&
232context\.sessionhasuser\_specified\_backdate&&
233context\.session\.user\_specified\_backdate==false
234\};
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260@id\("medagentbench\_5\_9\_med\_request\_requires\_medication\_and\_dosing"\)
261@source\("policy\.md§5\.9"\)
262@enforcement\("cedar\+typed"\)
263@description\("MedicationRequestmustincludecompletedosinginstructions\(timing\+route\+doseAndRateperentry,mirroringdata\_model\.py:432\);forbidpost\_medication\_requestwithincompletedosingunlessexplanation\_for\_no\_dosing\_instructionsissupplied"\)
264forbid\(principal,action,resource\)
265when\{
266action==Action::"ToolCall::post\_medication\_request"&&
267contexthasinput&&
268context\.inputhasdosing\_complete&&
269context\.input\.dosing\_complete==false&&
270context\.inputhasdosing\_explanation\_present&&
271context\.input\.dosing\_explanation\_present==false
272\};
273
274@id\("medagentbench\_5\_9\_med\_request\_requires\_medication\_concept"\)
275@source\("policy\.md§5\.9"\)
276@enforcement\("cedar"\)
277@description\("MedicationRequestmustincludeamedicationconcept;forbidpost\_medication\_requestwhosepayloadomitsmedicationCodeableConceptandmedicationReference"\)
278forbid\(principal,action,resource\)
279when\{
280action==Action::"PreToolUse"&&
281context\.tool=="post\_medication\_request"&&
282contexthasarguments&&
283\!\(context\.argumentslike"\*\\"medicationCodeableConcept\\":\*"\)&&
284\!\(context\.argumentslike"\*\\"medicationReference\\":\*"\)
285\};
286
287
288
289
290
291
292
293@id\("medagentbench\_5\_11\_subject\_reference\_must\_be\_patient"\)
294@source\("policy\.md§5\.11"\)
295@enforcement\("cedar"\)
296@description\("subject\.referenceonwrittenresourcesmustbeoftheformPatient/\{patient\_id\};forbidpost\_\*withasubjectofanyotherresourcetype"\)
297forbid\(principal,action,resource\)
298when\{
299action==Action::"PreToolUse"&&
300\(context\.tool=="post\_observation"\|\|
301context\.tool=="post\_service\_request"\|\|
302context\.tool=="post\_medication\_request"\)&&
303contexthasarguments&&
304context\.argumentslike"\*\\"subject\\":\{\\"reference\\":\\"\*"&&
305\!\(context\.argumentslike"\*\\"subject\\":\{\\"reference\\":\\"Patient/\*"\)
306\};
307
308
309
310
311
312
313
314
315
316@id\("medagentbench\_5\_12\_allergy\_check\_before\_medication"\)
317@source\("policy\.md§5\.12"\)
318@enforcement\("cedar\+session"\)
319@description\("BeforepostingaMedicationRequest,theusermustconfirmallergyreview;forbidpost\_medication\_requestunlesscontext\.session\.user\_confirmed\_allergy\_check==true"\)
320forbid\(principal,action,resource\)
321when\{
322action==Action::"PreToolUse"&&
323context\.tool=="post\_medication\_request"&&
324\!\(contexthassession&&
325context\.sessionhasuser\_confirmed\_allergy\_check&&
326context\.session\.user\_confirmed\_allergy\_check==true\)
327\};
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348@id\("medagentbench\_5\_9\_med\_request\_status\_active"\)
349@source\("tools\.py:990"\)
350@enforcement\("cedar\+typed"\)
351@description\("MedicationRequest\.statusmustbe'active'"\)
352forbid\(principal,action,resource\)
353when\{
354action==Action::"ToolCall::post\_medication\_request"&&
355contexthasinput&&
356context\.inputhasstatus&&
357context\.input\.status\!="active"
358\};
359
360
361
362@id\("medagentbench\_5\_9\_med\_request\_intent\_order"\)
363@source\("tools\.py:993"\)
364@enforcement\("cedar\+typed"\)
365@description\("MedicationRequest\.intentmustbe'order'"\)
366forbid\(principal,action,resource\)
367when\{
368action==Action::"ToolCall::post\_medication\_request"&&
369contexthasinput&&
370context\.inputhasintent&&
371context\.input\.intent\!="order"
372\};
373
374
375
376
377
378
379
380
381@id\("medagentbench\_5\_9\_med\_request\_ndc\_coding"\)
382@source\("tools\.py:1004\-1015"\)
383@enforcement\("cedar\+typed"\)
384@description\("MedicationRequestmedicationcodingsystemmustbe'http://hl7\.org/fhir/sid/ndc'"\)
385forbid\(principal,action,resource\)
386when\{
387action==Action::"ToolCall::post\_medication\_request"&&
388contexthasinput&&
389context\.inputhasmedication\_coding\_system&&
390context\.input\.medication\_coding\_system\!="http://hl7\.org/fhir/sid/ndc"
391\};
392
393
394
395@id\("medagentbench\_5\_9\_observation\_status\_final"\)
396@source\("tools\.py:724"\)
397@enforcement\("cedar\+typed"\)
398@description\("Observation\.statusmustbe'final'"\)
399forbid\(principal,action,resource\)
400when\{
401action==Action::"ToolCall::post\_observation"&&
402contexthasinput&&
403context\.inputhasstatus&&
404context\.input\.status\!="final"
405\};
406
407
408
409
410
411
412
413
414@id\("medagentbench\_5\_9\_observation\_category\_valid"\)
415@source\("tools\.py:711"\)
416@enforcement\("cedar\+typed"\)
417@description\("Observationcategory\[0\]\.coding\[0\]\.codemustbe'vital\-signs'or'laboratory'"\)
418forbid\(principal,action,resource\)
419when\{
420action==Action::"ToolCall::post\_observation"&&
421contexthasinput&&
422context\.inputhasobservation\_category\_code&&
423context\.input\.observation\_category\_code\!="vital\-signs"&&
424context\.input\.observation\_category\_code\!="laboratory"
425\};
426
427
428
429@id\("medagentbench\_5\_9\_service\_request\_status\_active"\)
430@source\("tools\.py:1217"\)
431@enforcement\("cedar\+typed"\)
432@description\("ServiceRequest\.statusmustbe'active'"\)
433forbid\(principal,action,resource\)
434when\{
435action==Action::"ToolCall::post\_service\_request"&&
436contexthasinput&&
437context\.inputhasstatus&&
438context\.input\.status\!="active"
439\};
440
441
442
443@id\("medagentbench\_5\_9\_service\_request\_intent\_order"\)
444@source\("tools\.py:1220"\)
445@enforcement\("cedar\+typed"\)
446@description\("ServiceRequest\.intentmustbe'order'"\)
447forbid\(principal,action,resource\)
448when\{
449action==Action::"ToolCall::post\_service\_request"&&
450contexthasinput&&
451context\.inputhasintent&&
452context\.input\.intent\!="order"
453\};
454
455
456
457
458
459
460
461
462
463@id\("medagentbench\_5\_7\_observation\_must\_have\_issued"\)
464@source\("tools\.py:650"\)
465@enforcement\("cedar\+typed"\)
466@description\("Observation\.issuedmustbepresent;forbidpost\_observationthatomitstheissuedtimestamp"\)
467forbid\(principal,action,resource\)
468when\{
469action==Action::"ToolCall::post\_observation"&&
470contexthasinput&&
471\!\(context\.inputhasissued\)
472\};
473
474
475
476@id\("medagentbench\_5\_7\_med\_request\_must\_have\_authoredOn"\)
477@source\("tools\.py:944"\)
478@enforcement\("cedar\+typed"\)
479@description\("MedicationRequest\.authoredOnmustbepresent;forbidpost\_medication\_requestthatomitsit"\)
480forbid\(principal,action,resource\)
481when\{
482action==Action::"ToolCall::post\_medication\_request"&&
483contexthasinput&&
484\!\(context\.inputhasauthoredOn\)
485\};
486
487
488
489@id\("medagentbench\_5\_7\_service\_request\_must\_have\_authoredOn"\)
490@source\("tools\.py:1200"\)
491@enforcement\("cedar\+typed"\)
492@description\("ServiceRequest\.authoredOnmustbepresent;forbidpost\_service\_requestthatomitsit"\)
493forbid\(principal,action,resource\)
494when\{
495action==Action::"ToolCall::post\_service\_request"&&
496contexthasinput&&
497\!\(context\.inputhasauthoredOn\)
498\};
499
500
501
502
503
504
505
506
507
508
509@id\("medagentbench\_5\_9\_observation\_category\_system"\)
510@source\("tools\.py:703"\)
511@enforcement\("cedar\+typed"\)
512@description\("Observationcategorycodingsystemmustbe'http://hl7\.org/fhir/observation\-category'"\)
513forbid\(principal,action,resource\)
514when\{
515action==Action::"ToolCall::post\_observation"&&
516contexthasinput&&
517context\.inputhasobservation\_category\_system&&
518context\.input\.observation\_category\_system\!="http://hl7\.org/fhir/observation\-category"
519\};
520
521
522
523
524
525
526
527
528
529
530
531
532@id\("medagentbench\_5\_9\_med\_request\_coding\_must\_be\_present"\)
533@source\("tools\.py:999"\)
534@enforcement\("cedar\+typed"\)
535@description\("MedicationRequestmedicationCodeableConceptmustincludeacodingwithasystem;forbidpost\_medication\_requestwhosepayloadlacksanycoding\[0\]\.system"\)
536forbid\(principal,action,resource\)
537when\{
538action==Action::"ToolCall::post\_medication\_request"&&
539contexthasinput&&
540context\.inputhasmedication\_coding\_present&&
541context\.input\.medication\_coding\_present==false
542\};
543
544
545
546
547
548
549
550
551
552
553@id\("medagentbench\_5\_9\_service\_request\_priority\_stat"\)
554@source\("tools\.py:1223"\)
555@enforcement\("cedar\+typed"\)
556@description\("ServiceRequest\.prioritymustbe'stat'"\)
557forbid\(principal,action,resource\)
558when\{
559action==Action::"ToolCall::post\_service\_request"&&
560contexthasinput&&
561context\.inputhaspriority&&
562context\.input\.priority\!="stat"
563\};
564
565
566
567
568
569
570
571
572@id\("medagentbench\_5\_9\_observation\_category\_display\_value"\)
573@source\("tools\.py:716"\)
574@enforcement\("cedar\+typed"\)
575@description\("Observationcategory\[0\]\.coding\[0\]\.displaymustbe'VitalSigns'or'Laboratory'"\)
576forbid\(principal,action,resource\)
577when\{
578action==Action::"ToolCall::post\_observation"&&
579contexthasinput&&
580context\.inputhasobservation\_category\_display&&
581context\.input\.observation\_category\_display\!="VitalSigns"&&
582context\.input\.observation\_category\_display\!="Laboratory"
583\};
584
585
586
587
588
589
590
591@id\("medagentbench\_5\_9\_observation\_category\_display\_required"\)
592@source\("tools\.py:694"\)
593@enforcement\("cedar\+typed"\)
594@description\("Observationcategory\[0\]\.coding\[0\]\.displaymustbepresent;forbidpost\_observationwhosecategorycodingomitsdisplay"\)
595forbid\(principal,action,resource\)
596when\{
597action==Action::"ToolCall::post\_observation"&&
598contexthasinput&&
599context\.inputhasobservation\_category\_code&&
600\!\(context\.inputhasobservation\_category\_display\)
601\};
602
603
604
605
606
607
608
609
610
611
612
613@id\("medagentbench\_5\_9\_observation\_category\_required"\)
614@source\("tools\.py:688"\)
615@enforcement\("cedar\+typed"\)
616@description\("Observationmusthaveacategory;forbidpost\_observationwhosepayloadomitscategoryentirely"\)
617forbid\(principal,action,resource\)
618when\{
619action==Action::"ToolCall::post\_observation"&&
620contexthasinput&&
621context\.inputhasobservation\_category\_present&&
622context\.input\.observation\_category\_present==false
623\};
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640@id\("medagentbench\_5\_7\_observation\_issued\_in\_window"\)
641@source\("tools\.py:654"\)
642@enforcement\("cedar\+typed"\)
643@description\("Observation\.issuedmustbewithin1hofthebenchmarkservertime;forbidpost\_observationwhoseissuedfallsoutsidethetolerancewindow"\)
644forbid\(principal,action,resource\)
645when\{
646action==Action::"ToolCall::post\_observation"&&
647contexthasinput&&
648context\.inputhasissued\_in\_window&&
649context\.input\.issued\_in\_window==false
650\};
651
652
653
654
655
656
657@id\("medagentbench\_5\_7\_med\_request\_authored\_on\_in\_window"\)
658@source\("tools\.py:949"\)
659@enforcement\("cedar\+typed"\)
660@description\("MedicationRequest\.authoredOnmustbewithin1hofthebenchmarkservertime;forbidpost\_medication\_requestwhoseauthoredOnfallsoutsidethetolerancewindow"\)
661forbid\(principal,action,resource\)
662when\{
663action==Action::"ToolCall::post\_medication\_request"&&
664contexthasinput&&
665context\.inputhasauthored\_on\_in\_window&&
666context\.input\.authored\_on\_in\_window==false
667\};
668
669
670
671
672
673@id\("medagentbench\_5\_7\_service\_request\_authored\_on\_in\_window"\)
674@source\("tools\.py:1205"\)
675@enforcement\("cedar\+typed"\)
676@description\("ServiceRequest\.authoredOnmustbewithin1hofthebenchmarkservertime;forbidpost\_service\_requestwhoseauthoredOnfallsoutsidethetolerancewindow"\)
677forbid\(principal,action,resource\)
678when\{
679action==Action::"ToolCall::post\_service\_request"&&
680contexthasinput&&
681context\.inputhasauthored\_on\_in\_window&&
682context\.input\.authored\_on\_in\_window==false
683\};
### A\.7Cedar Rules \- 06\_tool\_safety\.cedar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15@id\("medagentbench\_6\_3\_stop\_on\_tool\_error"\)
16@source\("policy\.md§6\.3"\)
17@enforcement\("cedar\+session"\)
18@description\("Ontoolerrors:stop,reportthefailure,andproposesafenextsteps;donotguessresults"\)
19forbid\(principal,action,resource\)
20when\{
21action==Action::"PreToolUse"&&
22contexthassession&&
23context\.sessionhaslast\_tool\_error&&
24context\.session\.last\_tool\_error==true
25\};
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43@id\("medagentbench\_6\_4\_no\_duplicate\_write\_retry"\)
44@source\("policy\.md§6\.4"\)
45@enforcement\("cedar\+session"\)
46@description\("Forbidpost\_\*whoseclinical\-fieldssignaturematchesapriorfailedwriteinthesametrajectory"\)
47forbid\(principal,action,resource\)
48when\{
49action==Action::"PreToolUse"&&
50\(context\.tool=="post\_observation"\|\|
51context\.tool=="post\_service\_request"\|\|
52context\.tool=="post\_medication\_request"\)&&
53contexthassession&&
54context\.sessionhascurrent\_call\_retries\_failed\_write&&
55context\.session\.current\_call\_retries\_failed\_write==true
56\};Similar Articles
PolicyGuide: From Guarding One Action to Guiding the Whole Workflow for Policy-Compliant LLM Agents
PolicyGuide compiles domain policies into workflow graphs and uses a proactive verifier to guide LLM agents through multi-step procedures, improving policy compliance across various benchmarks.
PolicyGuard: A Dialogue-Grounded Sub-Agent Verifier for Policy Adherence in LLM Agents
PolicyGuard is a sub-agent verifier that enhances LLM agent policy adherence by providing contextual reasoning and conversation-specific feedback across multi-turn interactions, achieving significant improvements on the tau^2-BENCH benchmark.
Beyond the Library: An Agentic Framework for Autoformalizing Research Mathematics
Presents an agentic framework using general coding LLMs to autoformalize research-level mathematics into Lean 4 code, evaluated on Putnam problems and STOC conference papers.
Governance by Construction for Generalist Agents
This paper presents CUGA's policy system, a modular policy-as-code layer that enforces governance at multiple checkpoints in LLM agent execution, enabling predictable and auditable behavior without model fine-tuning.
PolicyAlign: Direct Policy-Based Safety Alignment for Large Language Models
PolicyAlign proposes a framework that directly aligns LLMs with natural-language safety policies via synthetic instruction generation and on-policy self-distillation, improving safety without relying on costly supervision data.