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

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.

Example
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

Example
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.

A deny-list is a promise you have to keep updating. Every new tool someone adds to the agent is allowed until a human remembers to forbid it. An allow-list inverts that, so the person adding a tool has to come and ask.

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.

Example
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.

Try it yourself
  • Add a third role that can send email but not look anything up.
  • Misspell the role in intercept_tool_execution from lesson 4 and watch a working agent go completely silent.
  • Call add_constraint twice 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.