One gate over both engines
This course taught two engines. The Python PolicyEngine checks the tool name and its arguments; the document PolicyEvaluator checks conditions written in YAML. A real gate calls both, because each catches what the other cannot.
What each engine is good at
The constraint engine from lesson 6 is the fast, absolute layer: this role may call these tools and no others, decided in Python at the choke point. The document engine from lesson 11 is the layer that changes without a deploy: a refund over a hundred needs a human, written in a file an auditor can read. A support agent needs both, the hard tool allow-list and the money rule that a manager might edit.
Calling both
from agent_control_plane import AgentKernel, PolicyEngine
from agent_os.policies.schema import PolicyDocument
from agent_os.policies.evaluator import PolicyEvaluator
constraints = PolicyEngine()
constraints.add_constraint("support", ["lookup_order", "issue_refund"])
kernel = AgentKernel(policy_engine=constraints)
money = PolicyEvaluator(policies=[PolicyDocument.from_yaml("refunds.yaml")])
def allowed(tool, args):
verdict = kernel.intercept_tool_execution("support", tool, args)
if verdict is not None:
return False, verdict["policy"]
decision = money.evaluate({"tool": tool, **args})
return decision.allowed, decision.matched_rule or decision.actionThe tool allow-list runs first. Only a call it permits reaches the document engine, which then judges the arguments against the YAML rules. A call has to pass both to be allowed, and the reason a refusal gives says which layer stopped it.
The four cases
for tool, args in [("lookup_order", {}), ("issue_refund", {"amount": 40}),
("issue_refund", {"amount": 4000}), ("delete_order", {})]:
print(f"{tool:13} {str(args):18}", allowed(tool, args))A lookup and a small refund pass both engines. A four-thousand refund clears the tool allow-list and is stopped by the document rule block_big_refunds. A delete is stopped by the constraint engine before the document engine is ever consulted. One function asks both engines and returns a single answer.
- Swap the order so the document engine runs first, and find a call whose reason changes.
- Add a second document with a higher-priority rule and watch it win, as in lesson 13.
- Return the full decision object instead of a string and read its
actionfield.
Every expert started right here.