Skip to main content

JACS Python Library

Cryptographic identity, signing, and verification for AI agents from Python.

This source version requires Python 3.11–3.14, including optional integrations. Published 0.15.0 wheels support Python 3.10–3.14; use the source requirement when building this checkout.

Published 0.15.0: jacs remains a supported native Python library. Wheel platforms, installed-package checks and provenance are recorded in the release inventory. Its separate native workspace remains buildable through the root Makefile and CI.

python -m pip install jacs==0.15.0

Supported wheels need no Rust toolchain.

First use of the jacs command

The first jacs command downloads the matching CLI release, verifies SHA-256, and caches it by version and platform. Importing or using the library downloads nothing. No musl CLI archive is published; unsupported platforms or verification failures exit nonzero. The fallback is cargo install jacs-cli.

If the Python shim shadows Cargo's binary, invoke ~/.cargo/bin/jacs directly (or %USERPROFILE%\.cargo\bin\jacs.exe on Windows). With CARGO_HOME set, use its bin directory instead.

Full documentation | Python Quick Start

Quick start

import jacs.simple as jacs

info = jacs.quickstart(name="my-agent", domain="my-agent.example.com")
signed = jacs.sign_message({"action": "approve", "amount": 100})
result = jacs.verify(signed.raw)
print(f"Valid: {result.valid}, Signer: {result.signer_id}")

quickstart() creates a persistent agent with encrypted keys on disk. If jacs.config.json exists, it loads it. Preserve the password through your host secret source or keychain for later processes; an automatically generated password is otherwise retained only in-process. See the password guide.

Core operations

Operation Description
quickstart(name, domain) Create or load a persistent agent
load() Load an existing agent from config
sign_message() Sign JSON-serializable data
sign_file() Sign a file with optional embedding
verify() Verify a signed document
verify_standalone() Verify without loading an agent
create_agreement_v2() Create a standalone Agreement v2 document
sign_agreement_v2() Sign as signer, witness, or notary
verify_agreement_v2() Inspect Agreement v2 hashes, signatures and claimed status
export_agent() Export agent JSON for sharing
audit() Run a security audit

Public human-approved document verification

The wheel build profile enables human-approval-vendored: the existing native WebAuthn verifier with OpenSSL compiled into the extension, without a separate OpenSSL installation. maturin develop uses this same profile. This configures new builds; it does not claim that an older published wheel has the method. Release gates check the installed artifact and reject external OpenSSL linkage. Browser WASM does not provide this verifier.

from jacs import SimpleAgent

report = SimpleAgent.verify_human_approved_document(
    bundle_json, expected_json, authority_json, provenance_json
)

This static method needs no agent, signing key, configuration, or network lookup. All four arguments are JSON strings. Read stored public evidence into bundle_json; select the expected human/action/credential and the two public key pins from your application's trusted state, not from the bundle. The complete report is a dict. Success confirms retained proof and document integrity, not permission to execute now: current remains not_evaluated. Live authorization, revocation and one-use checks stay with the relying application.

Request authentication and signed events

The instance-based SimpleAgent exposes the transport protocol helpers. Build the header from the exact request values that will be sent:

import json
from jacs import SimpleAgent

agent, _ = SimpleAgent.ephemeral()  # default pq2025
body = '{"action":"approve"}'
authorization = agent.build_request_auth_header(
    "POST",
    "https://api.example.com/v1/jobs?mode=strict",
    body,
    "jobs-api",
)
assert authorization.startswith("JACS v2.")

envelope = agent.sign_response(json.dumps({"decision": "allow"}))
signer_id = json.loads(envelope)["jacsSignature"]["agentID"]
server_keys = json.dumps({signer_id: agent.get_public_key_pem()})
verified = json.loads(agent.unwrap_signed_event(envelope, server_keys))
assert verified["verified"] is True
assert verified["data"]["decision"] == "allow"

build_request_auth_header() accepts bytes for arbitrary request bodies or str (encoded as UTF-8), and binds the exact bytes with method, absolute URL including query, audience, signer/key, issue time, and nonce. Do not serialize the body again after building the header. sign_response() emits a 2.0.0 envelope whose jacs-response-v2 signature covers both payload and metadata. unwrap_signed_event() is fail-closed: plain events, legacy payload-only envelopes, unknown signers, and mutations raise instead of returning data.

