Metadata-Version: 2.4
Name: leash
Version: 0.3.0
Summary: Leash – AI Agent Identity, Authorization, and Audit Layer
Author: Chad Eckles
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/chadeckles/leash
Project-URL: Repository, https://github.com/chadeckles/leash
Project-URL: Documentation, https://github.com/chadeckles/leash#readme
Project-URL: Issues, https://github.com/chadeckles/leash/issues
Project-URL: Changelog, https://github.com/chadeckles/leash/blob/main/CHANGELOG.md
Keywords: ai,agents,authorization,audit,security,mcp,langchain,crewai,policy,openclaw,guardrails
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.104.0
Requires-Dist: uvicorn[standard]>=0.24.0
Requires-Dist: sqlalchemy>=2.0.0
Requires-Dist: pyjwt>=2.8.0
Requires-Dist: cryptography>=41.0.0
Requires-Dist: pyyaml>=6.0.1
Requires-Dist: pydantic>=2.5.0
Requires-Dist: httpx>=0.25.0
Provides-Extra: dev
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Dynamic: license-file

<p align="center">
  <img src="https://raw.githubusercontent.com/chadeckles/leash/main/assets/leash.png" alt="Leash – Keep your AI agents on a leash" width="700">
</p>

<p align="center">
  <a href="https://pypi.org/project/leash/"><img src="https://img.shields.io/pypi/v/leash?color=blue" alt="PyPI"></a>
  <a href="https://github.com/chadeckles/leash/actions/workflows/tests.yml"><img src="https://github.com/chadeckles/leash/actions/workflows/tests.yml/badge.svg" alt="Tests"></a>
  <a href="https://github.com/chadeckles/leash/actions/workflows/docker.yml"><img src="https://github.com/chadeckles/leash/actions/workflows/docker.yml/badge.svg" alt="Docker"></a>
  <a href="https://github.com/chadeckles/leash/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License"></a>
  <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.11%2B-blue.svg" alt="Python 3.11+"></a>
</p>

# Leash

**Keep your AI agents on a leash.**

You wouldn't let a dog roam the neighborhood unsupervised, so why let an AI agent read your files, send emails, and call APIs _without_ guardrails? Leash is an API-layer policy engine that sits between your agent and the outside world — no containers, no sidecars, just authorization. You write simple YAML rules that say what's allowed. Everything else is denied. Every decision from allow or deny activities is logged in a cryptographically signed, hash-chained audit trail that's tamper-evident by design.

One `pip install`, one policy file, and your agent is on a leash.

## 🌟 Highlights

