Metadata-Version: 2.4
Name: agent-guard-python
Version: 0.2.6
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Security
Summary: Outbound change control for AI agents — gate shell, file-write and HTTP side effects before they happen
Keywords: security,sandbox,policy,agent,audit
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/XuebinMa/agent-guard/blob/main/CHANGELOG.md
Project-URL: Homepage, https://github.com/XuebinMa/agent-guard
Project-URL: Repository, https://github.com/XuebinMa/agent-guard

# agent-guard-python

> **Python bindings for execution control at the agent side-effect boundary.**

This package provides Python bindings for `agent-guard`, giving Python hosts a pre-execution decision layer before agent tool calls turn into shell commands or other side effects.

---

## 🚀 Quick Start (Python Adapters)

> **Status**: The Python wrapper layer is a **beta adapter surface**. The clearest current proof point is still shell-first execution control, and Node remains the most mature integration path in the repository.

Integrate `agent-guard` into your existing LangChain tools with a policy gate in front of the original tool:

```python
from agent_guard import Guard, wrap_langchain_tool

# 1. Initialize the Guard with your security policy
guard = Guard.from_yaml_file("policy.yaml")

# 2. Secure your existing tools
bash_tool = ShellTool() # Your original tool
secured_tool = wrap_langchain_tool(guard, bash_tool, agent_id="researcher")

# 3. Use the tool as normal - agent-guard handles the rest!
secured_tool.run("ls -la")
```

OpenAI-style handler wrapping is also available:

```python
from agent_guard import Guard, wrap_openai_tool, AgentGuardDeniedError

guard = Guard.from_yaml_file("policy.yaml")

guarded_handler = wrap_openai_tool(
    guard,
    lambda input_data: {"ok": True, "query": input_data["query"]},
    tool="web_search",
    mode="check",
    trust_level="trusted",
)

try:
    print(guarded_handler({"query": "agent-guard"}))
except AgentGuardDeniedError as error:
    print("blocked", error.code)
```

---

## ✨ Features

- 🛡️ **Pre-execution policy decisions**: Put allow/deny/ask checks in front of Python tool handlers.
- 💻 **Shell-first execution control**: The strongest current execution path is still shell / Bash style tooling.
- ⚠️ **Typed adapter errors**: Distinct deny, ask-required, and execution failure exceptions.
- 📜 **Signed receipts**: Optional cryptographic proof of execution when you need deeper verification.
- 🔏 **Signed policy loading**: Optional detached-signature verification for `policy.yaml`.
- 📊 **Auditing support**: JSONL logs and metrics integration for operator-visible outcomes.

Current boundary note:

- explicit `check` mode remains a policy-only gate; in `auto` mode, non-shell
  tools use `Guard.run()`. A `Handoff` closes its one-shot lifecycle before
  returning the original handler result, while Guard-owned WriteFile or
  mutating HTTP outcomes may execute without invoking that handler
- the exact tool ID `bash` is the owned shell path; shell-like custom IDs such
  as `shell`, `terminal`, `sh`, `cmd`, or `powershell` fail closed in `auto`
  with `UnsupportedShellAlias` until explicitly mapped or assigned a mode
- Python is an active adapter surface, but still below the current Node path in maturity
- `Guard.execute()` / `Guard.run()` use the SDK default sandbox selection, or accept an explicit `backend=` keyword (`"none"`, `"linux-seccomp"`, `"linux-landlock"`, `"macos-seatbelt"`, `"windows-job-object"`, `"windows-appcontainer"`); a backend that is not compiled into the module or not functional on the host resolves truthfully to `"none"`, and an unknown name raises
- to get real isolation through `backend=`, build the module with the matching feature forwarded, e.g. `maturin develop --features extension-module,seccomp` (requires libseccomp on Linux); the default build carries no sandbox feature
- if the default sandbox diagnosis falls back to `NoopSandbox`, the policy gate still runs, but OS-level isolation is not equivalent
- unknown, expired, or duplicate handoff report IDs raise `GuardError`; a
  successful host action whose report fails surfaces `AgentGuardExecutionError`
  with the host result, request ID, attempted handoff result, and an explicit
  do-not-retry marker rather than silently returning success

---

## 🔧 Installation

The latest published package is `0.2.6`:

```bash
python -m pip install agent-guard-python==0.2.6
```

To test the current `0.2.6` source, install it from a repository checkout
(requires Python and a Rust toolchain):

```bash
python -m pip install ./crates/agent-guard-python
```

The distribution name is `agent-guard-python`; the import name remains
`agent_guard`:

```python
from agent_guard import Guard
```

For local development in this repository:

```bash
cd crates/agent-guard-python
maturin develop --features extension-module
pytest tests -v
```

---

## 📺 Demos

Check the `examples/` directory for full usage scenarios:
- `demo_langchain.py`: Comprehensive 3-line integration demo.
- `provenance_receipt.py`: Cryptographic verification example.

