a2aproject / a2aproject/A2A

trust.signals[] extension: consolidated signal type specification

Aberta
#1,628 124 comentários 0 reações 0 responsáveis Ver no GitHub
Linguagem predominante
Shell
Estrelas
25.7k
Forks
2.6k
Merge médio
3d 6h
PRs com merge (30d)
16

Descrição

## Context

This consolidates the `trust.signals[]` schema work from [#1501](https://github.com/a2aproject/A2A/issues/1501) (closed, 26 comments) into a standalone spec proposal. The discussion converged on a 5-signal taxonomy for the AgentCard trust extension, with a shared ECDSA/JWKS verification pattern adopted across all signal types.

**Co-authors:** @douglasborthwick-crypto (`onchain_credentials`, `onchain_activity`), @The-Nexus-Guard (`vouch_chain`), @imran-siddique (`behavioral`, overall structure), @lorenzocipriani-huawei (trust registry design), @aeoess (`governance_attestation`)

## Problem

A2A agents can discover each other via AgentCards, but have no standardized way to assess trust before delegation. This creates three gaps:

1. **Cold start** — new agents with no interaction history cannot be evaluated
2. **No verifiability** — self-reported trust scores are gameable (Sybil attacks, botnets)
3. **No composability** — different trust signals (behavioral, social, on-chain) have no shared schema for consuming agents to weight and combine

## Proposed Solution: `trust.signals[]` Array

Extend the AgentCard with a `trust.signals[]` array containing independently verifiable signals from multiple providers. Each signal type solves a different phase of the trust lifecycle:

| Signal Type | Proves | Cold-Start? | Provider Example |
|---|---|---|---|
| `onchain_credentials` | Third-party attestations on-chain (KYC, membership) | Yes | [InsumerAPI](https://insumermodel.com/developers/) |
| `onchain_activity` | Observable holdings across 7 dimensions | Yes | [InsumerAPI](https://insumermodel.com/developers/) |
| `vouch_chain` | Social trust graph with domain-scoped scores | Requires existing trusted agent | [AIP](https://github.com/The-Nexus-Guard/aip) |
| `behavioral` | Runtime performance (success rate, policy compliance) | Requires interaction history | Agent-SRE |
| `governance_attestation` | Prospective authorization — declared scope + evaluator verdict | Yes | [APS](https://gateway.aeoess.com) |

### Shared Verification Pattern

All 5 signal types use the same verification model: ECDSA (or EdDSA) signatures checked against the key set the consuming agent already trusts for that provider.

```json
{
"type": "...",
"provider": {
"name": "...",
"jwks": "https://provider.example/.well-known/jwks.json",
"kid": "provider-key-v1",
"sig": "base64-signature-over-signal-payload"
}
}
```

A consuming agent verifies any signal type with the same flow:
1. Take the provider's key set from the consuming agent's own configuration (a JWKS endpoint it configured, a key it ships, or another source it controls). The key set is the trust boundary. `provider.jwks` tells a consumer where a provider publishes keys; it is not an instruction to fetch the key that verifies this signal.
2. Select the key matching `provider.kid` within that set. A `kid` that resolves to no key in it fails closed; it is not a reason to fetch or try another key.
3. Verify `provider.sig` over the signal payload using the key's declared `alg` (ES256 or EdDSA)
4. Check `expiresAt` for freshness

This eliminates the self-asserted vs. third-party distinction: the signature binds the payload to a key in a set the consumer already trusts, regardless of who includes the signal in their AgentCard. A consumer configures a provider's key set once and verifies every later signal offline. This pattern was adopted across all signal types during the #1501 discussion, after identifying that HMAC-SHA256 doesn't work for first-contact scenarios where no shared secret exists.

---

## Signal Type: `onchain_credentials`

Verifies third-party attestations stored on-chain. Strongest cold-start signal for agents with on-chain identity.

Supported credential types:
- **`eas_attestation`** — Ethereum Attestation Service (e.g., Coinbase Verified Account on Base)
- **`nft_ownership`** — NFT holdings including soulbound tokens
- **`farcaster_id`** — Farcaster social identity registration (Optimism, chain 10)

```json
{
"type": "onchain_credentials",
"binding": {
"method": "did:pkh",
"did": "did:pkh:eip155:8453:0xabc...",
"wallet": "0xabc..."
},
"credentials": [
{
"credentialType": "eas_attestation",
"chainId": 8453,
"label": "Coinbase Verified Account",
"met": true,
"evaluatedCondition": {
"type": "eas_attestation",
"chainId": 8453,
"operator": "valid",
"schemaId": "0xf8b05c79...",
"attester": "0x357458739F..."
},
"conditionHash": "0x99ba3f...",
"blockNumber": "0x290df9c",
"blockTimestamp": "2026-03-07T12:37:47.000Z"
}
],
"attestedAt": "2026-03-07T12:37:47.495Z",
"expiresAt": "2026-03-07T13:07:47.495Z",
"provider": {
"name": "insumerapi",
"jwks": "https://insumermodel.com/.well-known/jwks.json",
"kid": "insumer-attest-v1",
"sig": "..."
}
}
```

Results are boolean (`met: true/false`) — no personal data or raw values exposed. Each result includes:
- `evaluatedCondition` — the canonical condition that was checked (enables audit)
- `conditionHash` — SHA-256 of the canonical condition (tamper detection)
- `blockNumber`/`blockTimestamp` — block-level anchoring at time of check

---

## Signal Type: `onchain_activity`

Wallet trust profile across **9 dimensions**, each containing boolean checks against curated condition sets. Returns per-dimension pass/fail counts, not balances. Five dimensions are evaluated for any EVM wallet; four more activate when the corresponding non-EVM wallet address is supplied.

| Dimension | What it checks | Coverage | Checks |
|---|---|---|---|
| `stablecoins` | USDC + USDT holdings across major networks | 21 chains (16 USDC + 10 USDT, overlapping) | 26 |
| `institutional_stablecoins` | Regulated and tokenised-fund stablecoins | EURCV + USDCV (Ethereum, Solana), EURCV (XRPL), USDC + BENJI (Stellar), USDC (Sui) | 8 |
| `governance` | Governance token holdings | UNI, AAVE (Ethereum), ARB (Arbitrum), OP (Optimism) | 4 |
| `nfts` | Blue-chip NFT ownership | BAYC, Pudgy Penguins, Wrapped CryptoPunks (Ethereum) | 3 |
| `staking` | Staked ETH positions | stETH (Lido), rETH (Rocket Pool), cbETH (Coinbase) | 3 |
| `solana` | SPL token holdings | USDC on Solana | 1 |
| `xrpl` | Trust line token holdings | RLUSD, USDC on XRPL | 2 |
| `bitcoin` | Native BTC balance | Bitcoin (P2PKH, P2SH, bech32, Taproot) | 1 |
| `tron` | Native TRX and TRC-20 holdings | USDT-TRC20 | 1 |

Base profile: 44 checks across 5 dimensions. Full profile with all non-EVM wallets supplied: 49 checks across 9 dimensions, spanning 27 chains.

```json
{
"type": "onchain_activity",
"binding": {
"method": "did:pkh",
"did": "did:pkh:eip155:1:0xabc...",
"wallet": "0xabc..."
},
"dimensions": {
"stablecoins": {
"checks": [
{
"label": "USDC on Ethereum",
"chainId": 1,
"met": true,
"evaluatedCondition": { "type": "token_balance", "chainId": 1, "contractAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "operator": "gt", "threshold": 0, "decimals": 6 },
"conditionHash": "0x...",
"blockNumber": "0x...",
"blockTimestamp": "2026-03-13T12:00:00.000Z"
}
],
"passCount": 14,
"failCount": 12,
"total": 26
},
"institutional_stablecoins": { "passCount": 1, "failCount": 7, "total": 8 },
"governance": { "passCount": 3, "failCount": 1, "total": 4 },
"nfts": { "passCount": 1, "failCount": 2, "total": 3 },
"staking": { "passCount": 1, "failCount": 2, "total": 3 },
"solana": { "passCount": 0, "failCount": 1, "total": 1 },
"xrpl": { "passCount": 0, "failCount": 2, "total": 2 },
"bitcoin": { "passCount": 1, "failCount": 0, "total": 1 },
"tron": { "passCount": 1, "failCount": 0, "total": 1 }
},
"conditionSetVersion": "v1",
"summary": {
"totalChecks": 49,
"totalPassed": 22,
"totalFailed": 27,
"dimensionsWithActivity": 7,
"dimensionsChecked": 9
},
"profiledAt": "2026-03-13T12:00:00.000Z",
"expiresAt": "2026-03-13T12:30:00.000Z",
"provider": {
"name": "insumerapi",
"jwks": "https://insumermodel.com/.well-known/jwks.json",
"kid": "insumer-attest-v1",
"sig": "..."
}
}
```

`conditionSetVersion` identifies the curated condition set that produced the profile. Together with each check's `evaluatedCondition`, `conditionHash` and block anchor, it is what lets a verifier reproduce the profile independently.

Other dimensions follow the same per-check structure (each check includes `evaluatedCondition`, `conditionHash`, and block-level anchoring); `stablecoins` shown in full for illustration.

Each individual check carries block-level anchoring (`blockNumber`/`blockTimestamp` for EVM, `ledgerIndex`/`ledgerHash` for XRPL). XRPL trust line checks also include `trustLineState: { frozen }` — frozen trust lines fail even with a positive balance, preventing false positives from illiquid positions.

A consuming agent can weight dimensions per task — a DeFi delegation cares about governance tokens; an NFT marketplace task cares about collection holdings; a payments task cares about stablecoins and staking.

---

## Signal Type: `vouch_chain`

*Section by @The-Nexus-Guard — schema from [#1501 comment](https://github.com/a2aproject/A2A/issues/1501#issuecomment-2693822779)*

Cryptographic vouch chains with domain-scoped scores, path depth, and attenuation model disclosure. Key design decisions:

- **Domain-scoped scores** — trust is not one number. An agent trusted for code review may not be trusted for financial operations.
- **Attenuation model disclosure** — `multiplicative` vs `additive` vs `decay` lets consumers understand what the score means.
- **Path depth** — how many hops from the nearest trusted root. Depth 1 is stronger than depth 4.
- **Voucher DIDs** — consuming agents can independently verify each vouch by resolving the voucher's DID.

Reference implementation: [AIP](https://github.com/The-Nexus-Guard/aip).

---

## Signal Type: `behavioral`

*Section by @imran-siddique — schema from [#1501 comment](https://github.com/a2aproject/A2A/issues/1501#issuecomment-2697831204)*

Behavioral trust from interaction history — task success rate, policy violations, dimensional breakdown (reliability, safety, efficiency, governance compliance). Updated during #1501 to use ECDSA/JWKS verification (replacing HMAC-SHA256) for consistency with the shared verification pattern.

---

## Signal Type: `governance_attestation`

*Section by @aeoess — reference schema on [insumer-examples #1](https://github.com/douglasborthwick-crypto/insumer-examples/issues/1)*

Prospective authorization attestation — verifies what an agent is **permitted to do** and whether an independent evaluator has verified the boundary holds at execution time. This is distinct from the other four signal types, which are retrospective (what the agent has held, done, or earned).

Two-signature structure:
- **Declared scope** — agent signature over claimed capabilities (intent)
- **Verified scope** — evaluator signature over the verdict at execution time (decision)
- Both signatures independently verifiable via the issuer JWKS

The evaluator is the trust anchor, not the agent. This distinguishes `governance_attestation` from `onchain_credentials` (which prove identity, not authorization) and `behavioral` (which proves history, not active permission).

Reference implementation: [APS gateway](https://gateway.aeoess.com) publishes `active_constraints` (delegation scope, spend limit, spend used) in a signed JWS, served from `GET /api/v1/public/trust/{agentId}`. JWKS at `https://gateway.aeoess.com/.well-known/jwks.json` (Ed25519, `kid: gateway-v1`, `alg: EdDSA`).

Independent implementations publishing the same signal type are welcome — post JWKS URL, `kid`, and a sample signed payload on insumer-examples #1 for the same verification pass applied to the other 6 verified issuers. Two or more implementations of `governance_attestation` with distinct vocabularies (e.g., APS delegation, MoltGuard AAE) strengthen the type as long as the schema contract holds.

---

## Identity Binding

Before evaluating on-chain signals, the consuming agent must establish that the presenting agent controls the wallet being attested. Three methods supported, in decreasing order of trust:

1. **`did:pkh`** — DID derived directly from the blockchain account per the [did:pkh method spec](https://github.com/w3c-ccg/did-pkh/blob/main/did-pkh-method-draft.md). No separate binding proof needed. Recommended for wallet-native agents.
2. **`eip191`** — Wallet signs a challenge proving ownership. For agents using `did:key`, `did:web`, `did:aip`, or other non-wallet-derived DIDs.
3. **`service_endpoint`** — DID document lists controlled wallets. Weakest — acceptable for read-only discovery only.

---

## Composite Trust Formula

Consuming agents compose signals with task-contextual weights:

```
effective_trust = w1 * vouch_chain + w2 * behavioral + w3 * credential_score + w4 * activity_score + w5 * governance_score
```

On-chain signals gate delegation entry; behavioral and vouch signals build trust over time; governance attestations gate specific actions at execution time. An agent can set minimum on-chain credentials as a prerequisite before behavioral scoring begins — solving the cold-start bootstrap problem — and require a live governance attestation before high-stakes actions.

---

## Security Considerations

### Signature Integrity

Attestation signatures include the wallet address, conditions, and timestamp in the signed payload. Replaying a signature for a different wallet or condition set fails verification. The `expiresAt` timestamp provides temporal replay protection.

### Data Integrity

The provider refuses to sign if any upstream data source fails during evaluation. Partial results are never signed — a consuming agent either gets a complete, signed profile or an error. This prevents scenarios where a missing chain check could make an agent appear less active than it is, and ensures the signature covers a fully verified state.

### Key Rotation

Providers rotate keys by publishing new keys in their JWKS endpoint with a new `kid`. Old keys are retained during a transition period. Consumers SHOULD cache JWKS for no more than 24 hours.

### Privacy

- Credential signals expose credential existence (`met: true/false`), not the underlying data
- Activity signals expose boolean holdings per dimension, not raw balances
- Governance signals expose scope + evaluator verdict, not raw delegation payloads
- Consuming agents SHOULD NOT store trust signals beyond their TTL

---

## Supported Chains

On-chain signals are available across **38 chains**: 32 EVM + Solana + XRPL + Bitcoin + Tron + Stellar + Sui.

**32 EVM chains:** Ethereum, Base, Polygon, Arbitrum, Optimism, BNB Chain, Avalanche, XDC, Chiliz, Soneium, Plume, World Chain, Sonic, Gnosis, Mantle, Scroll, Linea, zkSync Era, Blast, Taiko, Ronin, Celo, Moonbeam, Moonriver, Viction, opBNB, Unichain, Ink, Sei, Berachain, ApeChain, Robinhood Chain.

**Solana:** SPL token balances and NFT ownership.

**XRPL:** Native XRP, trust line tokens (RLUSD, USDC), and NFTs. Includes trust line state detection (frozen lines fail).

**Bitcoin:** Native BTC balance only. Supports P2PKH, P2SH, bech32, and Taproot address formats.

**Tron:** Native TRX and TRC-20 token balances.

**Stellar:** Native XLM and classic trustlines via `assetCode`, including USDC and BENJI. Classic account balances only; Soroban contract-held balances are out of scope.

**Sui:** Native SUI and Sui-native tokens via fully-qualified Move type strings.

Token-balance checks cover all 38 chains. NFT ownership is available on the 32 EVM chains plus Solana and XRPL; Bitcoin, Tron, Stellar and Sui are token-balance only.

---

## Next Steps

- [ ] @The-Nexus-Guard: contribute full `vouch_chain` schema (draft in #1501)
- [ ] @imran-siddique: contribute full `behavioral` schema with ECDSA/JWKS update
- [ ] @lorenzocipriani-huawei: review trust registry / external authority design
- [ ] @aeoess: consolidate full `governance_attestation` schema with live APS payload example
- [ ] Formal extension spec document once schemas are finalized

Guia de contribuição

Abrir o guia de contribuição

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.