Agentic AI Governance: Policy, Guardrails, and Human Oversight
TL;DR — Agentic AI governance ensures autonomous agents operate within defined boundaries using policy-as-code, guardrails, and human oversight. EU AI Act Article 14 requires human oversight — agents must be stoppable. Article 9 requires risk management. Article 12 requires automatic record-keeping. NIST AI RMF maps to four functions: Govern, Map, Measure, Manage. Three guardrail types: input (block bad requests), output (validate responses), tool (check tool calls). Four policy outcomes: allow, warn, require_approval, block. Human-in-the-loop for high-risk actions: agent pauses, human approves/rejects, fail-safe auto-deny on timeout. Policy-as-code: YAML/OPA/Cedar rules enforced by external engine — never trust the agent to police itself. Microsoft Agent Governance Toolkit covers 10/10 OWASP Agentic Top 10. Circuit breakers prevent cascading failures. Kill switches for emergency shutdown. Audit trails with tamper-evident records. Aligns with OWASP Agentic AI Top 10, MCP security, zero-trust, and AI incident response.
Microsoft's Agent Governance Toolkit provides policy enforcement, zero-trust identity, execution sandboxing, and reliability engineering for autonomous AI agents. It covers all 10 OWASP Agentic Top 10 risks. The architecture is simple: Agent → Policy Engine → Identity → Audit Log.
Cerbos notes the critical insight: "Move policy out of the agent. Today this layer is just whatever the agent framework chose to expose. Often the agent itself decides what tools it can call, which is the security model of asking a child whether they're allowed dessert."
Governance Architecture
Rules"] Evaluate["Evaluate Action"] end subgraph Outcomes["Policy Outcomes"] Allow["allow
(proceed)"] Warn["warn
(proceed + log)"] Approval["require_approval
(pause for human)"] Block["block
(deny)"] end subgraph HITL["Human-in-the-Loop"] Notify["Notify Approver"] Review["Human Review"] Decision["Approve / Reject"] end subgraph Audit["Audit Trail"] Log["Tamper-Evident
Decision Records"] end Plan --> Evaluate Evaluate --> Rules Rules --> Allow Rules --> Warn Rules --> Approval Rules --> Block Allow --> Execute Warn --> Execute Approval --> Notify Notify --> Review Review --> Decision Decision -->|approve| Execute Decision -->|reject| Block Block --> Log Execute --> Log Allow --> Log
Regulatory Framework Alignment
| Framework | Key Requirements for Agents | Governance Implementation |
|---|---|---|
| EU AI Act Art. 9 | Risk management system | Identify foreseeable risks, circuit breakers, behavioral monitoring |
| EU AI Act Art. 14 | Human oversight | HITL approval, kill switch, stop mechanism |
| EU AI Act Art. 12 | Automatic record-keeping | Tamper-evident audit logs, decision records |
| EU AI Act Art. 13 | Transparency to deployers | Policy disclosure, action explanations |
| NIST AI RMF: Govern | Who can deploy, budgets, allowed actions | Policy-as-code, tool allowlisting |
| NIST AI RMF: Map | Risk surfaces, tool access, blast radius | Risk inventory, dependency mapping |
| NIST AI RMF: Measure | Cost variance, action frequency, violations | Metrics, dashboards, alerts |
| NIST AI RMF: Manage | Enforce limits, degrade gracefully, stop | Circuit breakers, kill switch, fail-closed |
| OWASP ASI01-10 | 10 agentic security risks | Guardrails, sandboxing, isolation |
| ISO 42001 | AI management system | Governance framework, continuous improvement |
Policy-as-Code
# agent-policy.yaml — Enterprise agentic AI governance policy
version: "1.0"
metadata:
name: enterprise-agent-governance
description: Production policy for autonomous AI agents
rules:
# ASI01: Goal hijack prevention
- name: block-goal-override
condition: "action.type == 'prompt_injection' or input.contains('ignore previous instructions')"
action: block
description: "Block prompt injection attempts"
priority: 1000
# ASI02: Tool misuse prevention
- name: allowlist-tools
condition: "action.tool not in ['search_kb', 'get_document', 'query_graph', 'send_email']"
action: block
description: "Only allowlisted tools can be called"
priority: 900
# ASI03: Identity and privilege
- name: check-permissions
condition: "not user.has_permission(action.tool)"
action: block
description: "User must have permission for tool"
priority: 800
# High-risk: require human approval
- name: approve-large-transfer
condition: "action.type == 'transfer' and action.amount > 10000"
action: require_approval
approvers: ["treasury-ops", "compliance"]
timeout_seconds: 300
description: "Transfers > $10K require human approval"
priority: 100
- name: approve-data-deletion
condition: "action.type == 'delete'"
action: require_approval
approvers: ["data-steward"]
timeout_seconds: 600
description: "Data deletion requires steward approval"
priority: 100
- name: approve-external-email
condition: "action.type == 'send_email' and recipient.domain != 'company.com'"
action: require_approval
approvers: ["manager"]
timeout_seconds: 300
description: "External emails require manager approval"
priority: 100
# ASI08: Circuit breaker
- name: rate-limit
condition: "user.actions_per_minute > 20"
action: block
description: "Rate limit: 20 actions per minute"
priority: 700
# Cost control
- name: budget-limit
condition: "user.daily_spend > user.daily_budget"
action: block
description: "Block when daily budget exceeded"
priority: 600
# Default: allow
- name: default-allow
condition: "true"
action: allow
description: "Default: allow if no rule blocks"
priority: 0
Human-in-the-Loop Implementation
from dataclasses import dataclass
from datetime import datetime, timedelta
import json
@dataclass
class ApprovalRequest:
action: str
context: dict
approvers: list[str]
timeout: int = 300 # 5 minutes
created_at: datetime = None
def __post_init__(self):
self.created_at = datetime.utcnow()
@dataclass
class ApprovalDecision:
approved: bool
approver: str
reason: str
timestamp: datetime = None
def __post_init__(self):
self.timestamp = datetime.utcnow()
class HumanInTheLoop:
def __init__(self, policy_engine, notification_service, audit_logger):
self.policy = policy_engine
self.notifier = notification_service
self.audit = audit_logger
async def evaluate_action(self, action, user, context):
"""Evaluate action against policy and handle approval if needed."""
decision = self.policy.evaluate(action, user, context)
if decision.outcome == "allow":
self.audit.log(user, action, "allowed", decision.reason)
return True
elif decision.outcome == "warn":
self.audit.log(user, action, "warned", decision.reason)
return True # Proceed with warning
elif decision.outcome == "block":
self.audit.log(user, action, "blocked", decision.reason)
raise GovernanceBlockedError(decision.reason)
elif decision.outcome == "require_approval":
return await self.request_approval(action, user, decision)
# Fail-closed: unknown outcome = deny
self.audit.log(user, action, "denied", "unknown_outcome")
return False
async def request_approval(self, action, user, decision):
"""Pause execution and request human approval."""
request = ApprovalRequest(
action=action.type,
context=action.context,
approvers=decision.approvers,
timeout=decision.timeout_seconds,
)
# Notify approvers (Slack, email, dashboard)
await self.notifier.notify(
channels=decision.approvers,
message=f"Approval required: {action.type} by {user.id}",
details=action.context,
)
# Wait for response (with timeout)
try:
approval = await self.notifier.wait_for_response(
request_id=request.id,
timeout=decision.timeout_seconds,
)
if approval.approved:
self.audit.log(user, action, "approved",
f"By {approval.approver}: {approval.reason}")
return True
else:
self.audit.log(user, action, "rejected",
f"By {approval.approver}: {approval.reason}")
raise GovernanceDeniedError(approval.reason)
except TimeoutError:
# Fail-safe: auto-deny on timeout
self.audit.log(user, action, "auto_denied", "Approval timeout")
raise GovernanceDeniedError("Approval timed out — auto-denied")
Guardrail Types
| Guardrail | When It Runs | What It Checks | Example |
|---|---|---|---|
| Input | Before agent processes | User request validity | Block "ignore instructions" |
| Output | Before response sent | Response safety, PII | Redact SSNs from output |
| Tool | Around tool calls | Arguments, results | Validate SQL query params |
| Goal | During planning | Goal persistence | Detect plan deviation |
| Cost | Each action | Budget limits | Block if daily budget exceeded |
| Rate | Each action | Frequency limits | 20 actions/minute max |
Agentic AI Governance Checklist
- [ ] Read OWASP Top 10 for Agentic Applications
- [ ] Implement policy-as-code (YAML, OPA, or Cedar)
- [ ] Move policy OUT of the agent — external policy engine
- [ ] Configure fail-closed: deny all if policy engine unreachable
- [ ] Implement input guardrails: block bad requests before processing
- [ ] Implement output guardrails: validate/redact responses
- [ ] Implement tool guardrails: check arguments and results
- [ ] Define tool allowlist — agents can only call pre-approved tools
- [ ] Implement human-in-the-loop for high-risk actions
- [ ] Configure approval timeout (default 5 min, fail-safe auto-deny)
- [ ] Set up approver notification (Slack, email, dashboard)
- [ ] Implement circuit breakers for cascading failure prevention
- [ ] Configure kill switch for emergency agent shutdown
- [ ] Set up tamper-evident audit logging for all decisions
- [ ] Send audit logs to SIEM (Splunk, ELK, Datadog)
- [ ] Implement rate limiting: 20 actions/minute per user
- [ ] Implement budget controls: daily spend limits per user
- [ ] Implement goal persistence checks (ASI01 defense)
- [ ] Use zero-trust architecture between agents
- [ ] Apply MCP security for tool connections
- [ ] Align with EU AI Act Articles 9, 12, 14
- [ ] Map to NIST AI RMF: Govern, Map, Measure, Manage
- [ ] Consider ISO 42001 certification
- [ ] Sponsor every agent with a named human owner
- [ ] Implement behavioral drift monitoring with platform monitoring
- [ ] Set up AI incident response plan
- [ ] Run adversarial tests in CI/CD for policy enforcement
- [ ] Test fail-closed behavior: kill policy engine, verify all actions denied
- [ ] Test kill switch: verify agent stops within 5 seconds
- [ ] Test approval timeout: verify auto-deny after timeout
- [ ] Document all agent capabilities, boundaries, and policies
- [ ] Quarterly governance audit: review policies, audit logs, incidents
- [ ] Consider AI vendor risk assessment for third-party agents
- [ ] Train approvers on human-agent trust risks (ASI09)
- [ ] Implement automatic rollback for failed agent actions
- [ ] Consider self-hosted AI for data sovereignty
FAQ
What is agentic AI governance?
Agentic AI governance is the framework of policies, guardrails, and oversight mechanisms that ensure autonomous AI agents operate safely within defined boundaries. It includes: policy-as-code (YAML/OPA rules that agents must follow), human-in-the-loop approval for high-risk actions, tool allowlisting, audit logging of all agent decisions, circuit breakers to prevent cascading failures, kill switches for emergency shutdown, and behavioral drift monitoring. Governance is required by EU AI Act Article 14 (human oversight), Article 9 (risk management), and Article 12 (record-keeping). The NIST AI RMF provides a voluntary framework with four functions: Govern, Map, Measure, Manage.
What are AI agent guardrails?
Guardrails are automated checks that validate agent behavior at runtime. Three types: (1) Input guardrails — block disallowed user requests before the agent processes them. (2) Output guardrails — validate or redact agent responses before they reach the user. (3) Tool guardrails — check arguments and results around tool calls. Guardrails can block (stop execution), warn (proceed with advisory), or require_approval (pause for human review). They are defined as code (YAML policy, OPA rules, Cedar policies) and enforced by a policy engine external to the agent — never trust the agent to police itself.
How does the EU AI Act apply to AI agents?
The EU AI Act (Regulation 2024/1689) regulates AI systems by risk tier: unacceptable (banned), high-risk (strict obligations), limited risk (transparency), minimal risk (voluntary). AI agents are not a separate legal category — they are AI systems. Key articles for agents: Article 9 (risk management — identify foreseeable risks including unauthorized actions and cascading failures), Article 14 (human oversight — ability to understand, monitor, and interrupt agent operation via stop mechanism), Article 12 (automatic record-keeping throughout system lifetime), Article 13 (transparency to deployers). High-risk obligations apply from August 2026 (may be deferred to December 2027 per Digital Omnibus proposal).
What is human-in-the-loop for AI agents?
Human-in-the-loop (HITL) is a governance pattern where certain agent actions require explicit human approval before execution. The agent can decide an action is needed, but execution pauses until a human approves or rejects. Use HITL for: financial transactions above threshold, data deletion, sending external communications, executing code, and any action with irreversible consequences. Implementation: policy defines which actions require approval, agent pauses and notifies approver, approver reviews context and decides, agent resumes or halts. Fail-safe: if no approver responds within timeout (default 5 min), action is auto-denied. Microsoft's Agent Governance Toolkit and OpenAI's Approvals API provide HITL implementations.
What is policy-as-code for AI agents?
Policy-as-code defines agent governance rules in machine-readable format (YAML, OPA/Rego, Cedar) enforced by an external policy engine. Example rule: 'if action.type == transfer and amount > 10000, require_approval from treasury-ops'. The policy engine evaluates every agent action against rules and returns allow, warn, require_approval, or block. Benefits: version-controlled policies, automated testing, consistent enforcement, audit trail of every decision. Move policy OUT of the agent — the agent should not decide what it's allowed to do. Use external engines like OPA, Cedar, or Microsoft Agent Governance Toolkit. Fail-closed: if policy engine is unreachable, deny all actions.
Want a self-hosted AI company brain that does all of this out of the box?
Book a demo →