Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/microsoft/agent-governance-toolkit/llms.txt

Use this file to discover all available pages before exploring further.

This specification defines how AI agents are identified, authenticated, and trust-scored within AgentMesh. Every agent operating in a governed mesh MUST possess a cryptographically bound identity tied to a human sponsor. Trust is not binary: it is a continuously computed score reflecting behavioral history across five dimensions, decaying over time without positive signals, and propagating through interaction networks. All SDK implementations — Python, TypeScript, Rust, .NET, and Go — MUST conform to this specification. The key words are interpreted as described in RFC 2119.

Status

Draft

Date

2026-05-17

Conformance Tests

135 tests

Design Principles

  1. Every agent has a human sponsor. No orphan agents. Accountability traces to a verified person.
  2. Trust is earned, not declared. Initial scores are defaults; only behavioral signals move them.
  3. Scope chains only narrow. Delegation can never grant more capabilities than the parent holds.
  4. Fail closed. Any identity or trust verification failure MUST result in denial.
  5. Cryptographic binding. Identity claims are backed by Ed25519 signatures; no unsigned assertions are trusted.

Agent Credential Structure

Agent DID Schema

An Agent DID MUST conform to the format:
did:mesh:<unique-id>
where <unique-id> is a hex-encoded string generated with at least 128 bits of cryptographically secure randomness.
The canonical wire format is planned to migrate to did:agentmesh:<fingerprint> in a future version. Implementations SHOULD accept both did:mesh: and did:agentmesh: prefixes in parsing but MUST generate did:mesh: in version 1.0.

AgentIdentity Required Fields

An AgentIdentity record MUST contain:
FieldTypeDescription
didAgentDIDThe agent’s decentralized identifier
namestringHuman-readable name; MUST NOT be empty or whitespace-only
public_keystringBase64-encoded Ed25519 public key
verification_key_idstringKey identifier: key-<first-16-hex-chars-of-SHA256(public_key)>
sponsor_emailstringHuman sponsor email; MUST contain @
statusenumOne of: active, suspended, revoked

Optional Fields

FieldTypeDefaultDescription
descriptionstringnullFree-text description
organizationstringnullOrganization name
capabilitieslist[string][]Granted capabilities
created_atdatetimenow(UTC)Creation timestamp
expires_atdatetimenullIdentity expiration (null = no expiry)
parent_didstringnullParent agent DID if delegated
delegation_depthint0Depth in the delegation chain (0 = root)
max_initial_trust_scoreintnullTrust ceiling for Sybil resistance

Validation Rules

  1. name MUST NOT be empty or whitespace-only.
  2. public_key MUST NOT be empty or whitespace-only.
  3. sponsor_email MUST contain @.
  4. If parent_did is not null, it MUST match the did:mesh: prefix.
  5. delegation_depth MUST be >= 0.
  6. The private key MUST NOT appear in any serialized representation (JSON, dict export, logging, API responses, error messages).

Identity Lifecycle

Status Transitions

             ┌──────────┐
create() ───►│  active  │
             └─────┬────┘

          ┌────────┼────────┐
          ▼                 ▼
    ┌──────────┐     ┌─────────┐
    │suspended │     │ revoked │
    └─────┬────┘     └─────────┘
          │ reactivate()   ▲
          └────────────────┘
            (security suspension
             requires override_reason)

Transition Rules

TransitionMethodCondition
active → suspendedsuspend(reason)Always allowed
active → revokedrevoke(reason)Always allowed
suspended → activereactivate()Requires override_reason=True if reason contains "security"
suspended → revokedrevoke(reason)Always allowed
revoked → anyMUST NOT be reactivated; attempts MUST raise an error
An identity is considered active if and only if status == "active" AND (expires_at is null OR expires_at is in the future).

Cryptographic Primitives

All agent identity signatures MUST use Ed25519 (Edwards-curve Digital Signature Algorithm, EdDSA on Curve25519).

Signing

The sign(data: bytes) method MUST:
  1. Verify a private key is available; if not, raise an error.
  2. Sign the data using the Ed25519 private key.
  3. Return the signature as a base64-encoded string (or bytes, depending on SDK).

Verification

