Guide: Retrofit Governance onto an Existing Agent¶
Package:
agent-os-kernelยท Time: 10 minutes ยท Prerequisites: Python 3.10+, existing agent
What You'll Learn¶
- Add policy enforcement to any existing agent in 3 steps โ install, wrap, and configure
- Blocked-pattern detection and audit trail without rewriting existing logic
Got an AI agent already running in production? This tutorial shows you how to add policy enforcement, blocked-pattern detection, and an audit trail in three steps โ without rewriting your existing logic.
What you'll learn:
| Step | What happens |
|---|---|
| 1. Install | Add the toolkit with one command |
| 2. Wrap | Two lines of code around your existing agent |
| 3. Configure | Drop in a single YAML file to define your rules |
| Verify | Run the companion script and see governance in action |
The Agent We're Starting With¶
Here's a typical "before" agent โ useful, but completely ungoverned. It happily executes whatever it's asked:
# before.py โ your existing code, untouched
def run_agent(user_input: str) -> str:
"""A simple agent with no guardrails."""
# ... your existing LLM calls, tool calls, etc.
return f"Agent result for: {user_input}"
# No checks, no audit trail, no blocked patterns
result = run_agent("DROP TABLE users;")
print(result) # ๐ฌ executes without question
By the end of this tutorial, the same run_agent call will be intercepted, evaluated against policy, and either allowed or blocked โ with every decision written to an audit trail.
Step 1: Install¶
That's it. No infrastructure changes, no config files yet.
Note:
[full]pulls in YAML policy support, framework integrations, and audit tooling. For a minimal install you can usepip install agent-os-kernelinstead, but YAML policy loading requires the[nexus]or[full]extra.
Step 2: Wrap Your Agent¶
Add two imports and wrap your existing function with a governance kernel. Your original run_agent logic stays completely unchanged:
# after.py โ the only new code you write
from agent_os.integrations import LangChainKernel # swap for your framework
from agent_os.integrations.base import GovernancePolicy
# --- NEW: create a kernel (one-time setup) ---
policy = GovernancePolicy(
name="my-agent-policy",
blocked_patterns=["DROP TABLE", "rm -rf", "os.system"],
max_tool_calls=10,
)
kernel = LangChainKernel(policy=policy)
ctx = kernel.create_context("my-agent")
# --- your original function, unchanged ---
def run_agent(user_input: str) -> str:
"""A simple agent with no guardrails."""
return f"Agent result for: {user_input}"
# --- NEW: check before every call ---
def governed_run(user_input: str) -> str:
allowed, reason = kernel.pre_execute(ctx, user_input)
if not allowed:
print(f"๐ซ BLOCKED โ {reason}")
return ""
result = run_agent(user_input)
print(f"โ
ALLOWED โ {result}")
return result
The key additions are:
GovernancePolicyโ declares what's blocked and what limits apply.kernel.pre_execute(ctx, input)โ evaluates the input against that policy before your code runs. Returns(allowed: bool, reason: str).
Don't use LangChain? Swap LangChainKernel for OpenAIAgentsKernel, CrewAIKernel, or AutoGenKernel โ the pre_execute API is identical across all integrations. See Tutorial 03 โ Framework Integrations.
Step 3: Configure Policy with YAML¶
Inline Python policy is fine for quick tests, but for real projects you want policy in a file you can review, version-control, and update without touching code.
Create policies/my-agent.yaml:
# policies/my-agent.yaml
version: "1.0"
name: my-agent-policy
description: >
Governance policy for my existing agent.
Blocks destructive commands and PII leakage.
rules:
- name: block-destructive-sql
condition:
field: input
operator: contains_any
value: ["DROP TABLE", "TRUNCATE", "DELETE FROM"]
action: block
priority: 100
message: "Destructive SQL is not permitted."
- name: block-shell-injection
condition:
field: input
operator: regex
value: '(rm\s+-rf|os\.system|subprocess\.call)'
action: block
priority: 90
message: "Shell injection patterns are blocked."
- name: flag-pii
condition:
field: input
operator: regex
value: '\b\d{3}-\d{2}-\d{4}\b' # SSN pattern
action: audit # log it, but don't block
priority: 50
message: "Possible SSN detected โ logged for review."
defaults:
action: allow
max_tool_calls: 10
Then load it with the policy evaluator instead of the inline GovernancePolicy:
from agent_os.policies import PolicyEvaluator
evaluator = PolicyEvaluator()
evaluator.load_policies("./policies/") # loads all .yaml files in the dir
def governed_run(user_input: str) -> str:
decision = evaluator.evaluate({"input": user_input})
if not decision.allowed:
print(f"๐ซ BLOCKED [{decision.action}] โ {decision.reason}")
return ""
result = run_agent(user_input)
print(f"โ
ALLOWED โ {result}")
return result
Now your entire policy lives in YAML: easy to audit, diff in pull requests, and hand off to a security team.
Verify It Works¶
Run the standalone companion script included with this tutorial:
Expected output:
============================================================
Retrofit Governance โ Verification Demo
============================================================
[1] Dangerous SQL input โฆ
๐ซ BLOCKED โ policy=my-agent-policy reason=Blocked pattern matched: 'DROP TABLE'
[2] Shell injection attempt โฆ
๐ซ BLOCKED โ policy=my-agent-policy reason=Blocked pattern matched: 'rm -rf'
[3] Safe input โฆ
โ
ALLOWED โ Agent result for: Summarise last week's sales report
โโ Audit Trail โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
[1] 2025-... input='DROP TABLE users;' status=BLOCKED
[2] 2025-... input='rm -rf /data' status=BLOCKED
[3] 2025-... input='Summarise last weekโฆ' status=ALLOWED
๐ Governance is working. 3 decisions logged.
If you see this output, your agent is now governed. Every decision โ allow or block โ is written to the audit trail automatically.
What Changed? (Before vs. After)¶
| Before | After | |
|---|---|---|
| Lines of new code | โ | ~10 |
| Original agent logic | unchanged | unchanged |
| Policy location | none | policies/my-agent.yaml |
| Blocked patterns | none | DROP TABLE, rm -rf, shell injection |
| Audit trail | none | every decision logged with timestamp |
| Deployment change | โ | none โ pure Python, no infra required |
Next Steps¶
- Tutorial 01 โ Policy Engine: Full YAML syntax, operators, conflict resolution.
- Tutorial 02 โ Trust & Identity: Add cryptographic agent identity and trust scoring.
- Tutorial 04 โ Audit & Compliance: Persist your audit trail and generate OWASP ASI compliance reports.
- Example policies: Drop-in YAML files for SQL safety, PII detection, MCP security, and more.