For multi-replica consumers, await unwrap_signed_event_with_replay_store(agent, envelope, server_keys, store) requires an application-owned shared atomic replay store implementing the Python store protocol. It fails closed on duplicates, expiry or store failure. See replay-store deployment and the signed-event contract before releasing verified payloads.

The server_keys object is a trust decision, not discovery: each key must be pinned or resolved under the application's configured policy. Successful verification proves possession of that key; it does not independently prove a person, organization, domain, or other real-world identity.

The old no-argument build_auth_header() remains available for source compatibility and emits a WARN because it does not bind the request. Migrate clients and servers together to JACS v2; strict deployments can reject the legacy method with JACS_REJECT_UNBOUND_AUTH_HEADER=true.

Text and image provenance

Python exposes the same inline text and image signing surface as the CLI:

import jacs.simple as jacs
from jacs import MissingSignatureError

jacs.load("./jacs.config.json")

# Markdown/text: append and verify an inline signature block.
jacs.sign_text("README.md")
text = jacs.verify_text("README.md")
print(text.status)  # 'signed' | 'missing_signature' | 'malformed'

try:
    jacs.verify_text("README.md", strict=True)
except MissingSignatureError:
    print("not signed")

jacs.verify_text("README.md", key_dir="./trusted-keys/")

# Images: embed and verify a signature in PNG, JPEG, or WebP metadata.
jacs.sign_image("photo.png", "signed.png")
image = jacs.verify_image("signed.png")
print(image.status)  # 'valid'

payload = jacs.extract_media_signature("signed.png")

The same methods are available on the instance-based JacsClient for multi-agent processes. These signatures prove that an agent signed specific canonical bytes at its claimed time; they do not prove first creation or legal ownership.

Verify without an agent

result = jacs.verify_standalone(signed_json, key_directory="./keys")

JACS uses a shared signed-document format across bindings. See the release evidence for installed-consumer checks and their limits.

Agreement v2

Use Agreement v2 to inspect native compatibility agreement documents:

from jacs import SimpleAgent

agent, info = SimpleAgent.ephemeral()  # default pq2025
agent_id = info["agent_id"]

agreement = agent.create_agreement_v2({
    "title": "Refund approval",
    "description": "Approval for a bounded refund.",
    "terms": "Refund up to $25 for order 123.",
    "status": "proposed",
    "parties": [{"agentId": agent_id, "agentType": "ai", "role": "signer"}],
    "signaturePolicy": {"partyQuorum": "all", "witnessRequired": 0, "notaryRequired": 0},
    "controllers": [agent_id],
})

signed = agent.sign_agreement_v2(agreement, "signer")
report = agent.verify_agreement_v2(signed)
assert report["mathematicalChecksValid"]
assert report["status"] == "final"
assert report["policyAccepted"] is False

Agreement v2 inspection checks signatures and claimed status; valid and policyAccepted remain false because this is not application consent-policy acceptance. Do not authorize an action from these mathematical checks alone.

The same methods are available on jacs.simple after quickstart() or load().

Verifying another agent's agreement signature requires that agent's public key, so distinct agents must share a data_directory or exchange public keys; ephemeral agents verify only their own signatures.

The older create_agreement() / sign_agreement() / check_agreement() methods remain for simple jacsAgreement sidecars on existing documents.

Framework adapters

pip install "jacs[langchain,langgraph]"  # LangChain / LangGraph
pip install jacs[fastapi]      # FastAPI / Starlette
pip install jacs[anthropic]    # Anthropic / Claude SDK
pip install jacs[a2a]          # A2A protocol
pip install jacs[all]          # Everything

Current-source A2A routes serve five direct-root discovery documents, or six for explicit ES256. Verify the card/JWKS and any root-signed compatibility binding under your trust policy; discovery and cache freshness do not establish authority. The guide covers renewal and expiry. New source behavior is not publication evidence.

Instance-based API

For multiple agents in one process:

from jacs.client import JacsClient

client = JacsClient.quickstart(name="my-agent", domain="example.com")
signed = client.sign_message({"action": "approve"})

See the API reference, framework adapters, and native development guide.

Metadata

