include::{mod-loc}shared/all-attributes.adoc[]

:_mod-docs-content-type: ASSEMBLY
[id="assembly-a2a-features_{context}"]
= A2A protocol features in {registry}

[role="_abstract"]
{registry} implements the A2A (Agent-to-Agent) protocol for AI agent discovery, orchestration, and lifecycle management.


ifdef::service-registry-downstream[]
WARNING: This section describes Developer Preview features. Developer Preview features are not supported by Red Hat in any way and are not functionally complete or production-ready. Do not use Developer Preview features for production or business-critical workloads. Developer Preview features provide early access to functionality in advance of possible inclusion in a Red Hat product offering. Customers can use these features to test functionality and provide feedback during the development process. Developer Preview features might not have any documentation, are subject to change or removal at any time, and have received limited testing. Red Hat might provide ways to submit feedback on Developer Preview features without an associated SLA. For more information about the support scope of Red Hat Developer Preview features, see link:https://access.redhat.com/support/offerings/devpreview[Developer Preview Support Scope].
endif::[]

* xref:a2a-overview_{context}[]
* xref:a2a-configuration_{context}[]
* xref:a2a-well-known-endpoints_{context}[]
* xref:a2a-agent-card-artifact-type_{context}[]
* xref:a2a-validation-rules_{context}[]
* xref:a2a-compatibility-checking_{context}[]
* xref:a2a-automatic-label-extraction_{context}[]
* xref:a2a-registry-built-in-skills_{context}[]
* xref:a2a-llm-lifecycle-management_{context}[]
* xref:a2a-multi-agent-workflow-example_{context}[]
* xref:a2a-java-sdk-usage_{context}[]
* xref:a2a-rest-api-reference_{context}[]
* xref:a2a-troubleshooting_{context}[]

// con-a2a-overview
:_mod-docs-content-type: CONCEPT
[id="a2a-overview_{context}"]
== A2A protocol overview

[role="_abstract"]
With the A2A protocol, AI agents can discover and communicate with each other through standardized endpoints. {registry} serves as both an A2A agent and an agent registry.

.{registry} as an A2A agent
{registry} provides its own capabilities, including schema validation, search, and artifact management.

.{registry} as an agent registry
{registry} stores and discovers other agents' Agent Cards.

.{registry} dual-role A2A architecture
[cols="1,1",options="header"]
|===
|{registry} as an A2A agent
|{registry} as an agent card registry

a|Endpoint: `/.well-known/agent.json`

Built-in skills:

* `schema-validation`
* `schema-search`
* `artifact-management`
* `compatibility-check`
* `agent-discovery`

a|Endpoints:

* `/.well-known/agents`
* `/.well-known/agents/\{groupId}/\{artifactId}`

Capabilities:

* Store agent cards as `AGENT_CARD` artifacts
* Search by skill, capability, or input/output mode
* Version management and compatibility checking
|===

// ref-a2a-configuration
:_mod-docs-content-type: REFERENCE
[id="a2a-configuration_{context}"]
== A2A configuration properties

[role="_abstract"]
You can control A2A features by using the following configuration properties.

[cols="2,1,3"]
|===
|Property |Default |Description

|`apicurio.a2a.enabled`
|`false`
|Enable or disable A2A protocol support

|`apicurio.a2a.agent.name`
|`Apicurio Registry`
|Name of the registry as an A2A agent

|`apicurio.a2a.agent.description`
|_varies_
|Description of the registry agent

|`apicurio.a2a.agent.version`
|_app version_
|Agent version (defaults to application version)

|`apicurio.a2a.agent.url`
|_base URL_
|Base URL for A2A endpoint

|`apicurio.a2a.agent.provider.organization`
|`Apicurio`
|Provider organization name

|`apicurio.a2a.agent.provider.url`
|`https://www.apicur.io`
|Provider organization URL

|`apicurio.a2a.agent.capabilities.streaming`
|`false`
|Whether streaming is supported

|`apicurio.a2a.agent.capabilities.push-notifications`
|`false`
|Whether push notifications are supported
|===

// ref-a2a-well-known-endpoints
:_mod-docs-content-type: REFERENCE
[id="a2a-well-known-endpoints_{context}"]
== A2A well-known endpoints

[role="_abstract"]
{registry} provides the following well-known endpoints for A2A agent discovery and retrieval.

.GET /.well-known/agent.json
Retrieves the Agent Card for the {registry} instance.

Response: Agent Card JSON document

