Skip to main content

a2a-protocol-core

License: Apache 2.0

The open, deterministic protocol core of the DNS of Money agent-to-agent (A2A) payment surface — the dependency-light layer external AI agents adopt to resolve, hash, and initiate pay: payments.

The intelligence lives in the calling agent. This package serves deterministic, inspectable primitives — no rail selection, no scoring, no model anywhere in the money path.

Install

pip install a2a-protocol-core

Runtime deps are intentionally minimal: pydantic and requests.

What's in here

Module A2A ref Purpose
addressing FAS-1 pay: URI grammar + validation (is_valid_pay_uri)
semantic_normalizer A2A-009 collapse synonym verbs → canonical action codes
canonical_hash A2A-008 metadata- & vocabulary-stable payment-intent hash
schemas A2A-041 payment-hook request/response wire models
client A2A-041 A2APaymentHookClient over /v1/a2a/*
x402_pay x402 one-call pay: XRP on XRPL ([xrpl]) / USDC on Algorand ([algorand])
screen x402 paid counterparty screen — "screen before you pay"
attestation_verify did:web verify the attestation's Ed25519 proof ([verify])

Quick start

from a2a_protocol_core import (
    A2APaymentHookClient,
    compute_canonical_hash,
    normalize_message,
)

# Your agent describes intent however it likes...
intent = {"action": "send", "amount": "2.50", "currency": "USD", "alias": "pay:agent.compute"}

# ...which collapses to a stable hash regardless of wording ("send" == "transfer" == "pay").
semantic_hash = compute_canonical_hash(normalize_message(intent))

client = A2APaymentHookClient(base_url="https://api.dnsofmoney.com")
result = client.trigger(
    job_id="job-001",
    provider_pay_address="pay:agent.compute",
    requester_pay_address="pay:vendor.alpha",
    amount="2.50",
    currency="USD",
    semantic_hash=semantic_hash,
)
print(result.settlement_result.status, result.iso_message_ref)

See examples/trigger_payment_hook.py.

Pay a pay: alias in one call (non-custodial)

Resolve the price, pay from your own wallet, and get back a signed resolve/verify/OFAC-screen attestation — one function, and your seed never leaves your process:

pip install "a2a-protocol-core[xrpl]"
from a2a_protocol_core import pay_alias_xrp

result = pay_alias_xrp(
    base_url="https://api.dnsofmoney.com",
    alias="pay:vendor.alpha",
    amount_xrp="0.10",
    seed="s...",             # YOUR XRPL wallet seed — signs locally, never transmitted
    api_key="fas_live_...",  # attributes the settle leg
)
print(result.tx_hash, result.summary.verdict)   # e.g. "A1B2…", "CLEAR"

Already settled the payment through your own wallet stack (or a Coinbase Agentic Wallet)? Skip the signing and just fetch the attestation — no [xrpl] extra:

from a2a_protocol_core import attest_settled_payment

result = attest_settled_payment(
    base_url="https://api.dnsofmoney.com",
    alias="pay:vendor.alpha",
    amount_xrp="0.10",
    tx_hash="A1B2C3...",     # your already-validated XRPL tx
    api_key="fas_live_...",
)

DNS of Money verifies an already-settled transaction and returns metadata — it never holds your keys or your funds.

Pay in USDC on Algorand (the priced endpoints)

DNS of Money's own paid endpoints declare their price in USDC on Algorand. pay_alias_usdc_algorand (or the rail-dispatching pay_alias) signs the USDC transfer leg locally via the official x402 client mechanisms — omit the amount and the server quotes its declared, enforced price:

pip install "a2a-protocol-core[algorand]"
from a2a_protocol_core import pay_alias_usdc_algorand

result = pay_alias_usdc_algorand(
    base_url="https://api.dnsofmoney.com",
    alias="pay:dnsofmoney",
    api_key="fas_live_...",
    mnemonic="...your 25-word Algorand mnemonic...",  # signs locally, never sent
)
print(result.tx_hash, result.summary.verdict)

Screen before you pay

Pay the screening fee, get an OFAC + resolution attestation about a caller-named target — a pay: alias or a raw any-chain address — before you send it money:

from a2a_protocol_core import screen

result = screen(
    base_url="https://api.dnsofmoney.com",
    target="pay:vendor.alpha",
    api_key="fas_live_...",
    algorand_mnemonic="...",   # fee is USDC on Algorand (server-priced)
    verify=True,               # also check the attestation signature
)
if result.verdict == "CLEAR":
    ...  # proceed to pay the vendor

Verify the attestation yourself

Attestations are W3C Verifiable Credentials signed eddsa-jcs-2022 by a did:web issuer. verify_attestation resolves the issuer's DID document, enforces assertionMethod authorization, and checks the Ed25519 signature — so the proof chain ends at your process, not at TLS:

pip install "a2a-protocol-core[verify]"
from a2a_protocol_core import verify_attestation

v = verify_attestation(result.attestation, expected_issuer="did:web:dnsofmoney.com")
assert v.verified

An unsigned attestation fails verification by design.

Why canonical hashing?

Two agents describing the same payment with different words ("send" vs "transfer") or different session/trace metadata must produce the same intent fingerprint. compute_canonical_hash excludes non-semantic noise (session/request/trace ids, timestamps, idempotency keys, memos) and normalizes the action verb, so the hash captures what is being paid — not how it was phrased. That fingerprint binds an agent's intent to a settlement without trusting free text.

Design constraints

  • Deterministic only. Nothing here selects or scores a rail.
  • Off the money path. The hash and client describe and carry intent; the deterministic core (server-side) resolves, generates ISO 20022, and settles.
  • Dependency-light. Safe to embed in an agent runtime.

Development

pip install -e ".[dev]"
pytest
ruff check src tests

License

Apache-2.0 — permissive with an explicit patent grant. See LICENSE.

Download files

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

Source Distribution

a2a_protocol_core-0.3.0.tar.gz (40.7 kB view details)

Uploaded Source

Built Distribution

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

a2a_protocol_core-0.3.0-py3-none-any.whl (29.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: a2a_protocol_core-0.3.0.tar.gz
  • Upload date:
  • Size: 40.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for a2a_protocol_core-0.3.0.tar.gz
Algorithm Hash digest
SHA256 72295a67fa50883855873337bada788b50bff2b24612886f1a2c9c74321b7be0
MD5 55672e01e0593acab2eefd2d7fde77e8
BLAKE2b-256 309cf26c7325fbf2a7a90889ffad2dcf8de731eac4902cf5389622f1b689ef53

See more details on using hashes here.

Provenance

The following attestation bundles were made for a2a_protocol_core-0.3.0.tar.gz:

Publisher: publish.yml on dnsofmoney/a2a-protocol-core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

File hashes

Hashes for a2a_protocol_core-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c5e296dfaf9521fcbe63d3150eeb23f3944fdf1341e544b9d773d629703fad4c
MD5 042d55adc4d9f3a6f9d931d98b89817b
BLAKE2b-256 c3851d360d1f92de9236334d0461cf5adc4fdb14a8f1774b6d6166e5ee8d0305

See more details on using hashes here.

Provenance

The following attestation bundles were made for a2a_protocol_core-0.3.0-py3-none-any.whl:

Publisher: publish.yml on dnsofmoney/a2a-protocol-core

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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