Metadata-Version: 2.4
Name: sentinel-agent-trust-crewai
Version: 0.1.0
Summary: CrewAI adapter for Sentinel AI agent governance — wrap any CrewAI tool so every call is authorized (and audited) by the Sentinel gateway before it runs. Private beta: cosimo@plannest.net
Author-email: "Cosimo (plannest.net)" <cosimo@plannest.net>
License: Apache-2.0
Keywords: ai-agents,crewai,governance,security,authorization,sentinel,tools
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: sentinel-agent-trust>=0.2.0
Requires-Dist: crewai>=0.86
Dynamic: license-file

# sentinel-agent-trust-crewai

[![PyPI](https://img.shields.io/pypi/v/sentinel-agent-trust-crewai)](https://pypi.org/project/sentinel-agent-trust-crewai/)
[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-green.svg)](LICENSE)

CrewAI adapter for **Sentinel AI** — the identity & governance layer for
AI agents. Wrap any CrewAI tool so that **every call is authorized (and
audited) by the Sentinel gateway before it runs**: your tool code and your
crew stay untouched.

> Sentinel is in **private beta**. For source access, a hosted sandbox
> organization key, or to collaborate: **cosimo@plannest.net**

## Install

```bash
pip install sentinel-agent-trust-crewai
```

## Quickstart

```python
import os
from crewai import Agent
from crewai.tools import tool
from sentinel_crewai import SentinelGuard

@tool("create_refund")
def create_refund(customer: str, amount: float) -> str:
    """Issue a refund to a customer."""
    return billing.refund(customer, amount)

guard = SentinelGuard(
    agent_id="agt_...",
    private_key=os.environ["SENTINEL_AGENT_PRIVATE_KEY"],  # base64 Ed25519 seed
    gateway_url="https://your-gateway.example.com",
)

agent = Agent(
    role="billing assistant",
    goal="handle refunds within policy",
    backstory="…",
    tools=guard.wrap_all([create_refund]),   # ← the only change to your crew
)
```

Every tool call is signed with the agent's Ed25519 key and checked against
your policies in real time. The wrapped tool keeps the same name,
description, and argument schema — the LLM sees no difference.

## What the model sees

Sentinel's decision comes back as the tool's observation (the underlying
tool is **never executed** unless the gateway approves):

| Gateway outcome | Tool behavior |
|---|---|
| `200` approved | the wrapped tool runs, result returned as usual |
| `403` denied (policy, constraint, budget) | not executed; observation says the denial is **final** for these arguments — don't retry, branch |
| `202` approval required | not executed; observation carries the `approval_id` and says to inform the user and retry the identical call after a human approves |
| gateway unreachable | not executed (**fail-closed**); observation says it's transient and safe to retry |

This mapping is what keeps agents out of retry loops: a policy denial reads
as a hard "no", an approval-pending reads as "park it", an outage reads as
"try again shortly".

## Mapping tools to your policy taxonomy

By default a tool named `create_refund` is authorized as action
`tool.create_refund` on resource `tool://create_refund` (tool names with
spaces are slugified), so a single policy with `action_pattern: "tool.*"`
governs every wrapped tool. For business-level policies, map tools
explicitly:

```python
tools = guard.wrap_all(
    [create_refund, read_contact],
    overrides={
        "create_refund": {"action": "crm.refund.create", "resource": "crm://refunds"},
        "read_contact":  {"action": "crm.contact.read",  "resource": "crm://contacts/*"},
    },
)
```

…and the policy on the Sentinel side:

```json
{
  "action_pattern": "crm.refund.create",
  "constraints": {"max_amount": 5000, "max_total_amount_per_day": 20000},
  "approval_thresholds": {"amount": 500}
}
```

*Each refund ≤ 5000, at most 20 000/day in total, and a human approves
anything from 500 up — enforced outside the model, no prompt engineering.*

The tool's keyword arguments are sent as the action payload, so constraints
like `max_amount` apply to the actual `amount` argument the model chose.

## Demo

With the repo's demo gateway running (`cd gateway && go run .`):

```bash
pip install -e sdk/python -e sdk/adapters/crewai
python examples/crewai_crm_agent.py
```

## See also

- [`sentinel-agent-trust-langchain`](https://pypi.org/project/sentinel-agent-trust-langchain/) — the LangChain twin of this adapter
- [`sentinel-agent-trust`](https://pypi.org/project/sentinel-agent-trust/) — the underlying Python SDK (includes proxy mode)

## License

Apache 2.0 (the adapter and SDKs). The Sentinel platform is licensed
separately under BSL 1.1 — see the repository root.
