Kanish TyagiA few weeks ago I was building a LangChain agent and realized I had no idea what it was actually...
A few weeks ago I was building a LangChain agent and realized I had no idea what it was actually doing. It could call any tool, write anything to memory, make unlimited API calls. It was essentially unsupervised.
Then I found Microsoft's agent-governance-toolkit. I added governance to my agent in about 30 minutes. Here's exactly how.
A LangChain agent that:
No rewrites. Just a governance wrapper around your existing agent.
pip install agent-governance-toolkit[full]
Verify it works:
agent-governance verify
You should see a green checkmark. You're ready.
Before governance, your agent looks like this:
from langchain.chat_models import ChatOpenAI
from langchain.agents import initialize_agent, AgentType
llm = ChatOpenAI(model="gpt-4")
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)
# No limits. No logging. No audit trail.
agent.run("Do whatever the user asks")
After governance:
from langchain.chat_models import ChatOpenAI
from langchain.agents import initialize_agent, AgentType
from agent_os.integrations.base import GovernancePolicy
from agent_os.integrations import LangChainKernel
llm = ChatOpenAI(model="gpt-4")
base_agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)
# Define what your agent is allowed to do
policy = GovernancePolicy(
name="my-first-policy",
blocked_patterns=["DROP TABLE", "rm -rf"],
max_tool_calls=10,
log_all_calls=True,
)
# Wrap your existing agent — no rewrite needed
kernel = LangChainKernel(policy=policy)
governed_agent = kernel.wrap(base_agent)
# Same interface, now governed
governed_agent.invoke({"input": "Help me analyze this dataset"})
That's it. Your agent now has a policy layer.
You probably don't want your agent to be able to delete files or execute arbitrary shell commands. Add an allowlist:
policy = GovernancePolicy(
name="restricted-policy",
# Only these tools are allowed
allowed_tools=["web_search", "read_file", "send_email"],
# These are always blocked regardless
blocked_patterns=[
"rm -rf", # destructive shell
"DROP TABLE", # SQL injection
r"\b\d{3}-\d{2}-\d{4}\b", # SSN pattern
r"password\s*[:=]", # credential leak
],
max_tool_calls=10,
)
Test it:
# This gets blocked before reaching the LLM
allowed, reason = kernel.pre_execute(ctx, "Execute: DROP TABLE users")
print(allowed) # False
print(reason) # "Blocked pattern 'DROP TABLE' detected"
# This passes through
allowed, reason = kernel.pre_execute(ctx, "Search for recent AI papers")
print(allowed) # True
The rejection happens at the code layer — the model never sees the blocked input.
Every action your agent takes is now logged automatically when log_all_calls=True. But you can also inspect the audit trail directly:
from datetime import datetime
audit_log = []
def on_action(event):
audit_log.append({
"timestamp": datetime.now().isoformat(),
"input": event.get("input"),
"allowed": event.get("allowed"),
"reason": event.get("reason"),
})
# Check what happened
for entry in audit_log:
status = "✅ ALLOWED" if entry["allowed"] else "🚫 BLOCKED"
print(f"{entry['timestamp']} — {status}: {entry['input'][:50]}")
In production, this goes to your observability stack. During development, it tells you exactly what your agent tried to do.
The toolkit includes a built-in compliance checker against the OWASP Agentic Top 10:
agent-governance verify --badge
This checks your configuration against known attack vectors:
You get a pass/fail report with specific recommendations.
Here's what changed in 30 minutes:
| Before | After | |
|---|---|---|
| Tool calls | Unlimited | Max 10 per session |
| Dangerous inputs | Passed to LLM | Blocked before LLM |
| PII handling | Unvalidated | Checked on every write |
| Audit trail | None | Every action logged |
| OWASP compliance | Unknown | Verified |
| Performance overhead | — | <0.1ms per action check |
The last point matters: governance doesn't slow your agent down in any meaningful way. The policy checks are in-process Python, not network calls.
I spent the past week contributing code to this toolkit — fixing bugs, adding docstrings, building Colab notebooks. Here's what surprised me:
The attack surface is bigger than you think. I saw how MCP tool poisoning works, how PII leaks into memory writes, how delegation chains can be exploited. None of these are theoretical. They're patterns security researchers are actively demonstrating.
Wrapping is better than rewriting. The governance layer wraps your existing agent. You don't throw away your prompts or your framework. You add a code layer underneath them. That's the right architecture.
Auditability is the real value. The blocked requests matter less than the audit trail. Knowing what your agent tried to do — even when it was allowed — is how you understand and improve agent behavior in production.
The full toolkit is open source:
pip install agent-governance-toolkit[full]
There are also interactive Colab notebooks (which I built!) that let you explore policy enforcement, MCP security scanning, and multi-agent governance without any local setup:
👉 github.com/microsoft/agent-governance-toolkit
The quickstart takes 10 minutes. The governance layer takes 5 more.
I'm Kanish Tyagi — MS Data Science student at UT Arlington, open source contributor to Microsoft's agent-governance-toolkit. Find me on GitHub and LinkedIn.