Release files for jacs 0.16.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jacs 0.16.0
File Size Uploaded Provenance Actions
jacs-0.16.0.tar.gz 1.8 MB With provenance Details for jacs-0.16.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for jacs 0.16.0
File Actions
jacs-0.16.0-cp311-abi3-musllinux_1_2_x86_64.whl CPython 3.11 abi3 Linux musl 1.2+ x86-64 Details for jacs-0.16.0-cp311-abi3-musllinux_1_2_x86_64.whl
jacs-0.16.0-cp311-abi3-manylinux_2_28_x86_64.whl CPython 3.11 abi3 Linux glibc 2.28+ x86-64 Details for jacs-0.16.0-cp311-abi3-manylinux_2_28_x86_64.whl
jacs-0.16.0-cp311-abi3-manylinux_2_28_aarch64.whl CPython 3.11 abi3 Linux glibc 2.28+ ARM64 Details for jacs-0.16.0-cp311-abi3-manylinux_2_28_aarch64.whl
jacs-0.16.0-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details for jacs-0.16.0-cp311-abi3-macosx_11_0_arm64.whl
jacs-0.16.0-cp311-abi3-macosx_10_12_x86_64.whl CPython 3.11 abi3 macOS 10.12+ x86-64 Details for jacs-0.16.0-cp311-abi3-macosx_10_12_x86_64.whl

Total release size: 64.6 MB

Release files / jacs-0.16.0.tar.gz

Download URL jacs-0.16.0.tar.gz
Size 1.8 MB
Tags Source
SHA-256 checksum
How to use checksums
f8d1cf260a3ee887e0cbb84d389e1d52a00f16b847b6ee4cb14d2f2b01492d85
BLAKE2b-256 checksum
How to use checksums
ca5b0ebca57c6361cc8b918520eb9c3a0a47025d60b29e4f6e4b41819817b4ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Release files / jacs-0.16.0-cp311-abi3-musllinux_1_2_x86_64.whl

Download URL jacs-0.16.0-cp311-abi3-musllinux_1_2_x86_64.whl
Size 11.9 MB
Tags CPython 3.11 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
7a3edad07d105a1c7b1915393ea1857c78bf90d3691d78c0a6f92629de84ee60
BLAKE2b-256 checksum
How to use checksums
b60b7335f366aa5bfddcd35eb0a7b8ecfe0fc02eff1ea17e1de1a2bd8d2ceaec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Release files / jacs-0.16.0-cp311-abi3-manylinux_2_28_x86_64.whl

Download URL jacs-0.16.0-cp311-abi3-manylinux_2_28_x86_64.whl
Size 13.3 MB
Tags CPython 3.11 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
fdf3e9f6d929dc1a6f810130c73073c5ad1afc19fd80afc9843fb7ff737e6f4c
BLAKE2b-256 checksum
How to use checksums
cba2c3725ddc75bad016982e0e298cb7563bfe3d982ac9cb173dfd7b9979640a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Release files / jacs-0.16.0-cp311-abi3-manylinux_2_28_aarch64.whl

Download URL jacs-0.16.0-cp311-abi3-manylinux_2_28_aarch64.whl
Size 13.5 MB
Tags CPython 3.11 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
a8e2170089c852b4ce7f201ecd0fe77dc2f4a71f9268d3829f275e000521496a
BLAKE2b-256 checksum
How to use checksums
22338519084dda5925f42765cf1b663d04289cc98ef0d0ae8abb06a71ead9201
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Release files / jacs-0.16.0-cp311-abi3-macosx_11_0_arm64.whl

Download URL jacs-0.16.0-cp311-abi3-macosx_11_0_arm64.whl
Size 11.9 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e0144d144c1ac7af1c9c2d0d9d9f0656d7109dd9cc5e237c9daa1facc4242a01
BLAKE2b-256 checksum
How to use checksums
b553c662113edc12575ed65834498dfc0c25faa5a0f59d75c2b57a707c657ade
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Release files / jacs-0.16.0-cp311-abi3-macosx_10_12_x86_64.whl

Download URL jacs-0.16.0-cp311-abi3-macosx_10_12_x86_64.whl
Size 12.2 MB
Tags CPython 3.11 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
62e627303572d34b0e631f0682f5a85a1c8e87e4da279595d3a2a1d62f77bb41
BLAKE2b-256 checksum
How to use checksums
fe6f425f31417938ddf7bdb0f0b3bcad33d9554eef8efaf7735219c97c02ec0d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Security for jacs 0.16.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for jacs-0.16.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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