Proxy vs SDK: Two Architectures for AI Agent Enforcement
Jay Cabello
Founder, Intercis · Security engineer
Every organization deploying AI agents in production eventually reaches the same decision point: How do we enforce policy on what agents do?
There are two fundamentally different architectural approaches:
- SDK/In-Process: Embed enforcement rules inside the agent's code
- Proxy/Out-of-Process: Intercept agent requests from outside the process
Each approach has distinct tradeoffs. This guide covers both, explains when to choose each, and explains why we built Intercis as a proxy.
What Is SDK-Based Enforcement?
Definition: A developer imports a library into their agent code. That library validates actions before they execute.
How it looks in code:
from guardrails import Guard
from langchain_agents import AgentExecutor
# Developer defines validation rules
guard = Guard.from_string("""
blocks:
- name: "block_credential_access"
on_fail: "exception"
validators:
- type: "is_not_secret"
- name: "block_delete_operations"
validators:
- type: "json_schema"
schema: {
"not": {"properties": {"action": {"const": "delete_file"}}}
}
""")
# Developer imports the guard into their agent
agent = AgentExecutor.from_agent_and_tools(
agent=agent,
tools=tools,
guard=guard,
verbose=True
)
response = agent.invoke({"input": "delete old logs"})
Examples of SDK-based solutions:
- Guardrails AI
- NeMo Guardrails (NVIDIA)
- LangChain callbacks and tools validation
- Custom decorators and middleware
Typical feature set:
- Output validation (check LLM responses for credentials, banned topics, etc.)
- Tool use validation (check which tools are called and with what parameters)
- Custom validators (regex, JSON schema, semantic checks)
- Per-agent customization
What Is Proxy-Based Enforcement?
Definition: A proxy sits between the agent and the systems it needs to reach (LLM API, databases, filesystems, cloud APIs). Every request is intercepted and evaluated.
How it looks architecturally:
┌──────────────────┐
│ Agent Code │
│ (unmodified) │
└────────┬─────────┘
│
│ POST /v1/messages
│ Authorization: Bearer sk-ant-...
│ {"model": "claude-3...", "tools": [...]}
│
v
┌──────────────────────────────────┐
│ Intercis Enforcement Proxy │
│ ────────────────────────────────│
│ 1. Parse request │
│ 2. Validate against policy │
│ 3. Route or block │
│ 4. Audit trail │
└────────┬─────────────────────────┘
│
│ Request approved
│ Forward to LLM API
│
v
┌──────────────────┐
│ Claude API │
│ (Anthropic) │
└──────────────────┘
Agents point to the proxy instead of the API:
from anthropic import Anthropic
# Instead of: client = Anthropic()
# Agent now points to proxy:
client = Anthropic(api_key="sk-ant-...", base_url="https://api.intercis.io")
# Everything else is identical
response = client.messages.create(
model="claude-3-sonnet-20250219",
max_tokens=4096,
tools=tools,
messages=[{"role": "user", "content": "delete old logs"}]
)
Examples of proxy-based solutions:
- Intercis
- Custom API gateways (Kong, Nginx with custom rules)
- Network-level policy enforcement
Typical feature set:
- Real-time policy enforcement (allow/deny/escalate)
- Immutable audit logging
- Tool call interception
- Human-in-the-loop approval gates
- Multi-agent policy coordination
Side-by-Side Comparison
| Dimension | SDK/In-Process | Proxy/Out-of-Process |
|---|---|---|
| Code changes required | Yes—developers must import library | No—agents point to proxy endpoint |
| Policy update latency | Requires redeployment of agent code | Real-time, no redeployment |
| Tamper resistance | Medium—process compromise disables guards | High—external enforcement cannot be disabled by agent |
| Framework support | Per-framework (LangChain ≠ AutoGen) | All frameworks (Claude SDK, OpenAI, custom agents) |
| Deployment complexity | Low—just add an import statement | Medium—requires infrastructure (reverse proxy, ingress) |
| Multi-agent coordination | Difficult—each agent has own rules | Easy—centralized policy applies to all agents |
| Latency overhead | Minimal (function call) | Low-medium (network round-trip ~50-200ms) |
| Visibility to security teams | Limited—developers control rules | High—security team owns the boundary |
| Audit trail | Inside agent logs (can be modified) | External audit store (immutable) |
| Approval workflows | Optional, framework-dependent | First-class citizen (hold action pending human approval) |
| Intermediate reasoning validation | Yes (can validate reasoning steps) | No (only sees final tool calls) |
| Vendor lock-in | Low (open source options available) | Higher (proxy is proprietary) |
When to Use SDK-Based Enforcement
SDK is the right choice if:
- Single-framework environment: All your agents use LangChain, and you're willing to standardize on one framework.
- Development/testing only: You're building agent prototypes, not deploying to production, so code changes are acceptable.
- You control all agent code: You own the codebase and can require guardrails as a coding standard.
- Latency-sensitive systems: You cannot tolerate the network latency of a proxy (though 50-200ms is usually acceptable).
- Fine-grained reasoning validation: You need to validate intermediate steps, not just final actions.
Real-world SDK scenario:
A startup building an internal DevOps automation tool:
- All agents use LangChain
- Small team (5 engineers)
- Development and staging only (no production agents yet)
- They implement Guardrails AI with custom validators for "no credential access" and "no delete operations outside /tmp"
- This is appropriate because they control the code, understand the framework, and can standardize.
When to Use Proxy-Based Enforcement
Proxy is the right choice if:
- Production with real infrastructure access: Agents have filesystem, database, or cloud API access with real consequences.
- Multi-framework environment: Teams use different agent frameworks (some LangChain, some Claude SDK directly, some custom).
- Strict policy requirements: You need guaranteed enforcement—the agent process cannot bypass rules, even if compromised.
- Security team ownership: Security needs to enforce policy without relying on developers to implement guards.
- Real-time policy updates: You need to change policy instantly without redeploying agents.
- Multi-agent coordination: You have many agents that need consistent policy across teams.
- Audit compliance: You need immutable audit trails that agents cannot modify.
- Zero code changes: You cannot or will not modify agent code.
Real-world proxy scenario:
A financial services company with agent governance:
- Multiple teams deploying agents (data pipeline team uses custom Python agents, DevOps team uses Claude SDK, platform team uses LangChain)
- Agents have access to production cloud infrastructure and customer databases
- Security team needs to enforce consistent policy: "no agent deletes customer data, all irreversible operations require approval"
- They cannot require every team to use the same framework or library
- They need SOC2 compliance evidence (immutable audit trails)
- They deploy Intercis as a proxy: agents point to api.intercis.io instead of api.anthropic.com
- Policy is defined centrally by the security team
- Agents cannot bypass enforcement, even if code is compromised
- This is appropriate because they have production risk, heterogeneous frameworks, and strict compliance requirements.
Technical Deep-Dive: How Each Approach Handles a Real Scenario
Let's walk through a concrete scenario with both architectures.
Scenario: "Delete Old Deployment Artifacts"
An agent is tasked with deleting files from /var/log/deployments/ that are older than 90 days. However, the prompt is vague:
"Clean up old deployment artifacts to save disk space."
The agent interprets this broadly and tries to delete:
/var/log/deployments/old/— ✓ Legitimate/var/lib/— ✗ Should be blocked/opt/application/— ✗ Should be blocked
With SDK-Based Enforcement (Guardrails AI)
from guardrails import Guard
guard = Guard.from_string("""
blocks:
- name: "delete_path_validation"
validators:
- type: "custom_validator"
code: |
paths = extract_paths_from_tool_call(validated_output)
allowed_dirs = ["/var/log/deployments", "/tmp", "/var/cache"]
for path in paths:
if not any(allowed in path for allowed in allowed_dirs):
raise ValueError(f"Path {path} not in whitelist")
""")
# Developer adds the guard
agent = AgentExecutor.from_agent_and_tools(
agent=agent,
tools=tools,
guard=guard,
verbose=True
)
Execution flow:
1. Agent decides: "Delete /var/lib/"
2. Agent constructs: tool_call(delete_file, path="/var/lib/")
3. Guard intercepts: Validates path against whitelist
4. Guard blocks: ValueError("Path /var/lib/ not in whitelist")
5. Agent receives: ToolError("Path blocked by policy")
6. Logs written to: Agent's stdout/application logs
7. Timeline: Blocked in ~5ms
What happens if the agent process is compromised:
If an attacker gains code execution in the agent process, they can:
- Disable the guard:
guard = None - Replace the whitelist:
allowed_dirs = ["/"] - Wrap the delete in a try-except:
try: tool_call(...) except: bypass_guard()
The guard is a suggestion, not a guarantee. It's code running inside a potentially compromised process.
With Proxy-Based Enforcement (Intercis)
# Agent code: UNCHANGED
from anthropic import Anthropic
client = Anthropic(
api_key="sk-ant-...",
base_url="https://api.intercis.io" # Point to proxy
)
response = client.messages.create(
model="claude-3-sonnet-20250219",
max_tokens=4096,
tools=[{
"name": "delete_file",
"description": "...",
"input_schema": {...}
}],
messages=[{"role": "user", "content": "Clean up old deployment artifacts..."}]
)
Proxy-side policy (defined once, applies to all agents):
policies:
- name: "enforce_delete_scope"
rule: |
if (tool == "delete_file"):
path = request.params.path
allowed_prefixes = ["/var/log/deployments", "/tmp", "/var/cache"]
if (not any_prefix_matches(path, allowed_prefixes)):
action = DENY
reason = "Delete outside permitted scope"
Execution flow:
1. Agent decides: "Delete /var/lib/"
2. Agent constructs: POST /v1/messages {tools: [delete_file call]}
3. Request sent to: https://api.intercis.io/v1/messages
4. Proxy intercepts: Parses request
5. Proxy evaluates: Path /var/lib/ not in whitelist
6. Proxy action: DENY
7. Proxy response: {"error": "tool_call_blocked", "reason": "Delete outside permitted scope"}
8. Agent receives: API error; tool_call never executes
9. Logs written to: Immutable audit trail (external, agent cannot modify)
10. Timeline: Blocked in ~100-200ms (network latency)
What happens if the agent process is compromised:
If an attacker gains code execution in the agent process, they can:
- Try to bypass the proxy by calling the LLM API directly: Won't help—the policy is external
- Try to modify the API key to point elsewhere: But then they're not using Claude; the task fails
- Try to disable TLS: Proxy enforces HTTPS; plain HTTP is rejected
The proxy is a guarantee, not a suggestion. It's infrastructure, not code the agent controls.
Architectural Decision: Why Intercis Chose Proxy
We chose the proxy model for four reasons:
1. Production Risk Requires Tamper Resistance
If a policy is just code running inside the agent process, it's a suggestion. In production environments where agents have filesystem or database access, a suggestion is not enough.
The founding incident behind Intercis happened because no layer between intent and action could stop an underspecified agent. An in-process guard would have been better than nothing, but not good enough. A proxy that sits outside the process boundary is the only architecture that truly enforces.
2. Multi-Framework Reality
In practice, enterprises deploy agents using multiple frameworks:
- Some teams use Claude SDK directly
- Some use LangChain
- Some use AutoGen
- Some use custom agents
Requiring each team to use the same guardrails library, or requiring developers to implement guardrails at all, creates friction. The proxy works with all of them without code changes.
3. Security Teams Must Own the Boundary
In-process guards are owned by developers. If a team forgets to add guardrails, or adds them incorrectly, the security team has no enforcement layer.
A proxy puts security policy outside developer control. Security teams can enforce policy across all agents in their organization without asking developers for permission.
4. Audit Compliance Requires External Audit Logs
SOC2 and ISO27001 compliance require immutable audit trails. If audit logs are written by the same process that's trying to hide something, they're not truly immutable.
A proxy writes to an external, append-only audit store. The agent cannot modify these logs, which is why they're suitable as compliance evidence.
The Real Tradeoff: Latency vs. Guarantee
The honest tradeoff is this:
In-process (SDK): Faster, easier to deploy, but optional—developers can bypass it.
Out-of-process (Proxy): Slightly slower (network latency), requires infrastructure changes, but mandatory—cannot be bypassed.
For most production systems, the difference between "10ms" and "110ms" doesn't matter. But in systems where latency is critical (high-frequency trading, real-time control systems), the proxy overhead becomes relevant.
If you're in a domain where sub-100ms latency is non-negotiable, you might need to accept the trade-off and use in-process enforcement with very strong code review practices.
For everyone else—which is most organizations deploying agents in production—the proxy model offers stronger guarantees.
Choosing: A Simple Framework
Ask yourself these questions in order:
- Do I have production agents with infrastructure access?
Yes → Proxy is better. Go to question 3.
No → Both are acceptable. Go to question 2. - Do I control all the agent code?
Yes → SDK is fine. You can enforce guardrails as a code standard.
No → Proxy is better. Go to question 3. - Do I need to enforce policy without code changes?
Yes → Proxy is required.
No → SDK might be acceptable if you have strong code review and all frameworks are unified. - Do I need immutable audit trails for compliance?
Yes → Proxy is better (external audit store).
No → SDK might be acceptable. - Do I have multiple agent frameworks or teams?
Yes → Proxy is better (framework-agnostic).
No → SDK might be acceptable if everyone uses the same framework.
If you answer "yes" to any of questions 1, 3, 4, or 5, use a proxy.
If you answer "no" to all of them, SDK is probably fine.
Hybrid Approach: Using Both
Some organizations use both:
┌──────────────────┐
│ Agent Code │
│ (with SDK guards)
└────────┬─────────┘
│
│ (SDK guards first line of defense)
│
v
┌──────────────────────┐
│ Intercis Proxy │
│ (second line) │
└──────────────────────┘
│
v
┌──────────────────┐
│ Claude API │
└──────────────────┘
How this works:
- Developers add in-process guards for performance and development velocity
- Proxy enforces mandatory organization-wide policy
- If either layer blocks an action, the action is stopped
- If either layer is compromised, the other still enforces
Trade-off: Complexity increases, but you get defense-in-depth.
This is common in financial services and healthcare where risk tolerance is very low.
The Bottom Line
The choice between SDK and Proxy is not about which technology is "better." It's about which architecture matches your risk profile and operational maturity.
Use SDK if:
- You have tight code control
- You're in development/testing
- You cannot tolerate proxy latency
- All agents use the same framework
Use Proxy if:
- You have production risk
- You need enforcement without code changes
- You have multiple frameworks or teams
- You need immutable audit trails
- You need real-time policy updates
For enterprises running AI agents in production DevOps environments with real infrastructure access, the proxy model is the only architecture that truly guarantees enforcement.
What's Next
If you're evaluating architectures for agent governance and want to understand how a proxy would work in your environment, let's talk.
We're working with design partners to integrate governance into production DevOps workflows.
Ready to govern your agents?
Intercis is designed for teams running AI agents in production. We work with your existing agent code — zero changes required. Apply for our design partner program and we'll integrate in a single call.
Apply for the design partner program