Deterministic, Zero-Trust Policy Enforcement Points (PEPs) for LangChain Agents
Shift your enterprise AI from fragile, prompt-dependent guardrails to deterministic, code-level governance.
This documentation portal provides architectural blueprints, step-by-step rollout guides, and module specifications for securing enterprise LLM applications.
| Documentation Resource | Description | Destination |
|---|---|---|
| 🚀 Quickstart Demo (“Seeing is Believing”) | Hands-on walkthrough to clone the demonstrator, run unhardened (main) vs hardened (secured) test suites, and explore the complete 46-test catalog. |
Open Quickstart Walkthrough |
| 📘 Enterprise Implementation Guide | 12-chapter comprehensive walkthrough using a real-world enterprise incident assistant to demonstrate hardening from scratch. | Open Implementation Guide |
| ⚙️ Unified Configuration Reference | Complete index of all configuration properties, environment variable overrides, defaults, and operational behaviors. | Browse Configuration Reference |
| 📚 API Reference | Complete module specifications for security_core, security_adapter_langchain, and security_pdp_opa. |
Browse API Reference |
| 🧪 Companion Reference Application | Working FastAPI + LangChain demonstrator application illustrating baseline vulnerabilities (main) vs hardened controls (secured). |
View on GitHub |
| 💻 Source Code Repository | Core library repository, Installation instructions, issue tracker, and contribution guidelines. | GitHub Repository |
Protect tool calls with Common Expression Language (CEL) argument constraints, caller role checks, and numeric clearance levels. Identity context propagates deterministically in-band via LangChain’s native RunnableConfig without prompt overhead:
from langchain_security_extension.security_adapter_langchain import secured_tool
from langchain_security_extension.security_core import IdentityBridge, SecurityIdentity, ToolExecutionDeniedError
# 1. Protect any tool with deterministic CEL argument constraints
@secured_tool(
required_roles=["DEVOPS"],
min_clearance=1,
cel_expression="args.server.startsWith('prod-') ? subject.dept == 'INFRA' : true",
is_mutative=True
)
def example_tool_op_reboot_server(server: str) -> str:
return f"Rebooted {server}"
# Helper: attach identity to LangChain RunnableConfig
def caller(dept: str):
return IdentityBridge.create_runnable_config(
SecurityIdentity.create("alice", "CORP", {"DEVOPS"}, 1, dept)
)
# 2. Authorized caller (DEVOPS + INFRA) -> PERMIT
print(example_tool_op_reboot_server("prod-db-01", config=caller("INFRA")))
# Output: "Rebooted prod-db-01"
# 3. Unauthorized caller (DEVOPS + MARKETING) -> Hard-aborted with 0 LLM tokens!
# example_tool_op_reboot_server("prod-db-01", config=caller("MARKETING"))
# Raises: ToolExecutionDeniedError (PARAMETER_CONSTRAINT_FAILED)
| Vulnerability Vector | Prompt-Based Guardrails (e.g. Llama Guard, NeMo) | langchain-security-extension (Code-Level PEPs) |
|---|---|---|
| Determinism | ❌ Stochastic (bypassed via jailbreaks & indirect prompt injection) | ✅ 100% Deterministic (enforced in Python bytecode before tool invocation) |
| Token Cost | ❌ Adds 200–1,500 tokens per turn + recursive retry token burn | ✅ 0 LLM Tokens (front-door denial + invocation retry budgets) |
| Context Forgery | ❌ Security parameters exposed in tool JSON schemas can be hallucinated | ✅ Schema Hiding strips security attributes before model binding |
| Argument Validation | ❌ Cannot reliably validate dynamic args (e.g. CIDR blocks, hostnames) | ✅ CEL Expressions evaluate tool arguments against live subject attributes |
| Data Retrieval (RAG) | ❌ Post-retrieval filtering causes cross-tenant leaks or result starvation | ✅ Native DB Pre-Filters + signed sec:* chunk envelopes & oversampling |
| Data Privacy (DLP) | ❌ Scattered manual regex hooks prone to developer oversight | ✅ Single-Point DLP masks PII, secrets, and payment cards in-flight |
| Compliance & SIEM | ❌ Synchronous or unstructured logs that stall agents or fail audits | ✅ Async Ring Buffer streaming OCSF, ECS, and RFC 5424 audit events |
The framework implements a distributed Zero-Trust Policy Enforcement Architecture aligned with NIST SP 800-207. The core policy decision engine is strictly separated from the LangChain orchestration layer, ensuring security evaluation executes independently of model prompts.
flowchart TB
subgraph HostApp["Host Application Layer (Any LangChain App)"]
Agent["LangChain Agent / LCEL Chain"]
Tool["Python Tool Callables"]
Retriever["Vector Store / Retriever"]
end
subgraph Adapters["security_adapter_langchain (PEP Integration Layer)"]
SR["SecureRunnable\n(Agent/Chain PEP)"]
ST["@secured_tool\n(Tool Interceptor PEP)"]
SRET["SecureRetriever\n(RAG Context Pre-Filter PEP)"]
IB["IdentityBridge\n(RunnableConfig Context Injector)"]
end
subgraph Core["security_core (Zero-Dependency Engine)"]
PDP["Policy Decision Engine (PDP)\n- Two-Tier Decision Cache (L1 Thread-Local / L2 TTL)\n- RoleGraph & Clearance Hierarchy"]
CEL["CEL Evaluator\n- Runtime Argument Validation\n- Attribute-Based Access Control (ABAC)"]
Audit["Audit Pipeline & PII Sanitizer\n- OCSF / ECS / RFC 5424 Emitter\n- In-Flight DLP & Parameter Redaction"]
end
subgraph External["Pluggable Backends & SPIs"]
OPA["Remote PDP (OPA / Cedar)"]
SIEM["SIEM (Splunk / Elastic / Datadog)"]
VDB["Vector DBs (Chroma / Pinecone / pgvector)"]
end
Agent <--> SR
Tool <--> ST
Retriever <--> SRET
IB -.->|"Injects SecurityIdentity"| Agent
SR & ST & SRET -->|"PolicyRequest"| PDP
ST -->|"Evaluate args"| CEL
SR & ST & SRET -->|"AuditEvent"| Audit
PDP -.->|"Optional SPI"| OPA
Audit -.->|"AuditPublisherSPI"| SIEM
SRET -.->|"Metadata Pre-filters"| VDB
| Zero-Trust Role | Library Component | Implementation Responsibilities |
|---|---|---|
| PEP (Policy Enforcement Point) |
@secured_toolSecureRunnableSecureRetriever |
• Intercepts execution requests before tool/chain execution. • Enforces caller role and clearance floors. • Applies vector DB metadata pre-filters and prunes documents. • Emits immutable structured audit events to SIEM. |
| PDP (Policy Decision Point) |
EmbeddedPolicyEngineRemotePDPAdapter |
• Evaluates authorization requests deterministically. • Manages two-tier decision caching (L1 thread-local, L2 LRU TTL). • Resolves hierarchical role graphs and multi-tenant isolation. • Evaluates fail-closed / fail-open circuit breakers on remote PDP outages. |
| PIP (Policy Information Point) |
IdentityBridgeEntityAttributeResolverSPI |
• Converts inbound JWT/OAuth claims into immutable SecurityIdentity.• Injects identity into LangChain’s native RunnableConfig.• Resolves dynamic entity attributes (e.g. server owner, user dept) for CEL rules. |
| PAP (Policy Administration Point) |
Declarative Decorators & CEL Expressions | • Declarative @secured_tool parameters (required_roles, min_clearance).• Common Expression Language rules evaluated over live arguments. • Metadata classification schemas ( sec.clearance, sec.department). |
sequenceDiagram
autonumber
actor Caller as Caller / Application
participant Bridge as IdentityBridge
participant Runnable as SecureRunnable (Agent PEP)
participant ToolPEP as @secured_tool (Tool PEP)
participant PDP as EmbeddedPolicyEngine (PDP)
participant CEL as CELEvaluator
participant SIEM as AuditPublisherSPI
participant Tool as Target Tool Function
Caller->>Bridge: create_runnable_config(identity)
Bridge-->>Caller: config: RunnableConfig
Caller->>Runnable: invoke(input, config)
Runnable->>PDP: evaluate(subject, action="AGENT_INVOKE")
PDP-->>Runnable: PERMIT
Runnable->>ToolPEP: invoke_tool(args, config)
rect rgb(240, 248, 255)
Note over ToolPEP,CEL: Pre-Execution Code PEP (0 LLM Tokens)
ToolPEP->>CEL: evaluate_expression(cel_rule, args, subject)
CEL-->>ToolPEP: Condition Satisfied
ToolPEP->>PDP: evaluate(subject, action="TOOL_EXECUTE", resource)
PDP-->>ToolPEP: PERMIT (cached / local)
ToolPEP->>SIEM: publish(AuditEvent: PERMIT)
end
ToolPEP->>Tool: execute(*args, **kwargs)
Tool-->>ToolPEP: raw_result
ToolPEP-->>Runnable: sanitized_result
Runnable-->>Caller: execution_output
The Enterprise Implementation Guide covers end-to-end integration across a hands-on quickstart, 12 focused architectural chapters, and a unified configuration reference: