Metadata-Version: 2.4
Name: authgraph
Version: 0.1.0
Summary: authgraph — the DAG framework where every agent action needs a permit before it runs. Import as authgate. Powered by TrigGuard.
Author: TrigGuard AI
License-Expression: Apache-2.0
Project-URL: Homepage, https://www.trigguardai.com
Project-URL: Repository, https://github.com/TrigGuard-AI/TrigGuard
Project-URL: Documentation, https://trigguardai.com/docs
Project-URL: Issues, https://github.com/TrigGuard-AI/TrigGuard/issues
Keywords: authgraph,authgate,trigguard,permit,execution-graph,dag,orchestration,authorization,ai-governance,agent-framework
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: trigguard>=0.2.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: ruff>=0.4.0; extra == "dev"
Requires-Dist: mypy>=1.8; extra == "dev"
Dynamic: license-file

# authgate

**The DAG framework where every agent action needs a permit before it runs.**

```bash
pip install authgraph
```

```python
from authgate import AGEFRuntime
```

`authgraph` is the PyPI distribution name; import the package as `authgate`. It is a Python DAG execution framework where every node transition asks a TrigGuard gateway "is this allowed?" and refuses to proceed without a PERMIT receipt. No permit → no execution. Every action leaves a signed receipt.

**Powered by [TrigGuard](https://trigguardai.com).** Requires a TrigGuard gateway (hosted free tier: 5,000 decisions/month, no credit card).

*Previously known internally as AGEF (Authority-Governed Execution Framework).*

---

## What authgate is

authgate is a DAG-based execution orchestration framework for AI agents. It answers a question that Temporal, Airflow, LangGraph, and CrewAI don't:

> *Before this agent executes this task — is it actually authorized to?*

authgate wraps every claim, every execution, and every completion in a TrigGuard authorization call. The result is a verifiable audit trail of receipts that proves every action was permitted before it happened.

---

## Relationship to TrigGuard

```
┌─────────────────────────────────────────────────┐
│                    authgate                         │
│  DAG engine  ·  Coordinator  ·  Verification    │
│                                                 │
│           AuthorityGate (gate.py)               │
│    ↓ authorize(surface, actor, context) ↓       │
└──────────────────┬──────────────────────────────┘
                   │  public SDK only
                   ▼
┌─────────────────────────────────────────────────┐
│                  TrigGuard                      │
│  Authorization  ·  Receipts  ·  Policy          │
└─────────────────────────────────────────────────┘
```

authgate is a **consumer** of TrigGuard. It calls TrigGuard's public `authorize()` SDK method and stores the returned receipt IDs as references. authgate never:

- Imports TrigGuard internals
- Mints or signs receipts
- Bypasses the authority boundary
- Modifies TrigGuard policy

The `AuthorityGate` class (`gate.py`) is the only file in authgate that touches TrigGuard. Every other module is framework-neutral.

---

## Architecture

```
authgateRuntime
├── ExecutionGraphEngine    DAG validation, Kahn's topological sort, state machine
├── AuthorityGate           Single TrigGuard integration point
├── Coordinator             Claim leases, TTL, duplicate suppression
├── VerificationEngine      Evidence checks, hallucination detection
└── OutcomeTracker          Drift scoring, policy flywheel data
```

### Node lifecycle

```
PENDING → READY → CLAIMED → EXECUTING → VERIFYING → COMPLETE
                                                   ↘ FAILED → READY (retry)
```

Every `PENDING → CLAIMED` and `VERIFYING → COMPLETE` transition requires a TrigGuard `PERMIT`.

### TrigGuard surfaces

| Surface | When |
|---|---|
| `planning.task.create` | Before `READY → CLAIMED` |
| `artifact.publish` | Before `VERIFYING → COMPLETE` |
| `execution.external_action` | Before releasing downstream external-effect nodes |

---

## Quick start

```python
import os
from authgate import authgateRuntime, EvidenceArtifact, VerificationTier
import hashlib

# Set your TrigGuard API key
os.environ["TRIGGUARD_API_KEY"] = "your-key"

runtime = authgateRuntime()

graph = runtime.create_graph(title="Deploy workflow", description="Plan → Build → Release")

plan    = runtime.add_node(graph, title="Plan",    description="Define scope")
build   = runtime.add_node(graph, title="Build",   description="Implement",
                            verification_tier=VerificationTier.HIGH)
release = runtime.add_node(graph, title="Release", description="Publish",
                            authority_surface="artifact.publish",
                            verification_tier=VerificationTier.CRITICAL)

runtime.add_dependency(graph, from_node=plan, to_node=build, transfer_outputs=["spec"])
runtime.add_dependency(graph, from_node=build, to_node=release, transfer_outputs=["artifact"])
runtime.start(graph)

# Claim and execute each node
for node in [plan, build, release]:
    claim = runtime.attempt_claim(graph, node, agent_id="my-agent")
    runtime.execute_node(graph, node, claim_token=claim["claim_token"])

    content = f"work done on {node.title}"
    h = hashlib.sha256(content.encode()).hexdigest()
    runtime.submit_completion(
        graph, node,
        claim_token=claim["claim_token"],
        outputs={"result": f"{node.title} complete"},
        evidence=[EvidenceArtifact(
            artifact_id=f"ev-{h[:8]}", artifact_type="TEXT",
            content_hash=h, content_ref=content, produced_by="my-agent",
        )],
    )

print(graph.status)  # COMPLETE
```

---

## CrewAI example

```python
from authgate import authgateRuntime, VerificationTier

runtime = authgateRuntime()
graph = runtime.create_graph(title="Research crew", description="Authority-governed research")

research = runtime.add_node(graph, title="Research", description="Market analysis")
report   = runtime.add_node(graph, title="Report",   description="Publish findings",
                              authority_surface="artifact.publish")

runtime.add_dependency(graph, from_node=research, to_node=report)
runtime.start(graph)

# Wrap each CrewAI task execution with attempt_claim / execute_node / submit_completion
# TrigGuard receipt is stored on node.complete_authority_receipt_id
```

See [`examples/crewai_example.py`](examples/crewai_example.py) for the full pattern.

---

## LangGraph example

```python
bridge = authgateLangGraphBridge()
bridge.register_node("planner", "Generate plan")
bridge.register_node("executor", "Execute plan", depends_on=["planner"])
bridge.start()

@bridge.guarded_node("planner")
def planner_node(state):
    return {**state, "plan": "do the thing"}
```

Each `@bridge.guarded_node` decorator wraps the LangGraph node function in an authgate authority gate. The TrigGuard receipt is stored in the LangGraph state under `agef_receipts`.

See [`examples/langgraph_example.py`](examples/langgraph_example.py) for the full pattern.

---

## Quanta example

```python
bridge = QuantaauthgateBridge()
graph = bridge.mission_to_graph(quanta_mission)

result = bridge.run_task(graph, "Engineering Build", eng_agent,
                          outputs={"artifact": "v2.tar.gz"},
                          work_summary="Build complete")
```

Quanta creates missions; authgate executes them with authority gates. Quanta is a consumer of authgate — any other orchestrator can replace it.

See [`examples/quanta_example.py`](examples/quanta_example.py) for the full pattern.

---

## Authorization example

```python
# gate.py handles all authorization — nothing else in authgate touches TrigGuard
from authgate import AuthorityGate

gate = AuthorityGate()  # reads TRIGGUARD_API_KEY from environment

decision = gate.authorize_claim(
    node_id="node-abc",
    graph_id="graph-xyz",
    agent_id="my-agent",
    surface="planning.task.create",
    context={"title": "Research task"},
)

if decision.permitted:
    print(f"PERMIT — receipt: {decision.receipt_id}")
else:
    print(f"DENIED — {decision.reason}")  # fail-closed
```

If TrigGuard is unreachable, `permitted` is `False` and the node stays `READY`. Nothing proceeds without a receipt.

---

## Outcome tracking example

```python
from authgate import OutcomeTracker, OutcomeClassification

tracker = OutcomeTracker()

tracker.record(
    node,
    execution_summary="Agent completed research on schedule",
    classification=OutcomeClassification.CORRECT,
    execution_drift_score=0.05,
    outcome_drift_score=0.10,
)

print(tracker.summary())
# {"total": 1, "by_classification": {"CORRECT": 1}, "avg_execution_drift": 0.05, "success_rate": 1.0}

# Export for policy model training
records = tracker.training_records()
```

---

## Environment variables

| Variable | Default | Description |
|---|---|---|
| `TRIGGUARD_API_KEY` | — | TrigGuard API key (required for live authorization) |
| `TRIGGUARD_GATEWAY_URL` | `https://api.trigguardai.com` | TrigGuard gateway URL |

---

## Install

```bash
pip install authgraph
```

Import as `authgate`:

```python
from authgate import AGEFRuntime, ExecutionGraph, ExecutionNode, NodeStatus
```

For development:

```bash
git clone https://github.com/TrigGuard-AI/agef
cd agef
pip install -e ".[dev]"
pytest tests/
```

---

## Authority boundary guarantee

```bash
# Zero TrigGuard internal imports in any authgate module except gate.py
grep -r "from trigguard\." authgate/ | grep -v gate.py  # → 0 matches

# Zero receipt minting
grep -r "mint_receipt\|receipt_chain" authgate/          # → 0 matches

# authorize() called only in gate.py
grep -rn "\.authorize(" authgate/ | grep -v gate.py      # → 0 matches
```

---

## License

MIT — see [LICENSE](LICENSE)
