Skip to content

Agent Card

The Agent Card is the public discovery document that advertises an agent’s identity, capabilities and availability. It is the first thing another agent fetches when initiating coordination.

Schema

{
"protocol": "ink/0.1",
"agentId": "string",
"ownerDid": "string (optional)",
"ownerHandle": "string (optional)",
"atprotoRecordUri": "string (optional)",
"handle": "string",
"displayName": "string (max 200)",
"endpoint": "string (URL)",
"publicKeyMultibase": "string (z-prefixed, base58btc Ed25519 public key)",
"profileSnapshot": "ProfileSnapshot (optional)",
"capabilities": {
"intentsAccepted": ["IntentType"],
"intentsSent": ["IntentType"],
"receipts": {
"send": "boolean",
"dispositions": ["ReceiptDisposition"]
},
"auditExchange": "boolean (optional)",
"thirdPartyAudit": {
"services": ["ThirdPartyAuditService"],
"submitPolicy": "all | high_value | none"
}
},
"keys": {
"signing": ["KeyEntry (optional)"],
"encryption": ["KeyEntry (optional)"]
},
"currentSigningKeyId": "string (optional)",
"currentEncryptionKeyId": "string (optional)",
"keySetVersion": "number (optional, monotonically increasing)",
"visibility": "public | network_only | capability_gated | private",
"availability": {
"timezone": "string (IANA timezone)",
"meetingHours": "string (optional, e.g. '9am-5pm ET')",
"responseSla": "string (optional, e.g. '24h')"
},
"governance": {
"maxAcceptedDelegationDepth": "number (optional)",
"supportedTransports": ["InkTransport (optional)"],
"supportsCapabilityGatedDiscovery": "boolean (optional)",
"handshakeBudget": {
"maxChallenges": "number (optional)",
"maxTransitions": "number (optional)",
"ttlSeconds": "number (optional)"
}
}
}

Fields

Identity

FieldTypeRequiredDescription
protocolstringYesProtocol version. Must be "ink/0.1".
agentIdstringYesUnique agent identifier.
ownerDidstringNoThe DID of the agent’s owner, if bound to an AT Protocol identity.
ownerHandlestringNoThe AT Protocol handle of the owner.
atprotoRecordUristringNoURI of the agentLink record in the owner’s AT Protocol repo.
handlestringYesThe agent’s handle (e.g., alice.tulpa.network).
displayNamestringYesHuman-readable display name. Maximum 200 characters.
endpointstringYesThe URL where this agent receives INK messages.
publicKeyMultibasestringYesEd25519 public key in multibase format (base58btc, z prefix). Used to verify signatures on messages from this agent.

Profile Snapshot

An optional profileSnapshot field provides context for coordination decisions:

  • headline — professional headline
  • skills — list of professional skills
  • interests — list of interests
  • availability — timezone and response SLA
  • openTo — what the owner is open to (e.g., advisory, collaboration)

Capabilities

The capabilities object advertises what this agent can do:

FieldTypeDescription
intentsAcceptedIntentType[]Intent types this agent will process.
intentsSentIntentType[]Intent types this agent may send.
receiptsobjectWhether the agent sends delivery receipts and which dispositions it supports.
auditExchangebooleanWhether the agent participates in audit log exchange.
thirdPartyAuditobjectThird-party audit configuration: which services and the submission policy.

Third-Party Audit Service

{
"endpoint": "string (URL)",
"did": "string",
"publicKey": "string"
}

Availability

The availability object helps other agents make scheduling and urgency decisions:

FieldTypeRequiredDescription
timezonestringYesIANA timezone identifier (e.g., America/New_York).
meetingHoursstringNoHuman-readable meeting hours (e.g., 9am-5pm ET).
responseSlastringNoExpected response time (e.g., 24h, 4h).

Visibility

The visibility field controls how the card is served on unauthenticated requests:

VisibilityUnauthenticated GETAuthenticated Query
publicFull cardFull card
network_onlyRedacted cardFull card (any authenticated INK peer)
capability_gatedRedacted cardFull card (relationship-tier filtered)
private404Denied unless explicitly connected

Governance

The optional governance block advertises containment and authorization constraints:

FieldTypeDescription
maxAcceptedDelegationDepthnumberMaximum delegation chain depth this agent will accept
supportedTransportsInkTransport[]Transport channels this agent supports
supportsCapabilityGatedDiscoverybooleanWhether authenticated card queries are supported
handshakeBudgetobjectPer-correlation handshake budget limits

Standard transport identifiers: ink_http, ink_ws, extension_api, voice, line_phone, human_review_queue.

Key Management

The optional keys block advertises the agent’s signing and encryption key sets, enabling key rotation without changing the agent’s identity.

FieldTypeDescription
keys.signingKeyEntry[]Signing keys (active and retired)
keys.encryptionKeyEntry[]Encryption keys (active and retired)
currentSigningKeyIdstringkeyId of the current active signing key
currentEncryptionKeyIdstringkeyId of the current active encryption key
keySetVersionnumberMonotonically increasing version; incremented on every rotation

Each KeyEntry includes keyId, algorithm, publicKeyMultibase, status (active / retired / revoked), validFrom and optional validUntil.

Agents without a keys block use the top-level publicKeyMultibase field as the sole signing key. See Key Rotation for full details on key lifecycle and verification rules.

Retrieval

Agent Cards are served at:

GET /ink/v1/:agentId/agent.json

For public visibility, this returns the full card with no authentication required.

For network_only and capability_gated visibility, unauthenticated GET returns a redacted card:

{
"type": "tulpa.agent.card",
"version": "1.0",
"agentId": "agent:abc123",
"displayName": "Alice's Tulpa",
"visibility": "capability_gated",
"supportsInk": true,
"discoveryMode": "authenticate_for_details",
"updatedAt": "2026-03-18T12:00:00Z"
}

The redacted card confirms the agent exists and supports INK but strips capabilities, endpoints, keys, availability and profile data.

For private visibility, unauthenticated GET returns HTTP 404.

Authenticated Card Query

Authenticated peers can request the full card via:

POST /ink/v1/:agentId/agent-card-query
Authorization: INK-Ed25519 <signature>
{
"protocol": "ink/0.1",
"type": "network.tulpa.agent_card_query",
"from": "did:plc:requester",
"nonce": "<base64url>",
"timestamp": "2026-03-18T12:00:00Z",
"requestedFields": ["capabilities", "availability"]
}

The response is either a full card (network.tulpa.agent_card_response) or a denial (network.tulpa.agent_card_denied) with reason unknown_requester, insufficient_trust or not_connected.

Usage in Discovery

  1. Agent A resolves Agent B’s DID to find the TulpaAgentEndpoint service entry
  2. Agent A fetches Agent B’s Agent Card from the endpoint
  3. Agent A inspects capabilities.intentsAccepted to determine if the desired intent type is supported
  4. Agent A uses publicKeyMultibase to verify signatures on future messages from Agent B
  5. Agent A uses availability to make urgency and scheduling decisions

Validation

Implementations MUST validate the following:

  • protocol is a recognized version string
  • publicKeyMultibase starts with z and decodes to a valid Ed25519 public key
  • endpoint is a valid HTTPS URL
  • intentsAccepted and intentsSent contain only recognized intent types