- 🐕 **Deny by default** — nothing happens unless your policy says so
- 📜 **YAML rules** — human-readable, version-controllable, git-diffable
- 🔗 **Tamper-evident audit trail** — hash-chained and signed; deletions are detectable
- 👀 **Observe mode** — shadow new rules in production before enforcing
- 🔍 **Security scanner** — discover an MCP server's tools, classify risk, generate policies
- 🧩 **Framework-agnostic** — Python SDK, MCP proxy, or plain REST
- 🧠 **[OpenClaw ready](docs/docs/openclaw-guide.md)** — built-in policies for the popular open-source AI assistant
- 🛡️ **OWASP mapped** — rules and audit checks reference [OWASP ASI](https://owasp.org/www-project-agentic-security-initiative/) and [LLM Top 10](https://owasp.org/www-project-top-10-for-large-language-model-applications/) threat IDs
- ⚡ **One dependency** — `pip install leash`. No Go, no Rust, no sidecar containers
- 📖 **[Full documentation](docs/docs/index.md)** — getting started, policy writing guide, SDK reference, CLI reference, architecture

## ⬇️ Installation

```bash
pip install leash
```

Or run from source:

```bash
git clone https://github.com/chadeckles/leash.git && cd leash
make quickstart    # installs deps, starts server, runs a demo
```

Requires Python 3.11+ (macOS ships with 3.9 — run `brew install python@3.12` first if needed).

> 💡 **Running from source?** Use `pip install -e .` to make the `leash` command available globally, or use `./leash` directly from the repo root. See the [getting started guide](docs/docs/getting-started.md) for details.

### Starting the Server

After installing, start the server:

```bash
leash start              # start on port 8000
leash start --reload     # auto-reload for development
leash start --port 9000  # custom port
```

Or from source: `make dev`

## 🚀 Usage

### Python SDK

For developers building agents in Python (LangChain, CrewAI, or custom code). Add a few lines to your existing agent code — no separate config file needed — and every tool call is authorized and audited.

Wrap individual functions with a decorator:

```python
from sdk import LeashAgent

agent = LeashAgent("http://localhost:8000", name="my-agent")

@agent.tool("email.read")
def read_inbox(mailbox: str):
    return gmail.read(mailbox)

with agent:
    read_inbox("user@example.com")   # Leash checks permission first
```

The `name` is how policies find your agent — a policy with `agents: ["*email*"]` matches any agent with "email" in its name.

Or wrap many tools at once with `guard()` — no need to decorate every function individually:

```python
# Wrap a list of existing callables in one line:
guarded = agent.guard([read_inbox, send_email, summarize, search])

# Works with LangChain tools too:
guarded = agent.guard(langchain_tools)
```

If the action is denied, the function doesn't run. If Leash is unreachable, it denies by default (fail-closed).

> 💡 **Deny by default.** These examples will be denied until you [write a policy](#-writing-rules) that allows the action. That's the point — nothing runs unless your rules say so.

### MCP Proxy (Claude Desktop, Cursor, etc.)

[MCP (Model Context Protocol)](https://modelcontextprotocol.io) is how AI tools like Claude Desktop and Cursor connect to external tool servers — but MCP has no built-in authorization. This proxy sits between the AI and the MCP server so every tool call is checked against your policies, with zero code changes to the server:

```bash
python -m sdk.mcp_proxy \
    --agent-name "fs-agent" \
    -- npx -y @modelcontextprotocol/server-filesystem /data
```

Every `tools/call` is authorized, logged, and checked for tool poisoning automatically. The proxy auto-discovers the server's tools on startup.

See the [MCP Proxy Guide](docs/docs/mcp-proxy-guide.md) for Claude Desktop config, Cursor setup, and policy examples.

### OpenClaw

[OpenClaw](https://github.com/openclaw/openclaw) is a popular open-source personal AI assistant. It can run shell commands, browse the web, and manage files — all of which Leash can govern. Leash ships with a built-in OpenClaw policy:

```bash
# Register your OpenClaw agent
leash agents register --name "openclaw-agent" --vendor openclaw

# The built-in policy allows reads and web search, denies exec and browser.
# Customize app/policies/openclaw.yaml to match your needs.
```

See the full [OpenClaw Integration Guide](docs/docs/openclaw-guide.md) for setup, example policies, and tool mappings.

### REST API

Any language — register once, check permission before each action:

```bash
# Register an agent (returns agent_id + JWT token)
curl -s -X POST http://localhost:8000/agents \
  -H "Content-Type: application/json" \
  -d '{"name": "my-agent"}'

# Authorize an action (use the token and agent_id from above)
curl -s -X POST http://localhost:8000/authorize \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "'$AGENT_ID'", "action": "email.read"}'
```

Full interactive API docs at **http://localhost:8000/docs** once the server is running.

## 📜 Writing Rules

Rules live in `app/policies/*.yaml`. The server picks up changes automatically — no restart needed.

```yaml
name: email-agent
priority: 10
agents: ["*email*"]
rules:
  - action: "email.read"
    effect: allow
    reason: "Agent may read emails"

  - action: "email.*"
    effect: deny
    reason: "Everything else is blocked"
```

**How evaluation works:**

- **`priority`** — higher number = evaluated first. The built-in `default.yaml` is priority 0 (catch-all deny). Your policies should be 10+ to take precedence.
- **`agents`** — wildcard patterns matched against the agent's name. `"*email*"` matches any agent with "email" in its name.
- **Rules** — evaluated top-to-bottom within a policy. First match wins. No match anywhere = **denied**.

**Don't guess at rules — observe first.** Deploy new policies in `mode: observe` to see what *would* be denied without actually blocking anything. Once you're confident, flip to `mode: enforce`. See [Write Your First Policy](docs/docs/write-your-first-policy.md) for the full scan-first workflow.

Rules also support rate limiting, ABAC conditions, and OWASP threat tags — see the [policy writing guide](docs/docs/write-your-first-policy.md).

## 🔍 CLI Cheat Sheet

```bash
leash status                              # server health
leash agents list                         # registered agents
leash agents register --name "my-bot"     # register a new agent
leash policy validate app/policies/       # lint your YAML rules
leash audit scan                          # security scan (integrity, storms, shadows)
leash scan -- npx -y @mcp/server-fs /data # scan an MCP server's tools
leash dashboard                           # live terminal TUI
leash doctor                              # health-check your deployment
```

## 🐳 Docker

```bash
make docker-up     # build + start on port 8000
make docker-down   # stop + remove volumes
```

Images are published to [GHCR](https://ghcr.io/chadeckles/leash), multi-arch (amd64 + arm64), and signed with [cosign](https://github.com/sigstore/cosign).

## 🏗️ Project Layout

```
app/
  policies/       ← your rules (edit these)
  policy/         ← policy engine
  audit/          ← hash-chained audit log
  identity/       ← agent registration & JWT
  core/           ← config, auth, crypto, DB
sdk/
  client.py       ← Python SDK (LeashAgent)
  cli.py          ← CLI
  mcp_proxy.py    ← MCP authorization proxy
  scanner.py      ← security surface scanner
  dashboard.py    ← terminal TUI
tests/            ← test suite
```

## ✍️ Author

Built by [Chad Eckles](https://github.com/chadeckles).

## 💭 Feedback & Contributing

Found a bug? Have an idea? [Open an issue](https://github.com/chadeckles/leash/issues) or check out the [contributing guide](CONTRIBUTING.md).

## 📄 License

Apache 2.0 — see [LICENSE](LICENSE).
