Catalog PyPI
Back to packageRELEASE DETAILS

1.4.0

PyPI

agentguardproxy

Python SDK for AgentGuard — the firewall for AI agents

agentsaifirewallguardrailspolicysafety
Published16 Oct 2026
Direct dependencies12
Transitive dependenciesNot calculated

README

Version 1.4.0 documentation

AgentGuard Python SDK

Lightweight Python client for AgentGuard — the firewall for AI agents.

  • Zero runtime dependencies for the core SDK (stdlib urllib).
  • Fail-closed by default — if the proxy is unreachable, check() returns DENY.
  • Framework adapters for LangChain, CrewAI, browser-use, MCP, and the OpenAI Agents SDK, gated behind optional extras.

Deep reference: docs/SDK_PYTHON.md — full API, exception hierarchy, fail-mode details, adapter internals.

Install

pip install agentguardproxy

# With framework adapters
pip install agentguardproxy[langchain]
pip install agentguardproxy[crewai]
pip install agentguardproxy[browser-use]
pip install agentguardproxy[mcp]
pip install 'agentguardproxy[openai-agents]'
pip install agentguardproxy[all]

The package is agentguardproxy; the import name is agentguard. agentguard-sdk on PyPI is an unrelated project that also installs an agentguard module — don't install both in the same environment.

Quick start

from agentguard import Guard

guard = Guard(
    base_url="http://localhost:8080",   # or set AGENTGUARD_URL
    agent_id="my-agent",
    api_key="…",                        # or set AGENTGUARD_API_KEY (needed for approve/deny/status)
)

result = guard.check("shell", command="rm -rf ./old_data")

if result.allowed:
    execute(command)
elif result.needs_approval:
    print(f"Approve at: {result.approval_url}")
    # Block until a human resolves it, or 5 min deadline, whichever first
    final = guard.wait_for_approval(result.approval_id, timeout=300)
    if final.allowed:
        # Replay the approval: consumes the one-shot ALLOW, reserves cost,
        # and audits the execution. The status poll alone spends nothing.
        replay = guard.check("shell", command=command, approval_id=result.approval_id)
        if replay.allowed:
            execute(command)
else:
    print(f"Blocked: {result.reason}")

Environment variables

VarDefaultUsed by
AGENTGUARD_URLhttp://localhost:8080Guard(base_url="") fallback
AGENTGUARD_API_KEY(empty)Guard(api_key="") fallback; sent as Authorization: Bearer <key> on /v1/approve, /v1/deny, /v1/status
AGENTGUARD_TENANT_ID(empty)Guard(tenant_id=None) fallback; a value other than local routes calls to /v1/t/<tenant>/…

Fail mode

# Default: fail closed. Proxy unreachable → CheckResult(decision="DENY", reason="AgentGuard unreachable (deny): …")
guard = Guard("http://localhost:8080")

# Opt in to fail open. Proxy unreachable → CheckResult(decision="ALLOW", reason="AgentGuard unreachable (allow): …")
# Use only when your threat model treats AgentGuard as advisory.
guard = Guard("http://localhost:8080", fail_mode="allow")

Fail mode applies to transport failures — urllib.error.URLError (connection refused / DNS / SSL, and HTTP error statuses), OSError (post-connect timeouts and resets), json.JSONDecodeError (garbage response body) — and to responses that aren't a valid decision (a non-JSON Content-Type, or a body without decision).

The @guarded decorator

from agentguard import Guard, guarded, AgentGuardDenied, AgentGuardApprovalRequired

guard = Guard("http://localhost:8080", agent_id="my-agent")

@guarded("shell", guard=guard)
def run_command(cmd: str):
    os.system(cmd)

try:
    run_command("ls")
    run_command("rm -rf /")        # raises AgentGuardDenied
except AgentGuardDenied as e:
    log(f"blocked: {e.result.reason}")

On REQUIRE_APPROVAL the decorator raises AgentGuardApprovalRequired immediately. To block until a human resolves it, opt in:

@guarded("cost", guard=guard, wait_for_approval=True, approval_timeout=300)
def expensive_call(prompt: str): ...

All AgentGuard exceptions (AgentGuardDenied, AgentGuardApprovalRequired, AgentGuardApprovalTimeout, AgentGuardAuthError) extend PermissionError, so existing except PermissionError: handlers keep working unchanged.

Framework adapters

LangChain

from agentguard.adapters.langchain import GuardedToolkit

toolkit = GuardedToolkit(
    tools=my_tools,
    guard_url="http://localhost:8080",
    agent_id="langchain-agent",
)
agent = create_react_agent(llm, toolkit.tools, prompt)

Scope is inferred from each tool's name/description (http/api→network, file/path→filesystem, browser→browser, shell→shell) and upgraded at call time if the input dict contains url, domain, or path keys.

CrewAI

from agentguard.adapters.crewai import guard_crew_tools

guarded_tools = guard_crew_tools(
    tools=my_crew_tools,
    guard_url="http://localhost:8080",
    agent_id="crew-agent",
)

Hooks both run and _run (CrewAI calls _run internally).

browser-use

from agentguard.adapters.browseruse import GuardedBrowser

browser = GuardedBrowser(guard_url="http://localhost:8080")

if browser.check_navigation("https://example.com").allowed:
    await page.goto("https://example.com")

