Rungate
Runtime validation middleware for AI agent tool-calls.
Rungate sits between your AI agents and their tools, validating every tool-call before execution. Policy enforcement, schema validation, rate limiting, cost tracking, kill switches, and full audit trails — in a single pip install with zero required dependencies.
Why Rungate?
AI agents fail 3–15% of tool-calls individually, and 41–87% in multi-agent workflows (arXiv:2311.05785, UC Berkeley MAST). A single unchecked execute_code or send_email call can leak data, burn budget, or take down production systems.
Existing guardrails validate LLM outputs (text/content). Rungate validates LLM actions (tool-calls) — the actual function invocations that interact with your systems.
┌──────────┐ ┌──────────────────────────────┐ ┌──────────┐
│ AI Agent │────▶│ RUNGATE │────▶│ Tools │
│ │ │ │ │ │
│ LangChain│ │ ┌─────────┐ ┌────────────┐ │ │ APIs │
│ CrewAI │ │ │ Policy │ │ Validation │ │ │ DBs │
│ OpenAI │ │ │ Engine │ │ (Schema) │ │ │ Files │
│ Custom │ │ ├─────────┤ ├────────────┤ │ │ Code │
│ │ │ │ Rate │ │ Cost │ │ │ Email │
│ │ │ │ Limiter │ │ Tracker │ │ │ │
│ │ │ ├─────────┤ ├────────────┤ │ │ │
│ │ │ │ Kill │ │ Audit │ │ │ │
│ │ │ │ Switch │ │ Logger │ │ │ │
│ │◀────│ └─────────┘ └────────────┘ │◀────│ │
└──────────┘ └──────────────────────────────┘ └──────────┘
Quick Start
pip install rungate-ai
from rungate import Rungate
# Define policies
gate = Rungate({
"policies": {
"default": {
"mode": "deny",
"tools": {
"web_search": "allow",
"read_file": "allow",
}
},
"researcher": {
"mode": "allow",
"tools": {"delete_file": "block", "execute_code": "block"},
"conditions": [{
"tool": "web_search",
"block_if": {"query_contains": ["password", "credential"]},
}],
}
},
"schemas": {
"web_search": {
"type": "object",
"required": ["query"],
"properties": {
"query": {"type": "string", "minLength": 1, "maxLength": 1000}
}
}
},
"rate_limits": {
"global": {"max_calls": 100, "window_seconds": 60}
},
"cost": {
"tool_costs": {"web_search": 0.01, "execute_code": 0.05},
"budgets": {"global": 50.0, "per_agent": {"researcher": 10.0}},
},
})
# Validate and execute a tool-call
result = gate.call(
agent="researcher",
tool="web_search",
args={"query": "AI safety research"},
callable=lambda **kw: search_api(kw["query"]),
)
if result.allowed:
print(result.result)
else:
print(f"Blocked: {result.error}")
Features
8 Core Modules
| Module | What it does |
|---|---|
| Interceptor | Central pipeline — wraps any callable, runs through all checks |
| Policy Engine | YAML-defined allow/block rules per agent, per tool, with conditions |
| Schema Validator | JSON Schema validation of tool-call arguments |
| Rate Limiter | Sliding-window limits: global, per-agent, per-tool, per-agent-tool |
| Cost Tracker | Per-call cost estimation, budget caps, auto-kill on overspend |
| Kill Switch | Emergency stop — kill all, specific agents, or specific tools |
| Audit Logger | Structured logs to SQLite, JSONL, stdout, or custom callbacks |
| Alert Engine | Real-time alerts via webhook, Slack, email on violations |
Zero Required Dependencies
The core library uses only Python stdlib. Optional dependencies unlock extra features:
pip install rungate-ai # Core (stdlib only)
pip install rungate-ai[yaml] # + YAML config support
pip install rungate-ai[schema] # + jsonschema validation
pip install rungate-ai[server] # + FastAPI SaaS server
pip install rungate-ai[all] # Everything
Three Operating Modes
# Enforce: block violations (production)
gate = Rungate({"mode": "enforce", ...})
# Monitor: log violations but don't block (rollout)
gate = Rungate({"mode": "monitor", ...})
# Dry-run: validate but don't execute (testing)
gate = Rungate({"mode": "dry-run", ...})
Framework Integrations
LangChain
from rungate.integrations.langchain import wrap_tools
gate = Rungate(config)
safe_tools = wrap_tools(tools, gate, agent="researcher")
executor = AgentExecutor(agent=agent, tools=safe_tools)
CrewAI
from rungate.integrations.crewai import gate_agent
gate = Rungate(config)
agent = Agent(role="Researcher", tools=[search, scrape])
safe_agent = gate_agent(agent, gate)
OpenAI Function Calling
from rungate.integrations.openai_fc import gate_tool_calls
response = client.chat.completions.create(model="gpt-4", messages=msgs, tools=tools)
results = gate_tool_calls(gate, "my_agent", response.choices[0].message.tool_calls, executor)
Generic Python
from rungate.integrations.generic import gated
@gated(gate, agent="my_agent")
def web_search(query: str) -> list:
return search_api(query)
results = web_search("AI safety") # Passes through Rungate
Kill Switch
Emergency stop for runaway agents:
# Kill everything
gate.kill()
# Kill specific agent
from rungate.core.kill_switch import KillMode
gate.kill(mode=KillMode.AGENT, targets=["rogue_agent"], reason="Budget exceeded")
# Kill specific tool
gate.kill(mode=KillMode.TOOL, targets=["execute_code"], reason="Security incident")
# Resume
gate.unkill()
SaaS API
Run Rungate as a hosted validation service:
pip install rungate-ai[server]
rungate-server --port 8000
# Validate a tool-call
curl -X POST http://localhost:8000/v1/validate \
-H "Authorization: Bearer rg_your_api_key" \
-H "Content-Type: application/json" \
-d '{"agent": "researcher", "tool": "web_search", "args": {"query": "test"}}'
Same Rungate class, adding api_key= switches from self-hosted to SaaS:
# Self-hosted
gate = Rungate(config)
# SaaS (same API)
gate = Rungate(config, api_key="rg_your_key", api_url="https://api.rungate.dev")
Configuration
YAML Config
mode: enforce
policies:
default:
mode: deny
tools:
web_search: allow
researcher:
mode: allow
tools:
delete_file: block
conditions:
- tool: web_search
block_if:
query_contains: ["password", "secret"]
schemas:
web_search:
type: object
required: [query]
properties:
query:
type: string
minLength: 1
rate_limits:
global:
max_calls: 100
window_seconds: 60
cost:
tool_costs:
web_search: 0.01
budgets:
global: 100.0
Load from YAML:
gate = Rungate.from_yaml("config/policies/default.yaml")
Audit & Observability
Every tool-call is logged with full context:
# Query audit logs
events = gate._audit.query(agent="researcher", limit=10)
# Get system stats
stats = gate.stats()
# → {"total_calls": 1523, "blocked": 47, "kill_switch": {...}, ...}
License
- Free for organizations under $1M ARR
- Paid for organizations over $1M ARR (contact for pricing)
- Converts to Apache 2.0 on October 26, 2027
Contributing
Contributions are welcome. Please open an issue to discuss before submitting a PR.
git clone https://github.com/pawangupta28/rungate
cd rungate
pip install -e ".[dev]"
pytest tests/ -v
Metadata
Release files for rungate-ai 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| rungate_ai-0.1.0.tar.gz | 45.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rungate_ai-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 93.9 kB
Release files / rungate_ai-0.1.0.tar.gz
| Download URL | rungate_ai-0.1.0.tar.gz |
|---|---|
| Size | 45.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8a93e67c868a5e05cb79e121e3bf74f150a0e884db91b35792d035bced969411
|
|
BLAKE2b-256 checksum How to use checksums |
de0b52de49ce45f10fb18afe5608774e44872ef6e956d4d9c196a0a401863412
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|
Release files / rungate_ai-0.1.0-py3-none-any.whl
| Download URL | rungate_ai-0.1.0-py3-none-any.whl |
|---|---|
| Size | 48.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
405edc24865c0765da0334090887d4073498752d4959928a4bf927a0349781b2
|
|
BLAKE2b-256 checksum How to use checksums |
8fc3347f0bef2d2eaf5aecdcdccfd3525b281afd9e26771cc75d9145b760f693
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|
Security for rungate-ai 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.