Agent Governance Toolkitagent-governance-toolkit 4.1.0 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
23 small wins to finish your pathNext lesson

Defaults, and the four actions

Lesson 12 was about which rule matched. This lesson is about what happens when none of them do, and about the fact that four actions produce only two outcomes.

Every document carries a defaults block. The important field is the action taken when no rule matched.

Example
from agent_os.policies.schema import PolicyDocument
from agent_os.policies.evaluator import PolicyEvaluator

for name in ["open.yaml", "shut.yaml"]:
    evaluator = PolicyEvaluator(policies=[PolicyDocument.from_yaml(name)])
    decision = evaluator.evaluate({"tool": "something_nobody_wrote_a_rule_for"})
    print(f"{name:11}", decision.allowed, "|", decision.action)

The default default is allow. That is the opposite of the Python policy engine from lesson 5, which denies anything it was not told about, and it is the single setting most worth changing in a policy you intend to rely on.

Four actions, two outcomes

A rule's action can be allow, deny, block or audit. Only two of those let the call through.

Example
policy = PolicyDocument.from_yaml("actions.yaml")
evaluator = PolicyEvaluator(policies=[policy])
for tool in ["lookup_order", "issue_refund", "send_email", "delete_order"]:
    decision = evaluator.evaluate({"tool": tool})
    print(f"{tool:14} action={decision.action:7} allowed={decision.allowed}")

audit allows the call and marks it as worth recording. It is how you watch a tool you are not ready to forbid, and it is the declarative twin of the shadow mode in lesson 23.

deny and block both refuse and differ only in the word that reaches your logs. Pick one and use it consistently; the decision object reports whichever you wrote.

When evaluation itself goes wrong

If the evaluator raises while working through the rules, it does not pass the error upwards and it does not let the call through. It returns a refusal with a reason saying so.

That is the fail-closed behaviour you want and the opposite of the missing-field case in lesson 11, where a rule that could not be evaluated was simply skipped. The difference is that a missing field is a condition that did not match, while an exception is the engine admitting it does not know.

Try it yourself
  • Remove the defaults block entirely and find out which action you get.
  • Change audit to deny and watch allowed flip.
  • Set the default to deny and rerun lesson 10's script, where the forty pound refund matched nothing.

Slow is fine. Stopping is the only problem.