Scope, and the rule that applies to everything
A policy document can say which part of your codebase it governs. This lesson writes one, watches it govern everything anyway, and then makes it work.
The field is scope, and it takes a glob. The intent reads clearly: this document only applies where the pattern matches.
version: "1.0"
name: refunds
scope: "billing/**"
rules:
- name: block_big_refunds
condition: {field: amount, operator: gt, value: 100}
action: deny
message: Refunds over 100 need a human
defaults:
action: allowA reasonable reading: a call from billing/ is capped, and a call from anywhere else is not. Test that.
from agent_os.policies.schema import PolicyDocument
from agent_os.policies.evaluator import PolicyEvaluator
policy = PolicyDocument.from_yaml("refunds.yaml")
print("scope says:", policy.scope)
evaluator = PolicyEvaluator(policies=[policy])
for path in ["billing/refund.py", "support/reply.py"]:
print(f"{path:20}", evaluator.evaluate({"amount": 4000, "path": path}).allowed)Both refused. The document said it governed billing and it governed the support code too. The scope field was read, stored and never consulted.
Why
The evaluator has two ways of working. The one used so far is flat: it takes the documents you handed it and checks every rule in all of them. Scope belongs to the other one, folder-scoped discovery, which only runs when the evaluator was given a root directory and the context contains a path.
Give it neither and the field is inert. Give it only the path, as above, and it is still inert, because the root directory is the part that switches modes.
Making it work
Put the policy in the folder it governs, name it governance.yaml, and give the evaluator a root to search from.
import os
evaluator = PolicyEvaluator(policies=[], root_dir=os.getcwd())
for path in ["billing/refund.py", "support/reply.py"]:
decision = evaluator.evaluate({"amount": 4000, "path": path})
print(f"{path:20}", decision.allowed, "|", decision.matched_rule)Now the two paths differ. The file sits in billing and governs the code in billing; the support path found no governance file above it and fell back to allowing the call.
The folder is doing the scoping, not the scope field. Placing the file is the mechanism, and scope narrows it further once discovery is already running.
scope as documentation until you have turned on folder discovery. A policy file loaded directly and handed to an evaluator applies to every call that evaluator sees, whatever its scope line says.Files found this way are merged from the root downwards, so a document nearer the call can override a rule of the same name higher up. inherit: false stops the chain at that folder.
- Delete
root_dirfrom the last snippet and watch both paths be refused again. - Put a second
governance.yamlat the root allowing everything, and see which one wins forbilling. - Add
inherit: falseto the billing file and check what stops reaching it.
This is what real progress feels like.