Metadata-Version: 2.4
Name: agf-sdk
Version: 0.1.0
Summary: Agent Governance Foundation — Python SDK
Project-URL: Homepage, https://agentgovernancefoundation.com
Project-URL: Documentation, https://agentgovernancefoundation.com/docs
License: MIT
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Provides-Extra: all
Requires-Dist: crewai>=0.28; extra == 'all'
Requires-Dist: langchain-core>=0.2; extra == 'all'
Provides-Extra: crewai
Requires-Dist: crewai>=0.28; extra == 'crewai'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.2; extra == 'langchain'
Description-Content-Type: text/markdown

# agf-sdk

Python SDK for the [Agent Governance Foundation](https://agentgovernancefoundation.com) authorization service. Enforce identity, trust, and policy controls on every action your AI agents take.

## Installation

```bash
pip install agf-sdk
```

With LangChain support:

```bash
pip install agf-sdk[langchain]
```

With CrewAI support:

```bash
pip install agf-sdk[crewai]
```

## Quick start

```python
import os
from agf import AgentGovernance

agf = AgentGovernance(
    api_key=os.environ["AGF_API_KEY"],
    org_id="org_acme",
)

result = agf.authorize(
    agent_id="did:agf:agt_01abc",
    action="file:write",
    resource="s3://corp-data/q2.csv",
)

if result.allowed:
    write_file()
else:
    raise PermissionError(f"Denied: {result.reason}")
```

## Authorization results

`authorize()` never raises for deny/review — it always returns an `AuthResult`:

| Field | Type | Description |
|---|---|---|
| `allowed` | `bool` | `True` when the PDP issued ALLOW |
| `denied` | `bool` | `True` when the PDP issued DENY |
| `review_required` | `bool` | `True` when HITL approval is needed |
| `reason` | `str` | Human-readable denial reason |
| `artifact_id` | `str` | Signed audit artifact ID |
| `risk_score` | `float` | 0.0–1.0 |
| `trust_score` | `int` | 0–100 |
| `approval_request_id` | `str` | HITL request ID (review_required only) |

## Async client

For async frameworks (FastAPI, async Django, etc.) use `AGFClient` directly:

```python
from agf import AGFClient, AGFDeniedError

async def handle_request():
    async with AGFClient(api_key="agfk_...") as client:
        try:
            result = await client.decide(
                action_type="file:write",
                resource="s3://corp-data/q2.csv",
                chain=[root_jwt, agent_jwt],
            )
        except AGFDeniedError as exc:
            print(f"Denied — artifact: {exc.artifact_id}")
```

## LangChain integration

### Authorization gate tool (recommended for most agents)

Add an authorization tool to your agent's tool list. The agent calls it before performing sensitive operations:

```python
from agf import AgentGovernance
from langchain.agents import initialize_agent, AgentType
from langchain_openai import ChatOpenAI

agf = AgentGovernance(api_key="agfk_...", org_id="org_acme")
agf_tool = agf.langchain_tool(agent_id="did:agf:agt_01abc")

agent = initialize_agent(
    tools=[agf_tool, *your_other_tools],
    llm=ChatOpenAI(),
    agent=AgentType.OPENAI_FUNCTIONS,
)
```

### Per-tool guard (enforces policy on every tool call)

Wrap individual tools so no call can bypass the policy check:

```python
from langchain_community.tools import ShellTool
from agf.langchain import AGFGuardedTool
from agf import AGFClient

client = AGFClient(api_key="agfk_...")

guarded_shell = AGFGuardedTool(
    tool=ShellTool(),
    client=client,
    agent_id="did:agf:my-assistant",
    action_type="exec:shell",
    resource="local-shell",
)
```

## CrewAI integration

```python
from crewai import Agent
from crewai.tools import BaseTool as CrewBaseTool
from agf.crewai import AGFCrewAITool
from agf import AGFClient

client = AGFClient(api_key="agfk_...")

class MyDBTool(CrewBaseTool):
    name: str = "database_query"
    description: str = "Query the production database"

    def _run(self, query: str) -> str:
        return db.execute(query)

guarded = AGFCrewAITool(
    tool=MyDBTool(),
    client=client,
    agent_id="did:agf:crew-researcher",
    action_type="query:database",
    resource="prod-db",
)

crew_agent = Agent(tools=[guarded], ...)
```

## Webhook verification

```python
from agf import verify_signature, parse_event, AGFWebhookVerificationError

# FastAPI example
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.post("/agf-webhook")
async def handle(request: Request):
    body = await request.body()
    try:
        verify_signature(body, request.headers["X-AGF-Signature"], WEBHOOK_SECRET)
    except AGFWebhookVerificationError:
        raise HTTPException(status_code=400, detail="Invalid signature")

    event = parse_event(body)
    if event.type == "decision.deny":
        print(f"Agent {event.agent_id} was denied — artifact {event.artifact_id}")
```

## Sync client

For scripts, Django views, or any non-async context:

```python
from agf import SyncAGFClient

with SyncAGFClient(api_key="agfk_...") as client:
    result = client.decide("file:write", "s3://bucket/file.csv")
    agents = client.list_agents(status="active")
```

## Environment variable

Set `AGF_API_KEY` in your environment and pass it via `os.environ["AGF_API_KEY"]`. The SDK does not auto-read environment variables — this keeps the dependency graph minimal and the behaviour explicit.

## Requirements

- Python 3.10+
- `httpx >= 0.27`
- `langchain-core >= 0.2` (optional, `agf-sdk[langchain]`)
- `crewai >= 0.28` (optional, `agf-sdk[crewai]`)

## Links

- [Documentation](https://agentgovernancefoundation.com/docs)
- [Quick start](https://agentgovernancefoundation.com/docs/quick-start)
- [API reference](https://agentgovernancefoundation.com/docs/api)
