Skip to main content

ClawID — Agent KYC. Verify autonomous AI agent credentials in three lines.

Project description

ClawID

clawid-sdk

Agent KYC. Verify autonomous AI agent credentials in three lines.

PyPI License Python versions


import clawid_sdk_sdk

result = clawid_sdk.verify(token)
if result.valid:
    print(result.agent_id, "owned by", result.tenant_id)

That's it. Three lines. Free forever for verifiers. No key, no contract.

What is this?

ClawID is the trust layer for autonomous AI agents and the services they touch. Every agent carries a Claw — a cryptographically signed credential that binds the agent to its owner, declares the owner's policy (the leash), and produces a tamper-evident receipt of every action. This SDK is what services use to verify a Claw on the way in.

When an AI agent calls your API, you want to know:

  • Who's behind it?result.tenant_id, result.agent_id
  • What did the owner permit?result.leash
  • Can the owner kill it? → yes; result.status reflects current revocation state
  • Is there a record of the attempt? → yes; every check-in lands in a hash-chained audit log on both sides

One round-trip, four answers. Free forever for verifiers.

Install

pip install clawid-sdk

Python 3.10+. Two dependencies: httpx and pyjwt[crypto].

Use

The common case

import clawid_sdk

result = clawid_sdk.verify(token)

if not result.valid:
    return reject(result.status, result.reason)

# Now you know who this is.
print(f"Agent {result.agent_id} owned by {result.tenant_id}")
print(f"Leash: {result.leash}")

When you want to configure things

from clawid_sdk import Claw

claw = Claw(
    hub_url="https://api.holdtheleash.id",   # defaults to this
    jwks_ttl=300,                             # cache the hub's pubkey for 5 minutes
    timeout=5.0,                              # per-request timeout
)

result = claw.verify(token)

Async

result = await clawid_sdk.verify_async(token)

Offline mode (signature + expiry only, no live revocation check)

result = clawid_sdk.verify(token, mode="offline")

Use when latency matters more than catching a revoke within ~30s. The signature check still uses the cached JWKS, so it's accurate; you just won't see a revoke immediately. Suited for very high-throughput verifiers who poll /v1/verify on a schedule out of band.

Web-framework integration

The SDK is framework-agnostic by design. A FastAPI middleware looks like:

from fastapi import FastAPI, HTTPException, Request, Depends

import clawid_sdk

app = FastAPI()

def claw_required(request: Request) -> clawid.VerifyResult:
    auth = request.headers.get("Authorization", "")
    token = auth.removeprefix("Bearer ").strip()
    if not token:
        raise HTTPException(401, "missing Claw")
    result = clawid_sdk.verify(token)
    if not result.valid:
        raise HTTPException(401, f"{result.status.value}: {result.reason}")
    return result

@app.post("/charge")
def charge(amount: float, agent: clawid.VerifyResult = Depends(claw_required)):
    if amount > agent.leash["spend_ceiling"]:
        raise HTTPException(403, "amount exceeds agent's leash")
    return {"agent_id": agent.agent_id, "charged": amount}

What the result tells you

VerifyResult is a dataclass. if result: is shorthand for if result.valid:.

@dataclass
class VerifyResult:
    valid: bool                     # True iff the Claw is currently usable
    status: VerifyStatus            # ACTIVE | REVOKED | EXPIRED | INVALID | UNKNOWN
    reason: str | None              # human-readable reason
    jti: str | None                 # JWT id of this Claw (stable receipt key)
    agent_id: str | None            # who the agent is
    tenant_id: str | None           # who owns the agent
    leash: dict | None              # the owner's policy: spend cap, surfaces, hours...
    agent_pubkey_pem: str | None    # for proof-of-possession on signed actions
    issued_at: int | None
    expires_at: int | None
    payload: dict | None            # raw decoded JWS payload, for custom claims

VerifyStatus:

Status Means
ACTIVE Claw is valid and live; owner has not revoked it.
REVOKED Owner hit the kill switch. Deny the request.
EXPIRED The exp claim is in the past. Agent needs a fresh Claw.
INVALID Signature didn't verify, malformed, unknown issuer, etc.
UNKNOWN Hub returned a status this SDK version doesn't recognize. Treat as INVALID.

What's the leash?

result.leash
# {
#   "spend_ceiling": 50.0,
#   "allowed_surfaces": ["stripe.com", "openai.com"],
#   "active_start_hour": 9,
#   "active_end_hour": 17,
#   "escalate_over": 25.0,
#   "auto_revoke_off_leash": True,
# }

You can use the leash to short-circuit policy decisions on your side — for example, refuse the request if amount > leash["spend_ceiling"] before doing any expensive work.

How the verify path works

                        clawid_sdk.verify(token)
                                │
              ┌─────────────────┴─────────────────┐
              ▼                                   ▼
       Offline (JWS)                       Online (revocation)
       │                                   │
       1. Fetch JWKS from                  1. POST /v1/verify
          /.well-known/jwks.json              with the token
          (cached for jwks_ttl)            2. Hub responds with
       2. Verify EdDSA signature              live revocation status
       3. Check exp / iss / required          + structural detail
          claims

       If signature is bad → INVALID
       If exp in past     → EXPIRED
       Otherwise:                          status: ACTIVE / REVOKED
       online mode → run the right path
       offline mode → return ACTIVE

The hub's signing key is in cloud KMS. We never see your verify traffic if you stay in offline mode after the first JWKS fetch.

Errors

ClawError is raised only for infrastructure problems (the hub is unreachable, JWKS is malformed). Verification failures — bad signature, expired, revoked — never raise; they return a VerifyResult with valid=False and a status that describes what happened.

import clawid_sdk

try:
    result = clawid_sdk.verify(token)
except clawid_sdk.ClawError as e:
    # Hub is down or JWKS is unreachable. Decide based on your trust posture
    # — typically: fail closed.
    return reject_with_503(str(e))

if not result.valid:
    # Bad/expired/revoked Claw. Tell the agent's owner why.
    return reject_with_401(result.status, result.reason)

Vendor onboarding

Verification is permissionless. You don't need a key, an account, or a contract to call clawid_sdk.verify(...). It's free forever. That's the whole network effect.

If you want to appear in the Verified Vendors directory — and get the matching audit-chain visibility on your side of every check-in to your domain — apply at holdtheleash.id/vendors (KYB-gated: entity + domain ownership + live service + signed TOS). Listing is free; promotional placement is a separate paid surface.

Versioning

clawid-sdk follows SemVer. The VerifyResult shape is stable within a major; new optional fields are minor; field removals or behavior changes are major. payload always carries the full decoded JWS for forward-compatibility with new claims.

License

Apache License 2.0. Copyright © 2026 Project Black Box LLC.

Links

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

clawid_sdk-0.3.0.tar.gz (22.6 kB view details)

Uploaded Source

Built Distribution

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

clawid_sdk-0.3.0-py3-none-any.whl (20.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for clawid_sdk-0.3.0.tar.gz
Algorithm Hash digest
SHA256 98db4387d73508e542d0dae5fdda24b885f3f6299bddcc4440e52ec4fa80615a
MD5 bac53a5485cb65af25be1f64fd265988
BLAKE2b-256 704c6c219b280917a6ce1e3a1d1958986f6a700b86c7fdfe6181d9b259d0cc31

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for clawid_sdk-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d2b58b91c380e9ec8ff9bfa2b8962bdaec96b1ad2ac50981c624d5b22b0c5f65
MD5 3e5692de1a5351105f39c3f2c09bcffe
BLAKE2b-256 7b9dc292032c5383e582537c69a006864474ebaba104b08f847cf05e160c1922

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