AutoGen + ExecLayer Governance Guide
Add execution authority to Microsoft AutoGen conversational agents. Gate code execution, prevent unauthorized tool use, and control GroupChat dynamics with ExecLayer policies.
The AutoGen Governance Problem
AutoGen is Microsoft's framework for building agentic applications through conversational patterns. Agents communicate with each other and with a human user through messages. Code execution and tool use happen as a result of conversation. The agent network can be simple (two agents) or complex (GroupChat with many agents all communicating).
AutoGen's strength is its flexibility: agents can suggest code to each other, negotiate approaches, and adapt based on feedback. But this flexibility creates a governance blind spot. If agent A suggests that agent B execute dangerous code, and agent B trustingly executes it, the system has a problem. There is no mechanism to verify that the code is safe before execution, and no way to enforce that specific agents are not allowed to execute specific kinds of code.
The problem is not AutoGen's design, which is sound. The problem is that AutoGen assumes the agents and the human are trustworthy. In a system where agents are semi-autonomous (calling LLMs), the assumption breaks down. An LLM can be persuaded to suggest inappropriate code. Agents need to check authorization before executing suggestions from other agents.
ExecLayer adds this check. Before any code is executed or tool is used, ExecLayer gates it with policy.
The Unique Risk: Conversational Persuasion
AutoGen's conversational model introduces a unique risk that tool-calling systems like LangChain do not have. In LangChain, an agent decides to use a tool based on its reasoning about the current state. The decision is localized to the agent's reasoning loop. In AutoGen, agents communicate with each other, and this communication can override individual agent authorization.
Imagine this scenario: agent A is a data analyst with read-only access. Agent B is a data engineer with write access. Agent A and agent B are in a GroupChat. Agent A sends a message to agent B saying "I need you to delete all failed transactions from the database to clean up my analysis." Agent B reasons that agent A is a colleague and the request makes sense, so agent B writes code and executes it. The deletion succeeds. But this action violates the organization's policy: only senior engineers should delete data, not data analysts delegating to junior engineers.
AutoGen has no way to prevent this. Agent B was authorized to delete data, and agent B decided to do it. The fact that agent A convinced agent B does not matter to the system. ExecLayer changes this by enforcing policy at the execution boundary, regardless of conversational dynamics.
Conceptual Architecture for AutoGen Integration
The gate sits between the code suggestion and execution. Code can be suggested by any agent, but it is only executed if the executing agent is authorized and the code is within approved scope.
How It Works: Three Key Integration Points
1. Intercepting AssistantAgent Actions
AutoGen's AssistantAgent class is responsible for code generation. It calls the LLM and asks for code to solve the problem. ExecLayer hooks into the code execution callback that fires when code is about to run:
class ExecLayerCodeCallback(BaseCallbackHandler):
def on_code_execution(self, code, executor_agent, **kwargs):
# Extract details
agent_name = executor_agent.name
code_content = code
# Create execution request
request = CodeExecutionRequest(
code=code_content,
agent_name=agent_name,
environment="autogen_sandbox"
)
# Gate the execution
result = self.execLayer.evaluate(request)
if not result.approved:
return {
"status": "denied",
"error": result.reason
}
# Execution approved, return control to AutoGen
return {"status": "approved"}
The callback fires before the code is sent to the Python sandbox. ExecLayer evaluates it synchronously and either allows execution or returns a denial error that the agent sees as an execution failure.
2. Gating UserProxyAgent Code Execution
In many AutoGen workflows, a UserProxyAgent acts as the human in the conversation. It has special privileges: it can execute code without asking permission. But in an autonomous system, the UserProxyAgent might be automated, and its code execution should still be governed.
ExecLayer applies the same gating to UserProxyAgent as to AssistantAgent. The agent name is "user_proxy", but the policy check is the same:
// Policy for UserProxyAgent
agent "user_proxy" {
can "code_execution" with constraint {
max_execution_time: 10_seconds
disallowed_imports: ["os", "subprocess", "socket"]
allowed_file_operations: "read_only"
}
}
The UserProxyAgent can execute code, but only if it meets these constraints. If the code tries to import "os" or run subprocess commands, ExecLayer denies it. If the code runs for more than 10 seconds, it is terminated.
3. Policy Enforcement for GroupChat Scenarios
GroupChat is AutoGen's mechanism for managing conversations among multiple agents. In a GroupChat, many agents can speak and suggest code. ExecLayer must evaluate code based on which agent is executing it, not which agent suggested it.
Example: agent_research suggests code. agent_exec executes it. ExecLayer checks agent_exec's policy, not agent_research's policy. agent_research might be authorized to run analysis code but not database code. agent_exec might be authorized for database code. The gate ensures that each agent respects its own policy boundaries.
class ExecLayerGroupChatIntegration:
def on_group_chat_code_execution(
self,
code,
executor_agent,
suggester_agent,
group_name,
**kwargs
):
# Verify executor's policy
executor_policy = self.get_policy_for_agent(executor_agent)
request = CodeExecutionRequest(
code=code,
executor_agent=executor_agent,
suggester_agent=suggester_agent,
group=group_name
)
# Check: Can executor run this code?
result = self.execLayer.evaluate(
request,
policy=executor_policy
)
if not result.approved:
# Record denial with both agents
self.execLayer.record_denial(
executor=executor_agent,
suggester=suggester_agent,
code=code,
reason=result.reason
)
return {"status": "denied", "error": result.reason}
# Execution approved
return {"status": "approved"}
Code Analysis and Canonicalization
Arbitrary Python code is complex. To enforce policies, ExecLayer must understand what the code does at a semantic level. This requires code analysis.
ExecLayer performs static and dynamic analysis of code before execution:
Static Analysis
Parse the code abstract syntax tree (AST) and extract imports, function calls, and file operations:
import ast
def analyze_code(code_string):
tree = ast.parse(code_string)
analysis = {
"imports": [],
"function_calls": [],
"file_operations": [],
"network_calls": []
}
for node in ast.walk(tree):
if isinstance(node, ast.Import):
analysis["imports"].extend([alias.name for alias in node.names])
elif isinstance(node, ast.Call):
if isinstance(node.func, ast.Attribute):
analysis["function_calls"].append(node.func.attr)
elif isinstance(node, ast.Call) and hasattr(node.func, 'id'):
analysis["function_calls"].append(node.func.id)
return analysis
This analysis tells ExecLayer: "This code imports os and subprocess, calls open() three times, and makes HTTP requests." ExecLayer can then check these against policy.
Canonicalization to SovereignIR
The analysis is converted to SovereignIR, our canonical intent representation:
{
"canonical_action": "code_execution",
"code_signature": "0xabc123...",
"operations": [
{
"type": "module_import",
"module": "os"
},
{
"type": "module_import",
"module": "subprocess"
},
{
"type": "file_operation",
"operation": "read",
"paths": ["data.csv", "config.txt"]
},
{
"type": "network_call",
"destination": "api.example.com"
}
]
}
Policies are then written in terms of these canonical operations, making them independent of Python syntax.
Policy Rules for Code Execution
ExecLayer policies for AutoGen code execution look like this:
agent "agent_analysis" {
can "code_execution" with constraints {
allowed_imports: ["pandas", "numpy", "matplotlib"]
disallowed_imports: ["os", "subprocess", "sys"]
allowed_file_operations: ["read"]
allowed_file_paths: ["/data/analysis/*"]
max_execution_time: 30_seconds
max_memory: 1_gigabyte
}
}
agent "agent_admin" {
can "code_execution" with constraints {
allowed_imports: ["*"]
disallowed_imports: []
allowed_file_operations: ["read", "write", "delete"]
allowed_file_paths: ["/"]
max_execution_time: unlimited
max_memory: unlimited
}
}
agent "agent_sandbox" {
can "code_execution" with constraints {
allowed_imports: ["math"]
disallowed_imports: ["*"]
allowed_file_operations: []
max_execution_time: 5_seconds
max_memory: 100_megabytes
}
}
When agent_analysis tries to execute code that imports "os", ExecLayer denies it. When agent_admin tries the same code, it is approved. When agent_sandbox tries to execute any code that runs longer than 5 seconds, it is terminated.
Handling Conversational Context
In AutoGen conversations, agents communicate context through messages. A message might include "Here is code to solve this problem" and another agent might respond "I'll execute that". ExecLayer preserves the conversational context in the Authority Receipt so that auditing can reconstruct the discussion:
{
"receipt_id": "auth_recv_7m8n9o",
"code_hash": "0xdef456...",
"executor_agent": "agent_exec",
"suggester_agent": "agent_research",
"conversation_context": {
"group_chat": "data_analysis_team",
"message_from_suggester": "This code will process the sales data",
"message_from_executor": "Executing the suggested code",
"turn_number": 5
},
"policy_evaluation": {
"approved": true,
"executor_policy": "agent_exec_policy_v2",
"constraints": {
"allowed_imports": ["pandas", "numpy"],
"disallowed_imports": ["os", "subprocess"],
"allowed_file_operations": ["read"]
},
"analysis": {
"imports": ["pandas", "numpy", "matplotlib"],
"file_operations": ["read"],
"network_calls": []
}
},
"timestamp": "2026-04-03T14:42:15Z",
"merkle_index": 6521
}
When auditing, you can see that agent_research suggested the code, agent_exec executed it, the conversation context shows what was discussed, and the policy evaluation shows that the code was approved because it matched the constraints.
Preventing Code-Based Privilege Escalation
The most common privilege escalation in AutoGen is code-based. Agent A suggests code that agent B executes, and through the code, agent A gains access to resources it should not have. Examples:
- Agent A suggests "import os; os.system('rm -rf /data')" and agent B executes it.
- Agent A suggests code that reads environment variables containing API keys, and agent B unknowingly leaks them.
- Agent A suggests code that connects to the database as admin, and agent B runs it with its own user context.
ExecLayer prevents these with static analysis and runtime constraints. The code is analyzed before execution. If it tries to import "os" or "subprocess", and the executing agent's policy disallows it, the code is rejected. If it tries to execute arbitrary shell commands, ExecLayer detects this and denies it.
Runtime constraints add another layer. Even if the code is allowed to run, ExecLayer limits execution time, memory, and file access. A code execution that tries to consume all memory is terminated. A subprocess call that runs too long is killed.
This Is Conceptual, Not Shipped
Like LangChain and CrewAI, the AutoGen integration is our detailed design for future implementation. We are building the code analysis engine, the policy evaluation logic, and the AutoGen adapter. We expect to release this in Q2 2026.
We are sharing this design because AutoGen is powerful and increasingly used in production. Organizations deploying AutoGen today need governance to ensure that conversational agents do not execute unauthorized code. ExecLayer provides that governance without requiring changes to AutoGen's architecture.
Key Takeaways
The AutoGen integration illustrates these principles:
- Conversational persuasion is a valid attack vector in agentic systems.
- Code execution gating must understand what code does, not just who suggested it.
- Policy must be applied to the executor, not the suggester.
- Static code analysis can identify risky operations before execution.
- Runtime constraints (time, memory, file access) provide defense-in-depth.
- Authority Receipts must include conversational context for full accountability.
For a deeper understanding of how ExecLayer works, see our guide on Authority Receipts and LangChain integration guide.
Ready to secure your AutoGen conversations?
Request Early Access