Skip to main content

Cryptographic identity for AI agents. Ed25519 keypairs, RFC 9421 HTTP Message Signatures, self-resolving keyids.

Project description

envoys

PyPI Python License

Cryptographic identity for AI agents. Ed25519 keypairs, RFC 9421 HTTP Message Signatures, self-resolving keyids.

Sign every HTTP request an agent makes, so the receiver can cryptographically verify which agent sent it — no shared secret, no central broker. Each agent hosts its own public key at a resolvable URL; verifiers fetch it and check the signature.

Python SDK, requires Python 3.10+. Mirrors @envoys/sdk (Node) — same surface, same wire format, byte-compatible against the envoys-rfc9421 §14 test vectors.

Install

pip install envoys

Quick start

Register an agent

import asyncio
from envoys import Envoys, RegisterOptions

async def main():
    client, result = await Envoys.register(RegisterOptions(
        account_key = "ak_...",        # from envoys.me dashboard
        name        = "scout",
    ))
    print(result.address)       # scout@your-handle.envoys.me
    print(result.private_key)   # PEM PKCS8 — store securely, shown once

asyncio.run(main())

Sign an outgoing HTTP request

from_env() reads the agent's credentials from environment variables — populate them from register's result above, or from your envoys.me dashboard.

from envoys import Envoys
import httpx

envoys = Envoys.from_env()   # ENVOYS_AGENT_KEY, ENVOYS_ADDRESS, ENVOYS_PUBLIC_KEY, ENVOYS_PRIVATE_KEY

body    = {"task": "summarize", "url": "https://example.com/doc"}
headers = envoys.sign_request("POST", "/api/task", body)

with httpx.Client() as http:
    r = http.post("https://other-agent.example/api/task",
                  headers={**headers, "Content-Type": "application/json"},
                  json=body)

Verify an incoming request

import asyncio
from envoys import Envoys, VerifyRequestOptions

async def verify(method, path, headers, body):
    result = await Envoys.verify_request(
        method, path, headers, body,
        VerifyRequestOptions(allowlist=["scout@trusted.envoys.me"]),
    )
    if not result.verified:
        return None, result.error
    return result.address, None

The verifier enforces component coverage per spec §5.5: signatures must cover @method and @path, plus content-digest whenever the request has a body — a signature that leaves the body uncovered is rejected even if cryptographically valid (digest-downgrade protection, since 0.2.0).

Optional: bind the signature to the target host (@authority)

headers = envoys.sign_request("POST", "/rpc", body, authority="receiver.example.com")

Covers RFC 9421 @authority so the signature is scoped to one receiving service — relayed to any other host it fails verification. The verifier reconstructs the value from VerifyRequestOptions(authority=...) (set this behind a proxy that rewrites Host) or the request's Host header. Opt-in: verifiers older than 0.2.0 reject signatures covering components they don't reconstruct. Spec v1.6.0 §4.2.

Surface

Mirrors @envoys/sdk one-to-one with Python-idiomatic naming. Methods shown with await are coroutines and must be awaited; the rest are synchronous.

Operation Method
Register a new agent await Envoys.register(opts)
Construct from environment Envoys.from_env()
Key rotation sync await client.sync_keys()
Sign arbitrary payload client.sign(payload)
Sign HTTP request (RFC 9421) client.sign_request(method, path, body, *, tag=None)
Sign Agent Card (JWS EdDSA) client.sign_agent_card(card)
Verify HTTP request await Envoys.verify_request(method, path, headers, body, options)
Verify Agent Card await Envoys.verify_agent_card(jws)
Verify payload signature Envoys.verify(payload, signature, public_key)
Resolve public key by address await Envoys.resolve_public_key(address)
Resolve dual-shape keyid await Envoys.resolve_key_from_keyid(keyid_url)
Resolve did:web await Envoys.resolve_did_web(domain)
Reset pin Envoys.reset_pin(address)
Clear caches (testing) Envoys.clear_pins(), Envoys.clear_replay_cache(), Envoys.clear_key_cache()

Spec & conformance

The wire format is published at https://envoys.me/specs/signature/v1. Every operation in this SDK byte-matches the §14 reference vectors at envoys-rfc9421, and cross-implementation interop is verified bidirectionally against @envoys/sdk (Node) — Python signs / Node verifies, and Node signs / Python verifies. The SDK also resolves W3C did:web Documents in both Ed25519VerificationKey2020 and JsonWebKey2020 shapes.

License

Apache-2.0

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

envoys-0.2.0.tar.gz (24.5 kB view details)

Uploaded Source

Built Distribution

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

envoys-0.2.0-py3-none-any.whl (18.5 kB view details)

Uploaded Python 3

File details

Details for the file envoys-0.2.0.tar.gz.

File metadata

  • Download URL: envoys-0.2.0.tar.gz
  • Upload date:
  • Size: 24.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for envoys-0.2.0.tar.gz
Algorithm Hash digest
SHA256 bb7b4a9b302552accb0b2b8b7ee5aa8ed378fc2a397c04509db338f064b37cd2
MD5 b868f717c7e8d2612dd7a4e65ca8b2c5
BLAKE2b-256 a5ac2316bcfa6ba574fedbb47c532353e44071baaf626f00f75b7ca9aae40526

See more details on using hashes here.

File details

Details for the file envoys-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: envoys-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 18.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for envoys-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0452904a407f6ae98fc7360304f4245ea4aceac8cbd12cd9c9b68c7a7a712c26
MD5 c6f11cf6332c09699ed815ed3e99a306
BLAKE2b-256 00162b112623704c5712f5306e0d96f42a9ffae1839b6ebb314e227920ce8733

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