Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Native library reference. Extended CLI examples use jacs-compat. This source reference can include unreleased changes; see the package guide for installation and MCP profiles for available tools.

Exchange Signed Artifacts

Sign artifacts with cryptographic provenance and verify artifacts from other agents. Node.js snippets run inside an async function. For multi-agent examples, create separate clients/configurations and independently authenticate each signer's public evidence and configure the verifier's key resolver before verification. Native artifact verification uses a trust-store enrollment for v2 artifacts signed by the exact enrolled agent_id:version; otherwise it uses its local public-key cache or opt-in registry or DNS/HTTPS key discovery. See cross-agent setup.

Sign and Verify

from jacs.client import JacsClient

client = JacsClient.quickstart(name="my-agent", domain="my-agent.example.com")

# Sign an artifact
signed = client.sign_artifact({"action": "classify", "input": "data"}, "artifact")

# Verify it (with trust assessment)
a2a = client.get_a2a()
result = a2a.verify_wrapped_artifact(signed, assess_trust=True)
print(f"Valid: {result['valid']}, Allowed: {result['trust']['allowed']}")

Chain of Custody

When multiple agents process data in sequence, link artifacts into a verifiable chain:

# Agent A signs step 1
step1 = client_a.sign_artifact({"step": 1, "data": "raw"}, "artifact")

# Agent B signs step 2, referencing step 1 as parent
step2 = client_b.sign_artifact(
    {"step": 2, "data": "processed"},
    "artifact",
    parent_signatures=[step1],
)

# Verify the full chain
result = a2a.verify_wrapped_artifact(step2)
assert result["valid"]
assert result["parent_signatures_valid"]

Build an Audit Trail

chain = a2a.create_chain_of_custody([step1, step2])
# Metadata only: chainOfCustody, created, totalArtifacts.
# This helper does not verify signatures, ordering or validity.

Sign and Verify

const { JacsClient } = require('@hai.ai/jacs/client');

const client = await JacsClient.quickstart({
  name: 'my-agent',
  domain: 'my-agent.example.com',
});

// Sign an artifact
const signed = await client.signArtifact({ action: 'classify', input: 'data' }, 'task');

// Verify it
const a2a = client.getA2A();
const result = a2a.verifyWrappedArtifact(signed);
console.log(`Valid: ${result.valid}`);

Chain of Custody

// Agent A signs step 1
const step1 = await clientA.signArtifact({ step: 1, data: 'raw' }, 'message');

// Agent B signs step 2, referencing step 1
const step2 = await clientB.signArtifact(
  { step: 2, data: 'processed' }, 'message', [step1],
);

// Verify the full chain
const result = a2a.verifyWrappedArtifact(step2);
console.log(`Chain valid: ${result.valid}`);
console.log(`Parents valid: ${result.parentSignaturesValid}`);

Artifact Types

The artifact_type parameter labels the payload for downstream processing:

TypeUse Case
taskTask assignments, work requests
messageInter-agent messages
resultTask results, responses

You can use any string -- these are conventions, not enforced types.

What Gets Signed

Every signed artifact includes:

FieldDescription
jacsIdUnique document ID
jacsSignatureSigner ID, algorithm, timestamp, and base64 signature
jacsSha256Content hash for integrity verification
jacsTypea2a- followed by the caller's artifact type label
jacsParentSignaturesParent artifacts for chain of custody (if any)
a2aArtifactThe original artifact data

Extract a2aArtifact only after the required signature and trust checks. Discarding the envelope also discards its provenance.

Next Steps