[source,json]
----
{
  "name": "Apicurio Registry",
  "description": "Central registry for AI agents and schemas",
  "version": "3.1.0",
  "url": "http://localhost:8080",
  "provider": {
    "organization": "Apicurio",
    "url": "https://www.apicur.io"
  },
  "skills": [
    {
      "id": "schema-validation",
      "name": "Schema Validation",
      "description": "Validate schemas against format specifications"
    },
    {
      "id": "schema-search",
      "name": "Schema Search",
      "description": "Search for schemas and APIs in the registry"
    }
  ],
  "capabilities": {
    "streaming": false,
    "pushNotifications": false
  },
  "defaultInputModes": ["text"],
  "defaultOutputModes": ["text"]
}
----

.GET /.well-known/agents
Searches for registered Agent Cards with filtering support.

.Query parameters for /.well-known/agents
[cols="1,1,3"]
|===
|Parameter |Type |Description

|`name`
|string
|Filter by agent name (partial match)

|`skill`
|string (repeatable)
|Filter by skill ID

|`capability`
|string
|Filter by capability (for example, `streaming:true`)

|`inputMode`
|string
|Filter by input mode (for example, `text`, `image`)

|`outputMode`
|string
|Filter by output mode

|`offset`
|integer
|Pagination offset (default: 0)

|`limit`
|integer
|Pagination limit (default: 20)
|===

.Example request
[source,bash]
----
curl "http://localhost:8080/.well-known/agents?skill=translation&capability=streaming:true"
----

.Example response: AgentSearchResults
[source,json]
----
{
  "count": 2,
  "agents": [
    {
      "groupId": "ai-agents",
      "artifactId": "translator-agent",
      "name": "Translation Agent",
      "description": "Translates text between languages",
      "version": "1.0.0",
      "url": "http://translator:9001",
      "skills": [{"id": "translation", "name": "Translation"}],
      "capabilities": {"streaming": true}
    }
  ]
}
----

.GET /.well-known/agents/\{groupId}/\{artifactId}
Retrieves a specific registered Agent Card.

.Path parameters
* `groupId` - The group containing the agent card
* `artifactId` - The artifact ID of the agent card

.Query parameters
* `version` (optional) - Specific version (defaults to latest)

Response: Agent Card JSON document

// ref-a2a-agent-card-artifact-type
:_mod-docs-content-type: REFERENCE
[id="a2a-agent-card-artifact-type_{context}"]
== Agent Card artifact type

[role="_abstract"]
Agent Cards are stored as artifacts with type `AGENT_CARD`. You can create Agent Cards by using the REST API and you can validate them against the A2A specification JSON schema.

.Agent Card creation example
[source,bash]
----
curl -X POST "http://localhost:8080/apis/registry/v3/groups/ai-agents/artifacts" \
  -H "Content-Type: application/json" \
  -d '{
    "artifactId": "my-agent",
    "artifactType": "AGENT_CARD",
    "firstVersion": {
      "version": "1.0.0",
      "content": {
        "contentType": "application/json",
        "content": "{\"name\": \"My Agent\", \"skills\": [{\"id\": \"task\", \"name\": \"Task Execution\"}]}"
      }
    }
  }'
----

.Agent Card JSON schema
Agent Cards must conform to the A2A specification:

[source,json]
----
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["name"],
  "properties": {
    "name": {"type": "string"},
    "description": {"type": "string"},
    "version": {"type": "string"},
    "url": {"type": "string", "format": "uri"},
    "provider": {
      "type": "object",
      "properties": {
        "organization": {"type": "string"},
        "url": {"type": "string", "format": "uri"}
      }
    },
    "capabilities": {
      "type": "object",
      "properties": {
        "streaming": {"type": "boolean"},
        "pushNotifications": {"type": "boolean"}
      }
    },
    "skills": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "name"],
        "properties": {
          "id": {"type": "string"},
          "name": {"type": "string"},
          "description": {"type": "string"},
          "tags": {"type": "array", "items": {"type": "string"}},
          "examples": {"type": "array", "items": {"type": "string"}}
        }
      }
    },
    "defaultInputModes": {"type": "array", "items": {"type": "string"}},
    "defaultOutputModes": {"type": "array", "items": {"type": "string"}},
    "authentication": {
      "type": "object",
      "properties": {
        "schemes": {"type": "array", "items": {"type": "string"}}
      }
    }
  }
}
----

// ref-a2a-validation-rules
:_mod-docs-content-type: REFERENCE
[id="a2a-validation-rules_{context}"]
== Agent Card validation rules

[role="_abstract"]
Agent Cards have three validation levels that control how much validation occurs when you create or update an Agent Card.

[cols="1,3"]
|===
|Level |Description

|`NONE`
|No validation.

|`SYNTAX_ONLY`
|Validates that the content is syntactically valid JSON and is a JSON object.

|`FULL`
a|Complete schema validation including:

