Skip to main content

Governance SDK for AI agents — audit trails, policy engine, approval gates.

Project description

agentlattice — Python SDK

Governance-aware SDK for AI agents. Wraps agent actions with audit trails, approval gates, and circuit breaker integration.

Install

pip install agentlattice

Quickstart

import asyncio
import os
from agentlattice import AgentLattice

al = AgentLattice(api_key=os.environ["AL_API_KEY"])

async def main():
    # gate() blocks until approved — your agent code only runs if it passes
    await al.gate("pr.merge")
    await merge_pr(42)

asyncio.run(main())

Handle denials and timeouts:

from agentlattice import AgentLattice, AgentLatticeDeniedError, AgentLatticeTimeoutError

al = AgentLattice(api_key=os.environ["AL_API_KEY"])

async def main():
    try:
        await al.gate("code.commit")
    except AgentLatticeDeniedError as e:
        print(f"Denied: {e.reason}, policy: {e.policy}")
        print(f"Failed conditions: {e.conditions}")
    except AgentLatticeTimeoutError as e:
        print(f"Approval timed out: {e.approval_id}")

asyncio.run(main())

Sync usage

If you're not in an async context:

import os
from agentlattice import AgentLattice

al = AgentLattice(api_key=os.environ["AL_API_KEY"])
al.gate_sync("code.commit")

API

AgentLattice(api_key, *, base_url?, gate_poll_timeout_ms?, gate_poll_interval_ms?)

Parameter Default Description
api_key required Bearer token — pass via os.environ["AL_API_KEY"], never hardcoded
base_url https://agentlattice.com Override for self-hosted or staging
gate_poll_timeout_ms 8 * 60 * 60 * 1000 (8 hours) How long gate() polls for approval
gate_poll_interval_ms 5000 Poll interval in ms

await al.execute(action_type, options?)

Submit an action and return immediately. Returns an ActionResult. Does not block.

from agentlattice import AgentLattice, ActionOptions

al = AgentLattice(api_key="al_...")
result = await al.execute("pr.open", ActionOptions(
    data_accessed=[{"type": "source_code", "count": 5, "sensitivity": "low"}],
    metadata={"pr_number": 42},
    event_id="my-idempotency-key",   # optional: dedup by your own key
))

if result.status == "executed":
    print(f"Auto-executed under policy: {result.policy_name}")
elif result.status == "requested":
    print(f"Awaiting approval: {result.approval_id}")
elif result.status == "denied":
    print(f"Denied ({result.denial_reason}): {result.conditions_evaluated}")

await al.gate(action_type, options?)

Submit an action and block until it is approved or denied.

try:
    await al.gate("pr.merge")
except AgentLatticeDeniedError as e:
    # e.reason:     "CONDITIONS_DENIED" | "POLICY_TAMPERED" | "DENIED_BY_REVIEWER"
    # e.policy:     name of the governing policy (if conditions-based)
    # e.conditions: list of ConditionResult (which rule failed and why)
    # e.approval_id: set if a human reviewer denied it
    ...
except AgentLatticeTimeoutError as e:
    # e.approval_id: the approval that timed out
    ...

al.gate_sync(action_type, options?) / al.execute_sync(action_type, options?)

Synchronous wrappers — identical semantics, no asyncio.run() needed.

ActionResult

@dataclass
class ActionResult:
    status: str                          # "executed" | "requested" | "denied" | ...
    audit_event_id: str
    approval_id: str | None              # set when status="requested"
    message: str | None
    timeout_at: str | None
    denial_reason: str | None            # "CONDITIONS_DENIED" | "POLICY_TAMPERED" | ...
    policy_name: str | None              # governing policy name
    conditions_evaluated: list[ConditionResult]  # which rules passed/failed

ConditionResult

@dataclass
class ConditionResult:
    field: str       # e.g. "pr_size"
    operator: str    # e.g. "lt"
    expected: Any    # e.g. 100
    result: bool     # True = passed, False = failed

Agents can read conditions_evaluated to understand exactly which governance rule blocked them and adapt their behavior accordingly.

Self-correcting agent pattern

conditions_evaluated is what makes this more than a compliance layer — it closes the feedback loop so agents can adapt, not just fail.

from agentlattice import AgentLattice, AgentLatticeDeniedError, ActionOptions

al = AgentLattice(api_key=os.environ["AL_API_KEY"])

async def commit_with_governance(files: list[str]) -> None:
    try:
        await al.gate("pr.open", ActionOptions(
            metadata={"pr_size": len(files), "repo": "acme/backend"},
        ))
        await open_pr(files)

    except AgentLatticeDeniedError as e:
        if e.reason == "CONDITIONS_DENIED":
            # Find which rules failed and why
            failed = [c for c in e.conditions if not c.result]
            # e.g. [ConditionResult(field="pr_size", operator="lt", expected=50, result=False)]

            for rule in failed:
                if rule.field == "pr_size":
                    # Policy says PRs must be < 50 files — split and retry
                    mid = len(files) // 2
                    await commit_with_governance(files[:mid])
                    await commit_with_governance(files[mid:])
                    return

        # Reviewer denial or policy tamper — no retry
        raise

Error hierarchy

AgentLatticeError          base — code, message, details
  AgentLatticeDeniedError  approval_id?, reason?, policy?, conditions?
  AgentLatticeTimeoutError approval_id

Reliability

execute() and gate() retry automatically on 5xx and network errors — up to 3 attempts with 1s/2s/4s exponential backoff. Each request has a 30-second timeout. Pass event_id to make retries idempotent.

execute_sync() and gate_sync() are safe in async runtimes (LangGraph, FastAPI, CrewAI) — they detect a running event loop and dispatch to a thread pool automatically.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agentlattice-0.3.0.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agentlattice-0.3.0-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

File details

Details for the file agentlattice-0.3.0.tar.gz.

File metadata

  • Download URL: agentlattice-0.3.0.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for agentlattice-0.3.0.tar.gz
Algorithm Hash digest
SHA256 c19c9d4281f92bbebcde69dcff3236c6001f49830d548603ffa2a2dc29eaa613
MD5 c65f4274ff9fac17bc643a4f45cd2a58
BLAKE2b-256 94609b5fb9f47ac39b81322757bf5f900257e759aee1db10b5e56bad77453dd0

See more details on using hashes here.

File details

Details for the file agentlattice-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: agentlattice-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 10.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for agentlattice-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 edc46f262720094c039b6bc2fb2f24e841ddfbcfeadce8dec48e4de4d181dfcd
MD5 6fe12c6664f700c0c433174512d3afb7
BLAKE2b-256 345433a6190c21ad70ba639a0777e38f251c689f233b65c0de0893b5f9e49166

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page