Skip to main content

archytan-lite (Python)

Fail-closed Python client for the Archytan Lite authorization gate.

pip install archytan-lite

The rule this client enforces

Only an HTTP 200 whose body has decision == "ALLOW", and a receipt whose Ed25519 signature verifies against the gate's public key, and a receipt that describes this request counts as authorized.

Everything else is denied: a non-200, a timeout, a refused connection, a malformed body, a signature that doesn't verify, a receipt for some other action, the gate process being dead.

Nothing here raises for a denial. A denial arrives as allowed=False, never as an exception — an exception is something a caller can forget to catch, and a forgotten except around an authorization check fails open.

Use

from uuid import uuid4
from archytan_lite import authorize, redeem_capability

result = authorize(
    url="http://archytan-lite:8421",
    token=CALLER_TOKEN,
    gate_public_key_hex=GATE_PUBLIC_KEY,   # the hex `keygen` printed
    action="invoice.delete",
    actor={"uid": "user_1"},               # see "Roles" below
    resource={"type": "invoice", "id": "inv_7"},
    idempotency_key=str(uuid4()),
)
if not result.allowed:
    raise PermissionError(result.reason)

authorize_async and redeem_capability_async are the async forms. They share their decision logic with the sync versions rather than reimplementing it — two copies is how a sync path and an async path end up disagreeing about what "authorized" means, with only one of them audited.

Roles

Omit actor["role"] when the gate runs credential-bound roles. In that mode your role is a property of your credential, resolved server-side, and a role asserted in the request that disagrees with it is treated as an escalation attempt and refused. The receipt comes back carrying the role the gate resolved.

Send actor["role"] only against a gate configured with a single shared token, which has no other way to learn one. When you do send it, this client checks the receipt agrees with it.

Capabilities

When the gate has capabilities enabled, an ALLOW carries a single-use grant scoped to exactly one action on one resource, expiring in seconds. Holding it is not permission to act — spend it immediately before acting:

spent = redeem_capability(
    url="http://archytan-lite:8421",
    token=CALLER_TOKEN,
    capability_token=result.capability.token,
    action="invoice.delete",
    resource={"type": "invoice", "id": "inv_7"},
)
if not spent.redeemed:
    raise PermissionError(spent.reason)   # expired, out of scope, or already spent

delete_invoice("inv_7")

A second redemption of the same capability is refused, so an actuator cannot be driven to act twice on one authorization.

AI agent frameworks

pip install "archytan-lite[langchain]"

ArchytanGuardedTool wraps a function so an agent cannot reach it without the gate authorizing the call and the capability being spent first:

from archytan_lite.integrations.langchain import ArchytanGuardedTool

delete_invoice_tool = ArchytanGuardedTool(
    name="delete_invoice",
    description="Permanently delete an invoice by id.",
    action="invoice.delete",
    resource_type="invoice",
    func=really_delete_invoice,          # reached only after ALLOW + redemption
    gate_url="http://archytan-lite:8421",
    caller_token=AGENT_TOKEN,
    gate_public_key_hex=GATE_PUBLIC_KEY,
    actor_uid="agent-invoices",
)

It is a LangChain BaseTool, which LangGraph and CrewAI both accept, so one integration covers all three.

A denial returns an explanation to the agent rather than raising, because a raised exception inside an agent loop is usually swallowed and retried — the agent should be told it was refused, in text it can reason about, so it stops rather than loops.

What this cannot do for you: nothing stops your code from importing the underlying function and calling it directly. The wrapper makes the guarded path the easy one and the unguarded path a deliberate act; it is not a sandbox.

Contract siblings

This client, clients/node/index.js, and the authorize() helper in testing/failclosed/failclosed_test.go are the same contract in three languages. If you change the decision logic in one, change it in the others.

What it does not do

It verifies the signature over the intent_hash the gate returned. It does not recompute that hash from the receipt's fields — doing so would require byte-for-byte replication of Go's encoding/json output, including its HTML-escaping of <, > and &, and getting that subtly wrong would silently reject legitimate receipts. Confirming a stored receipt still matches its hash is --verify-chain's job, server-side, where the canonical encoding lives.

Download files

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

Source Distribution

archytan_lite-2.0.0.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

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

archytan_lite-2.0.0-py3-none-any.whl (13.3 kB view details)

Uploaded Python 3

File details

Details for the file archytan_lite-2.0.0.tar.gz.

File metadata

  • Download URL: archytan_lite-2.0.0.tar.gz
  • Upload date:
  • Size: 15.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for archytan_lite-2.0.0.tar.gz
Algorithm Hash digest
SHA256 30c5567164839f6dd2dce7983ad533506b13ee1655572e1bb67ffc0866f3c683
MD5 c93068004f9fac4ecb2b4022b0a64ed8
BLAKE2b-256 a8e427fcf1b3cf350d3ce965b21a54c2862941f0f44cc57999953d2fecc044ff

See more details on using hashes here.

File details

Details for the file archytan_lite-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: archytan_lite-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 13.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for archytan_lite-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 047a1d7a920319e6cd5ca4af243726bd73d545bf433c837d2106d904f9224ae9
MD5 7395309b9ec41984c250eed80fdea980
BLAKE2b-256 63c73a129a313730f55d4fa40f2f5d4614f67a1482155b21dd9536f63483f57d

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page