* Required `name` field
* Valid JSON structure
* Skill objects with `id` and `name`
* Boolean capability values
* Array types for `defaultInputModes` and `defaultOutputModes`
* Valid `supportedInterfaces` entries with `url` and `protocolBinding`
* Valid `provider` object with `organization` field
* Authentication and security scheme validation
|===

// ref-a2a-compatibility-checking
:_mod-docs-content-type: REFERENCE
[id="a2a-compatibility-checking_{context}"]
== Agent Card compatibility rules

[role="_abstract"]
When you version Agent Cards, {registry} enforces compatibility rules to ensure that changes do not break existing clients.

.Compatible changes (allowed)
* Adding new skills
* Adding new capabilities
* Adding authentication schemes
* Adding input or output modes

.Incompatible changes (can break clients)
* Removing skills
* Removing or disabling capabilities
* Removing supported interfaces (matched by URL and protocol binding)
* Changing the protocol version on an existing interface
* Removing authentication schemes
* Removing input or output modes

// ref-a2a-automatic-label-extraction
:_mod-docs-content-type: REFERENCE
[id="a2a-automatic-label-extraction_{context}"]
== Automatic label extraction for Agent Cards

[role="_abstract"]
{registry} automatically extracts labels from Agent Cards for search. You can use these labels for efficient capability-based discovery by using the {registry} label search.

[cols="2,3"]
|===
|Label pattern |Source

|`agent_card:skill:<id>`
|Each skill ID in the skills array

|`agent_card:capability:<name>`
|Enabled capabilities (streaming, pushNotifications)

|`agent_card:inputmode:<mode>`
|Each input mode

|`agent_card:outputmode:<mode>`
|Each output mode

|`agent_card:protocolbinding:<binding>`
|Each protocol binding from the supported interfaces

|`agent_card:securityscheme:<name>`
|Each security scheme from the authentication configuration

|`agent_card:tag:<value>`
|Each tag value from skills
|===

// ref-a2a-registry-built-in-skills
:_mod-docs-content-type: REFERENCE
[id="a2a-registry-built-in-skills_{context}"]
== {registry} built-in A2A skills

[role="_abstract"]
{registry} operates as an A2A agent with the following built-in skills.

[cols="1,2"]
|===
|Skill ID |Description

|`schema-validation`
|Validate schemas against format specifications (Avro, JSON Schema, Protobuf, OpenAPI, AsyncAPI, GraphQL, WSDL, XSD)

|`schema-search`
|Search for schemas and APIs in the registry by name, labels, or content

|`artifact-management`
|Create, update, and manage schema artifacts with full versioning

|`compatibility-check`
|Check schema compatibility between versions by using configurable rules

|`agent-discovery`
|Discover and manage A2A agent cards stored in the registry
|===

// con-a2a-llm-lifecycle-management
:_mod-docs-content-type: CONCEPT
[id="a2a-llm-lifecycle-management_{context}"]
== LLM lifecycle management

[role="_abstract"]
A2A integration includes full LLM lifecycle management with additional artifact types, including MODEL_SCHEMA and PROMPT_TEMPLATE.

.MODEL_SCHEMA artifact type
The MODEL_SCHEMA artifact type defines input and output schemas for LLM agents:

[source,json]
----
{
  "$schema": "https://apicurio.io/schemas/model-schema/v1",
  "modelId": "sentiment-analysis-output",
  "provider": "a2a-demo",
  "version": "1.0.0",
  "output": {
    "type": "object",
    "required": ["sentiment", "confidence"],
    "properties": {
      "sentiment": {"type": "string", "enum": ["positive", "negative", "neutral"]},
      "confidence": {"type": "number", "minimum": 0, "maximum": 1}
    }
  }
}
----

.PROMPT_TEMPLATE artifact type
The PROMPT_TEMPLATE artifact type stores versioned prompt templates with variable support:

[source,yaml]
----
templateId: sentiment-analysis
name: Sentiment Analysis Prompt
version: "1.0.0"

template: |
  Analyze the sentiment of the following message:

  MESSAGE: {{customerMessage}}

  Respond with JSON containing sentiment and confidence.

variables:
  customerMessage:
    type: string
    required: true
    description: The message to analyze

metadata:
  outputSchema: urn:apicurio:llm-agents.schemas/sentiment-output
----

.Artifact links
Agent Cards can reference their schemas and prompts by using URN references:

[source,json]
----
{
  "name": "Sentiment Agent",
  "skills": [
    {
      "id": "sentiment-analysis",
      "name": "Sentiment Analysis",
      "outputSchema": "urn:apicurio:llm-agents.schemas/sentiment-agent-output",
      "promptTemplate": "urn:apicurio:llm-agents.prompts/sentiment-agent-prompt"
    }
  ]
}
----

// con-a2a-multi-agent-workflow-example
:_mod-docs-content-type: CONCEPT
[id="a2a-multi-agent-workflow-example_{context}"]
== Multi-agent workflow example

