RIL Warden · Docs · Guide

Drop Warden into your agent

Route an agent's web requests through Warden so it can reach only approved sites, never sees the API keys it uses, and leaves a signed, tamper-evident trail. Pick the tier that fits, copy, run.

Jump to
Proxy (no code change) Drop-in HTTP client One jailed LLM tool LangChain LlamaIndex CrewAI OpenAI Agents SDK Claude Agent SDK MCP Node

Get the client once (zero dependencies, Python 3.8+):

curl -O https://warden.ripitlabs.com/sdk/warden.py     # Python
curl -O https://warden.ripitlabs.com/sdk/warden.mjs    # Node

You need an agent token (wdn_...) from your console, and set it once: export WARDEN_TOKEN=wdn_.... Create agents, approve sites, and watch traffic in the console.

Proxy mode – no code change

zero edits to your agent

Point the standard proxy environment variables at Warden and every outbound HTTP call your agent already makes is gated, with no change to its code.

export HTTPS_PROXY=$(python3 -c "from warden import Warden;print(Warden().proxy_url('<proxy-host-from-your-console>'))")
export HTTP_PROXY=$HTTPS_PROXY
python your_agent.py     # unchanged
Proxy mode needs a reachable proxy host. It ships in the self-hosted bundle; on the hosted service it is turned on per workspace. If you do not see a proxy host in your console yet, use the drop-in client below, which needs no proxy.

Drop-in HTTP client

same shape as requests

Anywhere your code calls requests or httpx, swap the call. Same verbs, same response object. The key never touches your process: you name it, Warden attaches it toward the approved host.

from warden import Warden
w = Warden()                                  # reads WARDEN_TOKEN

r = w.get("https://api.github.com/user", secrets=["github"])
print(r.status, r.json())

r = w.post("https://api.stripe.com/v1/charges",
           data={"amount": 500, "currency": "usd"}, secrets=["stripe"])

An unapproved host raises WardenBlocked; a stored secret is injected toward its bound host only and redacted if the response echoes it back.

One jailed LLM tool

works with any model that calls tools

Give the model a single web tool. Every call it makes runs through Warden, and a block comes back as plain text the model can read, so it learns the boundary instead of crashing.

from warden import Warden
import anthropic

w = Warden()
client = anthropic.Anthropic()

msg = client.messages.create(
    model="claude-sonnet-4-5", max_tokens=1024,
    tools=[w.tool_spec()],                      # one web tool, jailed
    messages=[{"role": "user", "content": "Get the latest release tag from the httpx GitHub repo."}],
)
for block in msg.content:
    if block.type == "tool_use":
        result = w.run_tool(block.input)        # executes through Warden, returns text
        # feed `result` back as the tool_result in your next turn

For OpenAI-style function calling, use w.tool_spec(fmt="openai").

LangChain

from warden import Warden
from langchain_core.tools import tool

w = Warden()

@tool
def web_request(url: str, method: str = "GET", secrets: list[str] | None = None) -> str:
    """Fetch an approved URL through Warden. Unapproved hosts are blocked."""
    return w.run_tool({"url": url, "method": method, "secrets": secrets or []})

# add `web_request` to your agent's tools as usual

LlamaIndex

from warden import Warden
from llama_index.core.tools import FunctionTool

w = Warden()

def web_request(url: str, method: str = "GET") -> str:
    """Fetch an approved URL through Warden."""
    return w.run_tool({"url": url, "method": method})

warden_tool = FunctionTool.from_defaults(fn=web_request)
# pass [warden_tool] to your agent

CrewAI

from warden import Warden
from crewai.tools import tool

w = Warden()

@tool("web_request")
def web_request(url: str, method: str = "GET") -> str:
    """Fetch an approved URL through Warden. Blocked for unapproved hosts."""
    return w.run_tool({"url": url, "method": method})

# give `web_request` to the agent that needs the web

OpenAI Agents SDK

from warden import Warden
from agents import function_tool

w = Warden()

@function_tool
def web_request(url: str, method: str = "GET") -> str:
    """Fetch an approved URL through Warden."""
    return w.run_tool({"url": url, "method": method})

# add web_request to your Agent(tools=[...])

Claude Agent SDK

Run the Warden MCP server and the agent gets one web tool that is jailed by Warden, no custom code:

claude mcp add warden -e WARDEN_TOKEN=wdn_... -- python3 /path/to/warden.py mcp

Or expose it as a plain function tool with w.tool_spec() / w.run_tool() exactly as in One jailed LLM tool.

MCP (Claude Code, Claude Desktop, Cursor, any client)

{"mcpServers": {
  "warden": {
    "command": "python3",
    "args": ["/path/to/warden.py", "mcp"],
    "env": {"WARDEN_TOKEN": "wdn_..."}
  }
}}

The server exposes a web-request tool and a status tool; every fetch the model makes goes through Warden. More at the MCP docs.

Node

import { Warden } from "./warden.mjs";
const w = new Warden();                         // reads WARDEN_TOKEN

const r = await w.get("https://api.github.com/user", { secrets: ["github"] });
console.log(r.status, await r.json());

Roll out safely

Start each agent in monitor mode so nothing is blocked while you watch what it reaches. After a while, let Warden suggest the sites it actually used, approve the safe ones, and flip it to enforce. The console and the guide walk through it.

Full API reference and options are in the docs.