$npx -y skills add github/awesome-copilot --skill agent-governancePatterns and techniques for adding governance, safety, and trust controls to AI agent systems. Use this skill when: - Building AI agents that call external tools (APIs, databases, file systems) - Implementing policy-based access controls for agent tool usage - Adding semantic int
| 1 | # Agent Governance Patterns |
| 2 | |
| 3 | Patterns for adding safety, trust, and policy enforcement to AI agent systems. |
| 4 | |
| 5 | ## Overview |
| 6 | |
| 7 | Governance patterns ensure AI agents operate within defined boundaries — controlling which tools they can call, what content they can process, how much they can do, and maintaining accountability through audit trails. |
| 8 | |
| 9 | ``` |
| 10 | User Request → Intent Classification → Policy Check → Tool Execution → Audit Log |
| 11 | ↓ ↓ ↓ |
| 12 | Threat Detection Allow/Deny Trust Update |
| 13 | ``` |
| 14 | |
| 15 | ## When to Use |
| 16 | |
| 17 | - **Agents with tool access**: Any agent that calls external tools (APIs, databases, shell commands) |
| 18 | - **Multi-agent systems**: Agents delegating to other agents need trust boundaries |
| 19 | - **Production deployments**: Compliance, audit, and safety requirements |
| 20 | - **Sensitive operations**: Financial transactions, data access, infrastructure management |
| 21 | |
| 22 | --- |
| 23 | |
| 24 | ## Pattern 1: Governance Policy |
| 25 | |
| 26 | Define what an agent is allowed to do as a composable, serializable policy object. |
| 27 | |
| 28 | ```python |
| 29 | from dataclasses import dataclass, field |
| 30 | from enum import Enum |
| 31 | from typing import Optional |
| 32 | import re |
| 33 | |
| 34 | class PolicyAction(Enum): |
| 35 | ALLOW = "allow" |
| 36 | DENY = "deny" |
| 37 | REVIEW = "review" # flag for human review |
| 38 | |
| 39 | @dataclass |
| 40 | class GovernancePolicy: |
| 41 | """Declarative policy controlling agent behavior.""" |
| 42 | name: str |
| 43 | allowed_tools: list[str] = field(default_factory=list) # allowlist |
| 44 | blocked_tools: list[str] = field(default_factory=list) # blocklist |
| 45 | blocked_patterns: list[str] = field(default_factory=list) # content filters |
| 46 | max_calls_per_request: int = 100 # rate limit |
| 47 | require_human_approval: list[str] = field(default_factory=list) # tools needing approval |
| 48 | |
| 49 | def check_tool(self, tool_name: str) -> PolicyAction: |
| 50 | """Check if a tool is allowed by this policy.""" |
| 51 | if tool_name in self.blocked_tools: |
| 52 | return PolicyAction.DENY |
| 53 | if tool_name in self.require_human_approval: |
| 54 | return PolicyAction.REVIEW |
| 55 | if self.allowed_tools and tool_name not in self.allowed_tools: |
| 56 | return PolicyAction.DENY |
| 57 | return PolicyAction.ALLOW |
| 58 | |
| 59 | def check_content(self, content: str) -> Optional[str]: |
| 60 | """Check content against blocked patterns. Returns matched pattern or None.""" |
| 61 | for pattern in self.blocked_patterns: |
| 62 | if re.search(pattern, content, re.IGNORECASE): |
| 63 | return pattern |
| 64 | return None |
| 65 | ``` |
| 66 | |
| 67 | ### Policy Composition |
| 68 | |
| 69 | Combine multiple policies (e.g., org-wide + team + agent-specific): |
| 70 | |
| 71 | ```python |
| 72 | def compose_policies(*policies: GovernancePolicy) -> GovernancePolicy: |
| 73 | """Merge policies with most-restrictive-wins semantics.""" |
| 74 | combined = GovernancePolicy(name="composed") |
| 75 | |
| 76 | for policy in policies: |
| 77 | combined.blocked_tools.extend(policy.blocked_tools) |
| 78 | combined.blocked_patterns.extend(policy.blocked_patterns) |
| 79 | combined.require_human_approval.extend(policy.require_human_approval) |
| 80 | combined.max_calls_per_request = min( |
| 81 | combined.max_calls_per_request, |
| 82 | policy.max_calls_per_request |
| 83 | ) |
| 84 | if policy.allowed_tools: |
| 85 | if combined.allowed_tools: |
| 86 | combined.allowed_tools = [ |
| 87 | t for t in combined.allowed_tools if t in policy.allowed_tools |
| 88 | ] |
| 89 | else: |
| 90 | combined.allowed_tools = list(policy.allowed_tools) |
| 91 | |
| 92 | return combined |
| 93 | |
| 94 | |
| 95 | # Usage: layer policies from broad to specific |
| 96 | org_policy = GovernancePolicy( |
| 97 | name="org-wide", |
| 98 | blocked_tools=["shell_exec", "delete_database"], |
| 99 | blocked_patterns=[r"(?i)(api[_-]?key|secret|password)\s*[:=]"], |
| 100 | max_calls_per_request=50 |
| 101 | ) |
| 102 | team_policy = GovernancePolicy( |
| 103 | name="data-team", |
| 104 | allowed_tools=["query_db", "read_file", "write_report"], |
| 105 | require_human_approval=["write_report"] |
| 106 | ) |
| 107 | agent_policy = compose_policies(org_policy, team_policy) |
| 108 | ``` |
| 109 | |
| 110 | ### Policy as YAML |
| 111 | |
| 112 | Store policies as configuration, not code: |
| 113 | |
| 114 | ```yaml |
| 115 | # governance-policy.yaml |
| 116 | name: production-agent |
| 117 | allowed_tools: |
| 118 | - search_documents |
| 119 | - query_database |
| 120 | - send_email |
| 121 | blocked_tools: |
| 122 | - shell_exec |
| 123 | - delete_record |
| 124 | blocked_patterns: |
| 125 | - "(?i)(api[_-]?key|secret|password)\\s*[:=]" |
| 126 | - "(?i)(drop|truncate|delete from)\\s+\ |