The verify(data: bytes, signature: bytes | str) method MUST:
  1. Base64-decode the signature if necessary.
  2. Verify using the stored Ed25519 public key.
  3. Return True on success, False on failure.
  4. MUST NOT raise an exception on verification failure — failures are returned as False.

Trust Score Algorithm

Score Model

Trust scores are integers in the range [0, 1000]. Implementations MUST clamp all scores to this range. Trust ceilings MUST be enforced on every score update. The trust score is computed across five reward dimensions:
DimensionWeightDescription
Policy ComplianceHighAdherence to governance policy decisions
Task CompletionHighSuccessfully completing assigned tasks
Communication ReliabilityMediumConsistent and predictable messaging behavior
Resource EfficiencyMediumOperating within allocated resource budgets
Behavioral ConsistencyLowStable action distribution over time

Score Update Formula

new_score = clamp(
    current_score + (reward_delta × dimension_weight),
    0,
    min(1000, trust_ceiling)
)
where trust_ceiling is inherited from the parent agent at delegation time.

Trust Decay

Trust scores MUST decay over time when no positive signals are received:
decayed_score = current_score × decay_rate ^ hours_elapsed
The default decay_rate is 0.95 per hour. Decay MUST be applied lazily (on access, not on a background timer) to avoid clock-skew issues.

Trust Tier Definitions

Implementations MUST define exactly five trust tiers:
TierScore RangeAccess Level
verified_partner900–1000Highest confidence; full mesh access
trusted700–899Established track record; standard access
standard500–699Default starting point
probationary300–499New or recovering agent; limited access
untrusted0–299Failed validation or malicious behavior; blocked
The TypeScript SDK uses a 0.0–1.0 floating-point scale with four tiers (Untrusted, Provisional, Trusted, Verified). The Rust SDK uses 0–1000 with five tiers. Both satisfy this specification as long as the tier boundaries align proportionally.

Delegation Chain Structure and Validation

Scope Chain Rules

A delegation chain is an ordered sequence of links from a root sponsor to a leaf agent. Each link MUST satisfy:
  1. Monotonic narrowing: Child capabilities MUST be a strict subset of the parent’s capabilities. A child MUST NOT hold capabilities the parent does not hold.
  2. Wildcard restriction: The wildcard capability "*" MUST NOT be delegated.
  3. Depth limit: The maximum delegation depth is implementation-defined but MUST be enforced. The default maximum depth is 5.
  4. Trust ceiling propagation: Each child’s maximum achievable trust score is the parent’s trust ceiling (or 1000 for root agents).

Chain Validation

A delegation chain is valid if and only if:
  1. Every link’s parent_did resolves to an active identity in the registry.
  2. Every link’s capabilities are a subset of its parent’s capabilities.
  3. The chain depth does not exceed the maximum.
  4. No wildcard "*" capability appears in any non-root delegation.
# Valid delegation chain
Root:  capabilities=["read:*", "write:data", "search"]
  └── Child: capabilities=["read:data", "search"]       # narrowed ✅
        └── Grandchild: capabilities=["read:data"]      # narrowed again ✅

# Invalid delegation attempts
Child attempts: capabilities=["read:*", "admin"]  # "admin" not in parent ❌
Child attempts: capabilities=["*"]                # wildcard forbidden ❌

Inter-Agent Trust Negotiation (IATP)

The Inter-Agent Trust Protocol (IATP) defines a challenge-response handshake for mutual authentication between agents.

Handshake Flow

Agent A                                           Agent B
  │                                                  │
  │──── IssueChallenge(target=B.did) ──────────────►│
  │     { challenge_id, nonce (256 bits), expires }  │
  │                                                  │
  │◄─── RespondToChallenge(challenge_id, sig) ───────│
  │     { response_nonce (128 bits), signature }     │
  │                                                  │
  │──── VerifyResponse() ──────────────────────────►│
  │     Returns: HandshakeResult                    │

Challenge Requirements

  • Challenge nonces MUST use at least 256 bits of cryptographically secure randomness.
  • Response nonces MUST use at least 128 bits.
  • Challenges MUST expire and be cleaned up. The default TTL is 60 seconds.
  • Pending challenge count MUST be bounded to prevent DoS.
  • Each challenge nonce is single-use: MUST be removed after use (success or failure).

