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

Discover & Trust Remote Agents

Find other A2A agents and decide whether to trust them.

from jacs.a2a_discovery import discover_and_assess_sync

result = discover_and_assess_sync("https://agent.example.com")
if result["allowed"]:
    print(f"Trusted: {result['card']['name']} ({result['trust_level']})")

Add to Your Trust Store

For strict policy, establish native JACS trust from an authenticated agent document and explicit native public key. An Agent Card is self-advertised and cannot create strict identity trust by itself:

from jacs.client import JacsClient
from jacs.a2a import JACSA2AIntegration

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

# Assess a remote agent's trustworthiness
assessment = a2a.assess_remote_agent(remote_card_json)
print(f"JACS registered: {assessment['jacs_registered']}")
print(f"Allowed: {assessment['allowed']}")

# Obtain both values through an authenticated out-of-band channel.
a2a.trust_a2a_agent(remote_native_agent_json, remote_native_public_key_pem)

Async API

from jacs.a2a_discovery import discover_agent, discover_and_assess

card = await discover_agent("https://agent.example.com")
result = await discover_and_assess("https://agent.example.com", policy="verified", client=client)
const { discoverAndAssess } = require('@hai.ai/jacs/a2a-discovery');

const result = await discoverAndAssess('https://agent.example.com');
if (result.allowed) {
  console.log(`Trusted: ${result.card.name} (${result.trustLevel})`);
}

Add to Your Trust Store

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

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

// Assess a remote agent
const assessment = a2a.assessRemoteAgent(remoteCardJson);
console.log(`JACS registered: ${assessment.jacsRegistered}`);
console.log(`Allowed: ${assessment.allowed}`);

// Obtain both through an authenticated out-of-band channel. Passing an
// Agent Card here is rejected.
a2a.trustA2AAgent(remoteNativeAgentDocument, remoteNativePublicKeyPem);

Trust Policies

PolicyBehavior
openAccept all agents without verification
verifiedRequire a valid Agent Card JWS against the same-origin JWKS and a durable jacsId:jacsVersion key pin (default). This is origin/key continuity, not proof of the claimed native JACS identity.
strictRequire an explicitly trusted native JACS root. ES256 cards must also carry the fixed-path compatibility binding, whose native signature, identity/version, binding hash, compatibility JWK/kid, scope, expiry, and signed issuance time all verify. Bindings are accepted for at most seven days after issuedAt (with five minutes of future clock skew), and the verifier durably pins the latest observed hash, kid, and issuedAt; a newer root-signed binding advances the pin and older replays fail closed.

Lifecycle boundary: The absolute seven-day freshness check also applies on first contact, independently of expiresAt. Local discovery generation refreshes an authentic binding after six days under the shared issuance lock, preserving its scopes and explicit expiry. Once a newer native-root-signed binding is observed, JACS also rejects rollback to the old hash/kid. Use an earlier expiresAt when old compatibility keys must stop working sooner, and distribute the refreshed binding promptly after rotation or compromise.

How Trust Flows

1. Discover  -- Fetch /.well-known/agent-card.json from a remote URL
2. Assess    -- Check for JACS extension, verify signatures
3. Decide    -- Trust policy determines if the agent is allowed
4. Trust     -- Optionally add the agent to your local trust store

With open, all agents pass step 3 without identity assurance. With verified, the Agent Card JWS must verify against the same-origin JWKS and the ES256 key must match its durable TOFU pin; this proves origin/key continuity, not native identity. With strict, the native root must be explicitly trusted and its signed compatibility binding must authorize the exact card key, identity, version, scope, and current binding hash.

Next Steps