Python Agents¶
Integrate Rampart with any Python agent framework — LangChain, CrewAI, AutoGen, or custom code.
Python SDK (source-distributed alpha)¶
SDK 0.2.0 has its own component version, independent of the Rampart CLI. Its outage default intentionally differs from SDK 0.1.0; see the migration below.
Start the Rampart proxy:
In a second terminal, configure the SDK for that local service. The service saves its administrative token in ~/.rampart/token; the SDK reads RAMPART_TOKEN rather than automatically opening that file:
This loads the token without displaying it. Use these settings only for local development. For a deployed agent, provision an evaluation-scoped token and supply it through the agent's secret configuration. Remote endpoints require HTTPS and an explicitly configured token; keep token values out of code and logs.
The SDK is not currently published on PyPI. From a Rampart source checkout, install it and put its fail-closed enforcement call directly at the execution boundary:
import subprocess
import rampart
@rampart.exec_guard()
def safe_exec(command: str) -> str:
return subprocess.check_output(command, shell=True, text=True)
The decorator sends an enforce: true preflight at the actual call boundary, consumes one-shot grants and call-count state exactly once, and does not execute the function unless Rampart returns a consistent allow decision. Its default client fails closed when the policy service is unavailable or malformed.
RampartClient() also fails closed by default, so supplying a custom client to change its URL or timeout preserves this protection. Transport failures and timeouts raise RampartConnectionError; HTTP server errors raise RampartServerError. Guards do not execute when these errors occur, including when raise_on_deny=False.
Upgrading earlier SDK source checkouts: calls that omitted fail_open previously returned a synthetic allow during transport/server failures. They now raise, including preflight, check_*, and their async equivalents. Handle availability exceptions without executing the guarded operation. If the application deliberately needs the previous availability fallback, use RampartClient(fail_open=True) explicitly. This does not override policy deny/ask or invalid decision responses. Explicit true/false settings and healthy decisions retain their behavior; health() and ahealth() still return False when unavailable.
Preflight API¶
Check if a command would be allowed without executing it:
import rampart
def preflight(command: str) -> bool:
"""Check if a command is allowed without executing."""
with rampart.RampartClient(fail_open=False) as client:
return client.check_exec(command, agent="my-agent", session="s1").allowed
Preflight is a preview only. Never separate a preflight from later execution; use enforce, aenforce, or a guard decorator at the execution boundary.
LD_PRELOAD Alternative¶
For simpler integration, wrap your entire Python process:
This optional path requires a source-built native library; current release and Homebrew packages contain only the Rampart CLI. Run make -C preload install from a matching Rampart source checkout first.
This can intercept supported exec-family calls that reach the dynamic loader, including common os.system() and subprocess paths. It does not cover static binaries, direct syscalls, in-process Python file or network I/O, or every possible subprocess implementation.
LangChain Example¶
import subprocess
import rampart
from langchain.tools import tool
@tool
@rampart.exec_guard()
def run_command(command: str) -> str:
"""Execute a shell command only after Rampart authorizes this invocation."""
result = subprocess.run(command, shell=True, capture_output=True, text=True)
return result.stdout
API Reference¶
| Method | Endpoint | Purpose |
|---|---|---|
POST | /v1/tool/{toolName} | Evaluate a host-owned tool call |
POST | /v1/preflight/{toolName} | Dry-run check |
GET | /v1/approvals | Pending approvals |
POST | /v1/approvals/{id}/resolve | Approve/deny |
GET | /healthz | Health check |