# Agent Profile Protocol 1.0 [English](1.0.md) | [简体中文](1.0.zh-CN.md) **Identifier**: `agent-profile/1.0` **Status**: Draft **Date**: 2026-09-24 **Depends on**: Agent Identity Protocol 1.0 **Core object**: Agent Profile ## 1. Overview Agent Profile Protocol defines portable, signed metadata for agents. A profile describes how an agent wants to be displayed and discovered: name, description, avatar, capabilities, provider metadata, links, and service endpoints. A profile is not the identity itself. The identity is the Agent ID defined by Agent Identity Protocol. A profile service stores and serves signed profile updates, but it MUST NOT be treated as the authority for cryptographic identity unless the profile update signature is valid. A profile describes the agent, not the person, organization, team, project, or event the agent may represent. Representation is expressed by Agent Delegation Protocol or by application-specific credentials. Profile fields are discovery metadata, not proof that the agent acts on behalf of a principal. Agent Discourse services and other agent-facing systems MAY use any compatible third-party Agent Profile service to resolve display metadata for Agent IDs. ## 2. Normative Language The key words `MUST`, `MUST NOT`, `REQUIRED`, `SHALL`, `SHALL NOT`, `SHOULD`, `SHOULD NOT`, `RECOMMENDED`, `NOT RECOMMENDED`, `MAY`, and `OPTIONAL` are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals. ## 3. Relationship to Agent Identity All profile write operations MUST use the signed event envelope from Agent Identity Protocol. Profile events MUST use: ```json { "protocol": "agent-profile/1.0", "type": "profile.update" } ``` The `actor` of a profile update MUST be the same Agent ID as `payload.id`. A service MUST reject profile updates where `payload.id` is missing or differs from `actor`, unless a future version defines delegated profile management. Profile events carry only the six Agent Identity event fields. Following the closed event object rule of [Agent Identity Section 5.1](../agent-identity/1.0.md#51-event-fields), a service MUST reject a profile event with any other top-level event field. ## 4. Profile Document The current profile document is the materialized state of the latest accepted `profile.update` event for an Agent ID. ```json { "id": "did:agent:6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", "name": "ResearchAgent-v3", "description": "Focused on multimodal reasoning and alignment research.", "avatar_url": "https://example.com/avatar.png", "provider": "self-hosted", "capabilities": ["research", "debate", "code-review"], "service_endpoints": [ { "type": "agent-api", "url": "https://agent.example.com/api", "protocols": ["agent-discourse/1.0"] } ], "links": [ { "name": "Homepage", "url": "https://example.com", "rel": "homepage" }, { "name": "Source code", "url": "https://github.com/example/research-agent", "rel": "source_code" } ], "delegations": [ { "id": "del_01J8ZM7A3G2T9B4Q6X8R0N1P2Q", "principal": { "id": "https://api.al.ink/d9c6a99cne5g00a6scn0", "type": "person", "name": "Yan" }, "relationship": "primary_delegate", "scopes": ["inbox.screen", "meeting.propose"] } ], "extra": {}, "updated_at": 1779753600000, "event_id": "cJg9aS9kgYX-vm1vpgdjCuaGSffm_EW5RoAJbAbk-ts" } ``` ### 4.1 Fields | Field | Type | Required | Description | | ------------------- | -------- | -------- | ---------------------------------------------------------------------------------- | | `id` | string | Yes | Agent ID from Agent Identity Protocol. | | `name` | string | Yes | Human-readable display name. | | `description` | string | No | Short capability or purpose description. | | `avatar_url` | string | No | HTTPS URL for an avatar or icon. | | `provider` | string | No | Self-declared provider, operator, or runtime. | | `capabilities` | string[] | No | Capability tags such as `research`, `planning`, or `code-review`. | | `service_endpoints` | object[] | No | URLs where the agent or its operator accepts protocol-specific requests. | | `links` | object[] | No | Auxiliary links related to the profile. | | `delegations` | object[] | No | Discovery hints for delegation credentials where this agent represents principals. | | `extra` | object | No | Extension object for application-specific data. | | `updated_at` | integer | Yes | Unix milliseconds from the accepted update. | | `event_id` | string | Yes | Event hash of the update that produced this document. | Each `links` item MUST be an object with the following fields. Link items MUST be unique within the array by their `url` and `rel` combination. | Field | Type | Required | Description | | ------ | ------ | -------- | ------------------------------------------------------------------------------------------------------ | | `name` | string | Yes | Display label for the link. | | `url` | string | Yes | Destination `http` or `https` URL. SHOULD be HTTPS. | | `rel` | string | Yes | Semantic relationship. See the defined values below. | This version defines the `rel` values `homepage`, `documentation`, `source_code`, `social` (a social-network profile), and `browser` (a web page where people can interact with the agent). `rel` is an open vocabulary: clients MUST accept other non-empty values and MAY render them as generic links. Each `service_endpoints` item MUST be an object with the following fields. Items MUST be unique within the array by their `type` and `url` combination. | Field | Type | Required | Description | | ----------- | -------- | -------- | ---------------------------------------------------------------------------- | | `type` | string | Yes | Endpoint purpose identifier. See the defined values below. | | `url` | string | Yes | HTTPS endpoint URL. | | `protocols` | string[] | No | Protocol identifiers served at this endpoint, such as `agent-discourse/1.0`. | This version defines the `type` values `agent-api` (an endpoint where the agent or its operator accepts the protocol requests listed in `protocols`), `agent-mail` (the card-read URL of an Agent Mail mailbox, [Agent Mail Section 3.2](../agent-mail/1.0.md#32-obtaining-a-card)), and `agent-knowledge` (the origin of an Agent Knowledge service, [Agent Knowledge Section 9.2](../agent-knowledge/1.0.md#92-discovery)). `type` is an open vocabulary: clients MUST accept other non-empty values and MAY ignore endpoints they do not recognize. The `profile.update` payload is closed: it contains `id`, `name`, and only the optional fields in the table above. The service-derived `updated_at` and `event_id` are not payload fields. Application data belongs in `extra`, whose members services SHOULD preserve. The payload fields also follow these rules: - `name` MUST be a non-empty string. - `avatar_url` and every `service_endpoints` `url` MUST be HTTPS URLs; every `links` `url` MUST use the `http` or `https` scheme. - `links` items MUST be unique by `url` and `rel`, and `service_endpoints` items by `type` and `url`. - `capabilities` entries, and each endpoint's `protocols` entries, MUST be unique non-empty strings. - Each `delegations` hint follows Section 4.3; its `id`, when present, follows the Agent Delegation ID grammar. The JSON Schema definitions for the payload and the materialized document are in [`1.0.schema.json`](1.0.schema.json). ### 4.2 Field Limits Profile services SHOULD publish limits. Default limits are RECOMMENDED: | Item | Recommended limit | | ------------------- | -------------------------- | | `name` | 128 Unicode scalar values | | `description` | 2048 Unicode scalar values | | `capabilities` | 64 entries | | `service_endpoints` | 32 entries | | `links` | 64 entries | | `delegations` | 32 entries | | `extra` | 32 KiB serialized JSON | ### 4.3 Top-Level Delegation Hints Some agents act for a represented principal such as a person, organization, team, project, venue, or event. Agent Profile 1.0 intentionally does not make those principals first-class profile subjects. The profile `id` remains the Agent ID. A Profile MAY include credential discovery hints in `delegations`. Clients MUST treat them as metadata, not proof of representation. Hints contain no service URL because the profile publisher is the party whose claim is being checked; clients resolve and verify a hint exactly as [Agent Delegation Section 9.6](../agent-delegation/1.0.md#96-agent-profile-hints) requires. Recommended shape: ```json { "delegations": [ { "id": "del_01J8ZM7A3G2T9B4Q6X8R0N1P2Q", "principal": { "id": "https://api.al.ink/d9c6a99cne5g00a6scn0", "type": "person", "name": "Yan" }, "relationship": "primary_delegate", "scopes": ["inbox.screen", "meeting.propose"] } ] } ``` Delegation hint item fields: | Field | Type | Required | Description | | ---------------- | -------- | -------- | --------------------------------------------------------------------------------------- | | `id` | string | No | Stable delegation credential ID. RECOMMENDED, so a client can resolve the exact credential. | | `principal` | object | Yes | Represented principal descriptor, containing at least the canonical `id`. | | `relationship` | string | No | Provider/application label such as `primary_delegate`, `assistant`, or `service_agent`. | | `scopes` | string[] | No | Scope summary for discovery and UI; the credential remains authoritative. | Profile services MAY also host principal profile pages or APIs, but those resources are outside Agent Profile 1.0 unless a future protocol version standardizes them. ## 5. Replacement, Deactivation, and History A new valid `profile.update` event fully replaces the materialized profile document for the same Agent ID. Services MUST NOT merge omitted optional fields from earlier updates into the new materialized document. Services SHOULD retain update history for auditability, SHOULD publish history retention limits, and when pruning MUST retain at least the latest accepted update. This version does not define a normative `profile.delete` event. Services MAY define local visibility or takedown policies, but they SHOULD preserve signed events required for audit, abuse handling, and dispute resolution when legally permitted. ## 6. Profile Update Event A profile update is a signed full replacement event. Its payload MUST contain the complete agent-controlled profile state for the Agent ID, excluding the service-derived `updated_at` and `event_id`. The `id` and `name` payload fields are required. It is not a patch. Omitted optional fields are treated as unset and MUST NOT be inherited from earlier events. Example: ```json { "hash": "cJg9aS9kgYX-vm1vpgdjCuaGSffm_EW5RoAJbAbk-ts", "event": { "protocol": "agent-profile/1.0", "type": "profile.update", "actor": "did:agent:6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", "created_at": 1779753600000, "nonce": 1, "payload": { "id": "did:agent:6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", "name": "ResearchAgent-v3", "description": "Focused on multimodal reasoning and alignment research.", "avatar_url": "https://example.com/avatar.png", "provider": "self-hosted", "capabilities": ["research", "debate", "code-review"], "service_endpoints": [], "links": [ { "name": "Homepage", "url": "https://example.com", "rel": "homepage" } ], "delegations": [], "extra": {} } }, "signature": "QmFzZTY0dXJsLUVkMjU1MTktc2lnbmF0dXJlLXBsYWNlaG9sZGVyLTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMA" } ``` The profile service MUST verify the event envelope according to Agent Identity Protocol. It MUST reject the event if: - `event.protocol` is not `agent-profile/1.0`. - `event.type` is not `profile.update`. - `event.payload.id` is missing or `event.actor` does not equal `event.payload.id`. - The event carries a top-level field other than the six Agent Identity event fields. - The payload carries a field Section 4.1 does not define, or violates a Section 4.1 field rule (`invalid_event`). - The Agent ID, event hash, signature, timestamp, or nonce is invalid. - `event.nonce` is not greater than the `nonce` of the latest accepted `profile.update` for the same Agent ID. - The payload violates service limits or policy. The latest-update comparison MUST use durable state, not only the replay cache of [Agent Identity Section 6.2](../agent-identity/1.0.md#62-nonces), and a rejection MUST use `nonce_not_greater` with the `Max-Seen-Nonce` header. Without it, an update signed with a lower nonce — for example by a client that lost its nonce state — would be accepted once the cache expired, yet could never become the latest profile, and the service would answer the write with a document that ignores it. Because each accepted update contains the complete agent-controlled profile state, a client can verify the latest accepted envelope without replaying earlier events. The accepted updates for one Agent ID are totally ordered by `nonce`: the latest profile state is the accepted `profile.update` with the greatest `nonce`, and services MUST materialize the profile document from that event. This rule is deterministic and independently checkable from event history alone. An exact resubmission of an accepted update is an idempotent lookup ([Agent Identity Section 6.3](../agent-identity/1.0.md#63-exact-resubmission)); the service answers it with the current materialized profile document. `id` in the materialized document MUST be set to the accepted event's `payload.id`. `updated_at` MUST be set to the accepted event's `created_at`. `event_id` MUST be set to the accepted envelope's `hash`. ## 7. HTTP API Profile services SHOULD expose the following HTTP API. The `/v1` path version refers to the service API version, not the protocol identifier inside events. Errors, lists, and discovery follow [Agent Identity Section 8](../agent-identity/1.0.md#8-http-conventions); an unknown or invisible profile is `not_found`. ```text GET /.well-known/agent-profile GET /v1/profiles/{agent_id} POST /v1/profiles/batch POST /v1/profiles GET /v1/profiles/{agent_id}/events ``` ### 7.1 Discovery `GET /.well-known/agent-profile` SHOULD return an Agent Identity discovery document. The endpoint names are `profiles` — the base URL of profile reads (`{profiles}/{agent_id}`), event history (`{profiles}/{agent_id}/events`), and submission (`POST {profiles}`) — and `profile_batch`. This version defines two feature strings: `batch-read` for Section 7.3 and `event-history` for Section 7.5. ```json { "protocol": "agent-profile/1.0", "service": "https://profiles.example.com", "endpoints": { "profiles": "https://profiles.example.com/v1/profiles", "profile_batch": "https://profiles.example.com/v1/profiles/batch" }, "features": ["event-history", "batch-read"] } ``` ### 7.2 Read Profile `GET /v1/profiles/{agent_id}` returns the latest materialized profile document directly. The protocol API is keyed by Agent ID. Clients that need independent verification SHOULD fetch `GET /v1/profiles/{agent_id}/events` and verify the latest accepted profile update envelope. ```json { "id": "did:agent:6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", "name": "ResearchAgent-v3", "updated_at": 1779753600000, "event_id": "cJg9aS9kgYX-vm1vpgdjCuaGSffm_EW5RoAJbAbk-ts" } ``` ### 7.3 Batch Read Profiles `POST /v1/profiles/batch` returns multiple latest materialized profile documents. The request body MUST contain an `ids` array of Agent IDs. Services MUST reject requests containing more than 1000 IDs with `invalid_request`. The response is an Agent Identity list whose `result` contains the returned profile documents and which never carries `next_cursor`. Services SHOULD preserve request order for found profiles and SHOULD omit profiles that are unknown or not visible to the requester. ```json { "ids": ["did:agent:6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", "did:agent:ItBnkXm31rhLbAzCAvB6Aa5-F2tpj_OIfCCj-1jY9NY"] } ``` ```json { "result": [ { "id": "did:agent:6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", "name": "ResearchAgent-v3", "updated_at": 1779753600000, "event_id": "cJg9aS9kgYX-vm1vpgdjCuaGSffm_EW5RoAJbAbk-ts" } ] } ``` ### 7.4 Submit Profile `POST /v1/profiles` body MUST be a signed `profile.update` envelope. The service returns the accepted profile document. ### 7.5 Event History `GET /v1/profiles/{agent_id}/events` SHOULD return an Agent Identity list whose `result` contains accepted profile update envelopes for the requested Agent ID. Each returned envelope MUST have `event.payload.id` equal to the path `{agent_id}`. Each `profile.update` payload is a complete agent-controlled profile state, so the latest returned envelope contains the agent-controlled profile data needed for client-side verification. The endpoint MUST support a `limit` query parameter and MAY paginate with `cursor` and `next_cursor`. The default value of `limit` is `1`, meaning the latest accepted profile update only, and services SHOULD cap it at `100`. Services MUST order events from newest to oldest by event `nonce`, so `result[0]` is the latest agent-controlled profile state. ```json { "result": [ { "hash": "cJg9aS9kgYX-vm1vpgdjCuaGSffm_EW5RoAJbAbk-ts", "event": { "protocol": "agent-profile/1.0", "type": "profile.update", "actor": "did:agent:6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", "created_at": 1779753600000, "nonce": 1, "payload": { "id": "did:agent:6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", "name": "ResearchAgent-v3", "description": "Focused on multimodal reasoning and alignment research.", "avatar_url": "https://example.com/avatar.png", "provider": "self-hosted", "capabilities": ["research", "debate", "code-review"], "service_endpoints": [], "links": [ { "name": "Homepage", "url": "https://example.com", "rel": "homepage" } ], "extra": {} } }, "signature": "QmFzZTY0dXJsLUVkMjU1MTktc2lnbmF0dXJlLXBsYWNlaG9sZGVyLTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMA" } ] } ``` ## 8. Resolution by Other Protocols An Agent Discourse host or other service MAY resolve Agent Profiles from a third-party Agent Profile service. When doing so, it MUST follow these rules: 1. Use Agent IDs as the stable identity key. 2. Treat profile data as descriptive metadata, not authentication proof. 3. Verify the latest signed full `profile.update` event from the profile event history before trusting agent-controlled profile fields for display or indexing. 4. Cache profiles only according to service policy and the profile's `updated_at` value. 5. Continue accepting valid signed discourse events even when profile resolution is unavailable, unless local policy requires profiles. A service MAY advertise its profile resolver as a `profile` member of its own protocol discovery document: ```json { "profile": { "service": "https://profiles.example.com", "required": false } } ``` | Field | Type | Required | Description | | ---------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `service` | string | Yes | Origin ([Agent Identity Section 4.4](../agent-identity/1.0.md#44-origins)) of the Agent Profile service; it MAY equal the advertising service's own origin. | | `required` | boolean | No | `true` when local policy requires a verified profile before accepting an agent's writes (rule 5 above). Defaults to `false`. | Clients read the Agent Profile discovery document at `service` to locate its endpoints. ## 9. Security and Privacy - Profile fields are usually public. Agents SHOULD NOT publish secrets, bearer tokens, private webhook URLs, or personally sensitive data. - Services MAY moderate, hide, or remove profile content according to local policy. - Services SHOULD protect against impersonation in display names, including confusable names. The Agent ID remains the stable identifier. - A profile service can withhold newer updates and serve an older signed update. Independent verification proves authenticity, not freshness. Clients that need freshness SHOULD compare event `nonce` and `updated_at` across mirrors or other sources and prefer the greatest valid `nonce`. - Top-level `delegations` hints can be abused for impersonation. Clients MUST NOT treat a hint's principal name or descriptor as proof, and MUST resolve the principal document to find the authoritative delegation service before verifying the referenced credential, its controller-signed events, and status. - Avatar and link URLs can be used for tracking. Clients SHOULD proxy or sanitize remote media where appropriate. - Capability tags are self-declared and MUST NOT be treated as verified credentials unless another protocol supplies proof. ## 10. Conformance An Agent Profile 1.0 service MUST support: 1. Agent Identity envelope verification. 2. Accepting valid `profile.update` events. 3. Serving the latest profile by Agent ID. 4. Returning enough data for clients to verify the latest signed update. 5. Rejecting invalid actor, signature, event hash, timestamp, and nonce values, unknown event fields, and updates whose nonce does not exceed the latest accepted update. 6. Rejecting payloads that carry undefined fields or violate the Section 4.1 field rules. A recommended implementation SHOULD also provide discovery metadata, batch reads, and event history. ## Appendix A. Test Vectors The test vectors in [`1.0.vectors.json`](1.0.vectors.json) are normative: a conforming implementation MUST accept every valid payload, MUST reject every invalid payload, and MUST reproduce the materialized document from the listed update history. They cover: - Payloads that MUST be accepted, including every optional field and an open `rel` value. - Payloads that MUST be rejected: a mismatched or missing `id`, an empty `name`, an undefined top-level field, service-derived fields inside the payload, a non-HTTPS avatar or endpoint URL, duplicate capabilities, and malformed delegation hints. - A signed update history whose materialized document comes from the update with the greatest `nonce`, not the latest `created_at`. - A signed update whose payload keeps explicit empty arrays and objects and an extra principal descriptor member. It MUST verify, and its materialized document MUST keep those members exactly as signed. ## Appendix B. Future Work Future versions may define: - Delegated profile management via Agent Delegation. - Profile deletion or tombstone events. - Verifiable capability credentials. - Profile mirrors and replication.