[role="_abstract"]
The link:https://github.com/Apicurio/apicurio-registry/tree/3.2.x/examples/a2a-real-world-integration[examples/a2a-real-world-integration] directory contains an example of context chaining across multiple agents.

.Context chaining pipeline
[cols="1,3,3",options="header"]
|===
|Step
|Input context
|Output

|1. Sentiment agent
|`\{{original}}`
|`{"sentiment": "very_negative", "urgency": "critical"}`

|2. Issue analyzer
|`\{{original}}` + `\{{sentiment}}`
|`{"priority": "P1", "issue_type": "delayed_delivery"}`

|3. Response generator
|`\{{original}}` + `\{{sentiment}}` + `\{{analysis}}`
|`{"response": "Dear customer, I sincerely apologize..."}`

|4. Translation agent
|`\{{response}}`
|`{"translated": "Estimado cliente, le pido disculpas..."}`
|===

ifndef::service-registry-downstream[]
.Example commands
The following commands start the example application:

[source,bash]
----
cd examples/a2a-real-world-integration
docker-compose up -d
mvn clean compile exec:java
----

The Web UI is available at http://localhost:9000.
endif::[]

// ref-a2a-java-sdk-usage
:_mod-docs-content-type: REFERENCE
[id="a2a-java-sdk-usage_{context}"]
== Java SDK usage for A2A

[role="_abstract"]
You can use the Java SDK to discover agents and register Agent Cards programmatically.

.Agent discovery example
[source,java]
----
RegistryClient client = RegistryClientFactory.create(
    RegistryClientOptions.create("http://localhost:8080/apis/registry/v3"));

// Search for agents with specific skill
var agents = client.wellKnown().agents()
    .get(config -> {
        config.queryParameters.skill = List.of("translation");
        config.queryParameters.limit = 10;
    });

for (var agent : agents.getAgents()) {
    System.out.println("Found: " + agent.getName() + " @ " + agent.getUrl());
}
----

.Agent Card registration example
[source,java]
----
CreateArtifact artifact = new CreateArtifact();
artifact.setArtifactId("my-agent");
artifact.setArtifactType("AGENT_CARD");

CreateVersion version = new CreateVersion();
version.setVersion("1.0.0");

VersionContent content = new VersionContent();
content.setContentType("application/json");
content.setContent(agentCardJson);
version.setContent(content);

artifact.setFirstVersion(version);

client.groups().byGroupId("ai-agents").artifacts()
    .post(artifact, config -> {
        config.queryParameters.ifExists = IfArtifactExists.FIND_OR_CREATE_VERSION;
    });
----

// ref-a2a-rest-api-reference
:_mod-docs-content-type: REFERENCE
[id="a2a-rest-api-reference_{context}"]
== A2A REST API endpoints

[role="_abstract"]
The following table describes the core A2A endpoints available in {registry}.

[cols="2,1,4"]
|===
|Endpoint |Method |Description

|`/.well-known/agent.json`
|GET
|Get the registry's own Agent Card

|`/.well-known/agents`
|GET
|Search registered Agent Cards

|`/.well-known/agents/{groupId}/{artifactId}`
|GET
|Get a specific Agent Card by artifact ID

|`/apis/registry/v3/groups/{groupId}/artifacts`
|POST
|Create an Agent Card artifact (type: AGENT_CARD)

|`/apis/registry/v3/groups/{groupId}/artifacts/{artifactId}`
|GET
|Get Agent Card artifact metadata

|`/apis/registry/v3/groups/{groupId}/artifacts/{artifactId}/versions/{version}/content`
|GET
|Get Agent Card content
|===

// ref-a2a-troubleshooting
:_mod-docs-content-type: REFERENCE
[id="a2a-troubleshooting_{context}"]
== A2A troubleshooting

[role="_abstract"]
Use the following information to troubleshoot common issues with A2A features in {registry}.

.A2A endpoints return 404
Ensure A2A is enabled in your configuration:
[source,properties]
----
apicurio.a2a.enabled=true
----

.Agent Card validation fails
Verify the following conditions:

* The `name` field is present and non-empty.
* Skills have both `id` and `name` fields.
* Capabilities are boolean values.
* The JSON is well-formed.

.Search returns no results
Verify the following conditions:

* Agent Cards are stored with type `AGENT_CARD`.
* The registry extracted labels correctly (check artifact labels).
* Search filters match stored values exactly.

[role="_additional-resources"]
.Additional resources
* xref:getting-started/assembly-llm-artifact-types-implementation.adoc[LLM Artifact Types]
* link:https://google.github.io/A2A/[A2A Protocol Specification]
* xref:getting-started/assembly-configuring-the-registry.adoc[{registry} configuration]