Signature Verification

The challenge response signature is over: challenge_id || nonce || response_nonce. Token verification MUST use constant-time comparison (e.g., hmac.compare_digest) to prevent timing side channels. Standard string equality MUST NOT be used for token comparison.

Freshness Support

When require_freshness=True, the challenge includes a freshness_nonce that MUST be included in the signed payload and verified. Freshness bypasses the handshake result cache.

JWK / JWKS Serialization

Implementations MUST support Ed25519 key export in JWK format (RFC 7517):
{
  "kty": "OKP",
  "crv": "Ed25519",
  "x": "<base64url-encoded-public-key>",
  "kid": "did:mesh:<unique-id>",
  "use": "sig"
}
JWK export MUST NOT include the private key (d field) by default. The includePrivate / include_private parameter is explicit opt-in. JWKS sets MUST wrap keys in {"keys": [...]}. Round-trip invariant: An identity serialized to JWK and imported back MUST produce a semantically equivalent identity (same did, public_key, capabilities).

DID Document Export

Implementations MUST support W3C DID Document export:
{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:mesh:<unique-id>",
  "verificationMethod": [{
    "id": "did:mesh:<unique-id>#key-<fingerprint>",
    "type": "Ed25519VerificationKey2020",
    "controller": "did:mesh:<unique-id>",
    "publicKeyBase64": "<base64-encoded-public-key>"
  }],
  "authentication": ["did:mesh:<unique-id>#key-<fingerprint>"],
  "service": [{
    "id": "did:mesh:<unique-id>#agentmesh",
    "type": "AgentMeshIdentity",
    "serviceEndpoint": "https://mesh.agentmesh.dev/v1"
  }]
}

Identity Registry

The IdentityRegistry manages collections of AgentIdentity records:
MethodDescription
register(identity)Register an identity. Raises error if DID already registered.
get(did)Look up by DID. Returns None / undefined if not found.
revoke(did, reason)Revoke identity and all its delegates (cascading revocation).
getBySponsor(email)Find all identities for a sponsor.
listActive()List all identities that are currently active.
Cascading revocation: When a root identity is revoked, the registry MUST recursively revoke all child identities in the delegation tree. Cycle detection MUST be implemented to prevent infinite recursion on malformed delegation graphs.

Security Considerations

ConcernRequirement
Private key protectionKeys MUST NOT appear in serialized records, logs, API responses, or error messages.
Timing side channelsToken verification MUST use constant-time comparison.
Log floodingSignature verification failures MUST be logged at DEBUG level only.
Nonce entropyChallenge nonces ≥ 256 bits; response nonces ≥ 128 bits.
DoS resistancePending challenge count MUST be bounded; expired challenges purged.
Sybil resistanceTrust ceilings on delegated agents prevent trust washing.
Replay protectionChallenge nonces are single-use; removed after use.
Credential securityTokens generated with secrets.token_urlsafe(32) (256 bits); only SHA-256 hash stored.

Conformance Requirements

An implementation is conformant if it satisfies all MUST requirements:
  1. DID format MUST be did:mesh:<unique-id> with ≥ 128 bits of randomness.
  2. Ed25519 MUST be the signature algorithm.
  3. Private keys MUST NOT appear in serialized output.
  4. Every identity MUST have a human sponsor.
  5. Trust scores MUST be clamped to [0, 1000].
  6. Trust ceilings MUST be enforced on every score update.
  7. Scope chain capabilities MUST only narrow, never widen.
  8. Wildcard "*" MUST NOT be delegated.
  9. Handshake challenges MUST expire and be cleaned up.
  10. Token verification MUST use constant-time comparison.
  11. Signature verification failures MUST NOT raise exceptions.
  12. Revoked identities MUST NOT be reactivated.
  13. Key rotation MUST produce verifiable proofs.
  14. JWK export MUST NOT include private keys by default.
Conformance tests MUST cover: DID generation and parsing; identity creation, validation, and lifecycle transitions; credential issuance, validation, rotation, and revocation; trust score computation, tier assignment, and ceiling enforcement; trust decay and network propagation; handshake challenge-response flow; delegation chain construction and verification; key rotation with proof verification; JWK round-trip; and revocation list operations.

Build docs developers (and LLMs) love