A2A protocol features in Apicurio Registry

A2A protocol overview

With the A2A protocol, AI agents can discover and communicate with each other through standardized endpoints. Apicurio Registry serves as both an A2A agent and an agent registry.

Apicurio Registry as an A2A agent

Apicurio Registry provides its own capabilities, including schema validation, search, and artifact management.

Apicurio Registry as an agent registry

Apicurio Registry stores and discovers other agents' Agent Cards.

Table 1. Apicurio Registry dual-role A2A architecture
Apicurio Registry as an A2A agent Apicurio Registry as an agent card registry

Endpoint: /.well-known/agent.json

Built-in skills:

  • schema-validation

  • schema-search

  • artifact-management

  • compatibility-check

  • agent-discovery

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

A2A configuration properties

You can control A2A features by using the following configuration properties.

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

A2A well-known endpoints

Apicurio Registry provides the following well-known endpoints for A2A agent discovery and retrieval.

GET /.well-known/agent.json

Retrieves the Agent Card for the Apicurio Registry instance.

Response: Agent Card JSON document

{
  "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.

Table 2. Query parameters for /.well-known/agents
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
curl "http://localhost:8080/.well-known/agents?skill=translation&capability=streaming:true"
Example response: AgentSearchResults
{
  "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

Agent Card artifact type

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
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:

{
  "$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"}}
      }
    }
  }
}

Agent Card validation rules

Agent Cards have three validation levels that control how much validation occurs when you create or update an Agent Card.

Level Description

NONE

No validation.

SYNTAX_ONLY

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

FULL

Complete schema validation including:

  • Required name field (non-empty string)

  • description and version fields

  • supportedInterfaces array, where each interface has url, protocolBinding, and protocolVersion

  • provider object with organization and url

  • skills array, where each skill has id and name

  • capabilities object with boolean values

  • defaultInputModes and defaultOutputModes arrays

  • Authentication and security scheme validation

  • Valid JSON structure

Agent Card compatibility rules

When you version Agent Cards, Apicurio 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 security schemes

  • Removing input or output modes

Automatic label extraction for Agent Cards

Apicurio Registry automatically extracts labels from Agent Cards for search. You can use these labels for efficient capability-based discovery by using the Apicurio Registry label search.

Label pattern Source

agent_card:skill:<id>

Each skill ID in the skills array

agent_card:capability:<name>

Each enabled capability in the capabilities object (where value is true)

agent_card:inputmode:<mode>

Each value in the defaultInputModes array

agent_card:outputmode:<mode>

Each value in the defaultOutputModes array

agent_card:protocolbinding:<binding>

Each protocolBinding value in the supportedInterfaces array

agent_card:securityscheme:<name>

Each key in the securitySchemes object

agent_card:tag:<value>

Each value in the tags array within each skill (deduplicated across skills)

Apicurio Registry built-in A2A skills

Apicurio Registry operates as an A2A agent with the following built-in skills.

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

LLM lifecycle management

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:

{
  "$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:

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:

{
  "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"
    }
  ]
}

Multi-agent workflow example

You can chain context across multiple agents in a pipeline. The a2a-real-world-integration example in the Apicurio Registry repository demonstrates this pattern.

Table 3. Context chaining pipeline
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…​"}

Example commands

To run the example application locally, clone the Apicurio Registry repository and run the following commands:

cd examples/a2a-real-world-integration
docker-compose up -d
mvn clean compile exec:java

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

Java SDK usage for A2A

You can use the Java SDK to discover agents and register Agent Cards programmatically.

Agent discovery example
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
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;
    });

A2A REST API endpoints

The following table describes the core A2A endpoints available in Apicurio Registry.

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/2024.Q2/content

GET

Get Agent Card content

A2A troubleshooting

Use the following information to troubleshoot common issues with A2A features in Apicurio Registry.

A2A endpoints return 404

Ensure A2A is enabled in your configuration:

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.