Default deny, and the allow-list
Lesson 4 ended by asking you to delete the add_constraint line. This lesson explains what you saw, which is the policy engine's most important default.
A policy engine with nothing configured does not let everything through. It lets nothing through.
from agent_control_plane import PolicyEngine
policy = PolicyEngine()
print(policy.check_violation("support", "lookup_order", {}))check_violation is the method the kernel calls for you. It returns None when there is no violation and a sentence when there is, which is the same convention as the gate itself.
A brand new engine knows about no roles, so a role it has never heard of can use no tools. Deny by default means a forgotten configuration file fails shut rather than open, which is the behaviour you want at three in the morning.
Naming what is allowed
policy = PolicyEngine()
policy.add_constraint("support", ["lookup_order", "issue_refund"])
for tool in ["lookup_order", "issue_refund", "send_email", "delete_order"]:
print(f"{tool:14} {policy.check_violation('support', tool, {})}")Two allowed, two refused, and nothing had to be written down about the two that were refused. This is the toolkit's phrasing of a rule that is easy to get backwards: you list what is permitted, and everything else follows from that.
The role is just the first argument
There is no registry of agents and no identity object here. The first argument to check_violation is a string, and it is both who the agent is and what role it has.
policy.add_constraint("readonly", ["lookup_order"])
for role in ["support", "readonly", "typo"]:
print(f"{role:9} issue_refund -> {policy.check_violation(role, 'issue_refund', {})}")readonly cannot refund. typo cannot do anything at all, and that is the point worth remembering: a misspelt agent name is not an error, it is an agent with no permissions. The program keeps running and every call is refused.
Lesson 27 comes back to identity properly, with signed credentials instead of a string you can mistype.
- Add a third role that can send email but not look anything up.
- Misspell the role in
intercept_tool_executionfrom lesson 4 and watch a working agent go completely silent. - Call
add_constrainttwice for the same role with different lists, then work out from the output whether the second call adds to the first or replaces it.
Every expert started right here.