# Or wrap the page directly so goto() enforces policy for you:
guarded_page = browser.wrap_page(page)
await guarded_page.goto("https://example.com")   # raises PermissionError on deny/approval

MCP

from agentguard.adapters.mcp import GuardedMCPServer

server = GuardedMCPServer(guard_url="http://localhost:8080")
server.add_tool("my_tool", "Description", handler=my_handler)
server.run()   # stdio JSON-RPC MCP server; pins MCP_PROTOCOL_VERSION

Or as a drop-in stdio server:

python -m agentguard.adapters.mcp --guard-url http://localhost:8080

OpenAI Agents SDK

from agents import Agent, Runner, function_tool
from agentguard import AgentGuardDenied, Guard
from agentguard.adapters.openai_agents import guard_tools

@function_tool
def run_shell(command: str) -> str:
    ...

guard = Guard("http://localhost:8080", agent_id="ops-agent")
agent = Agent(name="ops", tools=guard_tools([run_shell], guard))

try:
    result = await Runner.run(agent, "clean up the build directory")
except AgentGuardDenied as e:
    print("blocked:", e.result.reason)

guard_tools returns gated copies of the FunctionTools; DENY and REQUIRE_APPROVAL raise out of Runner.run before the tool runs. To let the model see the reason and continue instead, attach agentguard_tool_guardrail(guard) as a tool input guardrail. Hosted tools (WebSearchTool, ...) cannot be gated. Runnable example: examples/openai-agents-config.py.

API reference (summary)

Guard(base_url="", agent_id="", timeout=5, api_key="", fail_mode="deny", tenant_id=None)

MethodBehavior
check(scope, *, action, command, path, domain, url, session_id, est_cost, meta, approval_id)POST /v1/check (approval_id replays a resolved approval — see the quick start). Returns CheckResult. Transport failure → fail-closed DENY (or ALLOW if fail_mode="allow").
approve(id) / deny(id)POST /v1/approve/{id} / /v1/deny/{id}. Returns bool success. Sends Bearer if api_key set.
wait_for_approval(id, timeout=300, poll_interval=2)Polls GET /v1/status/{id} until resolved or deadline. Timeout → CheckResult(DENY, "Approval timed out").

CheckResult

Fields: decision, reason, matched_rule, approval_id, approval_url. Properties: .allowed, .denied, .needs_approval.

Exception hierarchy (all extend PermissionError)

  • AgentGuardError — base; carries .result: CheckResult.
  • AgentGuardDenied — policy said DENY.
  • AgentGuardApprovalRequired — policy said REQUIRE_APPROVAL and the decorator was not configured to wait. Carries .approval_id, .approval_url.
  • AgentGuardApprovalTimeout — wait_for_approval deadline elapsed. Carries .approval_id.
  • AgentGuardAuthError — a wait_for_approval status poll got 401/403 (API key missing or wrong). Carries .status.

License

Apache 2.0

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 13

Native requirements
12 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
langchain-core
Environment
{
  "extras": "",
  "marker": "extra == \"langchain\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
langchain-core<2.0,>=0.3; extra == "langchain"runtime
langchain
Environment
{
  "extras": "",
  "marker": "extra == \"langchain\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
langchain<2.0,>=0.3; extra == "langchain"runtime
crewai
Environment
{
  "extras": "",
  "marker": "extra == \"crewai\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
crewai<2.0,>=1.0; extra == "crewai"runtime
browser-use
Environment
{
  "extras": "",
  "marker": "extra == \"browser-use\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
browser-use<1.0,>=0.4; extra == "browser-use"runtime
playwright
Environment
{
  "extras": "",
  "marker": "extra == \"browser-use\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
playwright>=1.40; extra == "browser-use"runtime
mcp
Environment
{
  "extras": "",
  "marker": "extra == \"mcp\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
mcp<3.0,>=0.9; extra == "mcp"runtime
openai-agents
Environment
{
  "extras": "",
  "marker": "extra == \"openai-agents\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
openai-agents<1.0,>=0.3.3; extra == "openai-agents"runtime
agentguardproxy
Environment
{
  "extras": "browser-use,crewai,langchain,mcp,openai-agents",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
agentguardproxy[browser-use,crewai,langchain,mcp,openai-agents]; extra == "all"runtime
pytest
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
pytest>=7.0; extra == "dev"runtime
pytest-cov
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
pytest-cov>=4.0; extra == "dev"runtime
pytest-asyncio
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
pytest-asyncio>=0.21; extra == "dev"runtime
responses
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
responses>=0.23; extra == "dev"runtime
agentguardproxy
Environment
{
  "extras": "browser-use,crewai,langchain,mcp,openai-agents",
  "marker": "extra == \"integration\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
agentguardproxy[browser-use,crewai,langchain,mcp,openai-agents]; extra == "integration"runtime

Distribution files

2 collected
agentguardproxy-1.4.0-py3-none-any.whl

bdist_wheel · 53.61 KB · Python py3

Source file
agentguardproxy-1.4.0.tar.gz

sdist · 113.52 KB · Python source

Source file

Repository

MOVED
caua-ferraz/agentguard

Shared repository data · GitHub

Repository moved · manual review pending

HTTP 301 · detected 22 Oct 2026

Reported destination
License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 22:06 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:062304fdec60ab0f8a37ec2c2d596bc27016cd4ddb37b4d97f0ea7fb8e89ceaf

Other collected versions

View all collected versions →