A2A Protocol Features in Apicurio Registry

Apicurio Registry implements the A2A (Agent-to-Agent) protocol, enabling AI agent discovery, orchestration, and lifecycle management. This document provides comprehensive documentation of all A2A features.

Overview

The A2A protocol enables AI agents to discover and communicate with each other through standardized endpoints. Apicurio Registry serves as both:

  1. An A2A Agent - Exposing its own capabilities (schema validation, search, artifact management)

  2. An Agent Registry - Storing and discovering other agents' Agent Cards

┌─────────────────────────────────────────────────────────────────────────────┐
│                           Apicurio Registry                                  │
│                                                                              │
│  ┌─────────────────────┐        ┌──────────────────────────────────────┐    │
│  │  Registry as Agent  │        │        Agent Card Registry           │    │
│  │                     │        │                                      │    │
│  │  /.well-known/      │        │  /.well-known/agents                 │    │
│  │    agent.json       │        │  /.well-known/agents/{group}/{id}    │    │
│  │                     │        │                                      │    │
│  │  Skills:            │        │  - Store agent cards                 │    │
│  │  - schema-validation│        │  - Search by skill                   │    │
│  │  - schema-search    │        │  - Filter by capability              │    │
│  │  - artifact-mgmt    │        │  - Version management                │    │
│  │  - compatibility    │        │  - Compatibility checking            │    │
│  │  - agent-discovery  │        │                                      │    │
│  └─────────────────────┘        └──────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────────────────┘

Configuration

A2A features are controlled via configuration properties:

Property Default Description

apicurio.a2a.enabled

true

Enable/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

Well-Known Endpoints

GET /.well-known/agent.json

Returns the Agent Card for the Apicurio Registry instance itself.

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

Search for registered Agent Cards with filtering support.

Query Parameters:

Parameter Type Description

name

string

Filter by agent name (partial match)

skill

string (repeatable)

Filter by skill ID

capability

string

Filter by capability (e.g., streaming:true)

inputMode

string

Filter by input mode (e.g., 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"

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}

Retrieve 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.

Creating an Agent Card

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

Validation Rules

Agent Cards support three validation levels:

Level Description

NONE

No validation performed

SYNTAX_ONLY

Validates JSON syntax only

FULL

Complete schema validation including: - Required name field - Valid JSON structure - Skill objects with id and name - Boolean capability values - Array types for modes

Compatibility Checking

When versioning Agent Cards, compatibility rules are enforced:

Compatible Changes (allowed): - Adding new skills - Adding new capabilities - Adding authentication schemes - Adding input/output modes

Incompatible Changes (may break clients): - Removing skills - Removing or disabling capabilities - Changing the agent URL - Removing authentication schemes - Removing input/output modes

Automatic Label Extraction

When Agent Cards are stored, labels are automatically extracted for search:

Label Pattern Source

a2a.skill.<id>

Each skill ID in the skills array

a2a.capability.<name>

Enabled capabilities (streaming, pushNotifications)

a2a.inputMode.<mode>

Each input mode

a2a.outputMode.<mode>

Each output mode

a2a.name

Agent name

a2a.url

Agent URL

This enables efficient capability-based discovery using the Registry’s label search.

Registry Built-in Skills

Apicurio Registry exposes itself as an A2A agent with these 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 using configurable rules

agent-discovery

Discover and manage A2A agent cards stored in the registry

LLM Lifecycle Management

The A2A integration extends to full LLM lifecycle management with additional artifact types:

MODEL_SCHEMA

Defines input/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

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

Linking Artifacts

Agent Cards can reference their schemas and prompts 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"
    }
  ]
}

Example: Multi-Agent Workflow

The examples/a2a-real-world-integration demonstrates context chaining:

Customer Message
       │
       ▼
┌──────────────────────────────────────────────────────────────────────────┐
│  Step 1: Sentiment Agent                                                  │
│  Input:  {{original}}                                                     │
│  Output: {"sentiment": "very_negative", "urgency": "critical"}           │
└──────────────────────────────────────────────────────────────────────────┘
       │
       ▼
┌──────────────────────────────────────────────────────────────────────────┐
│  Step 2: Issue Analyzer                                                   │
│  Input:  {{original}} + {{sentiment}}                                     │
│  Output: {"priority": "P1", "issue_type": "delayed_delivery"}            │
└──────────────────────────────────────────────────────────────────────────┘
       │
       ▼
┌──────────────────────────────────────────────────────────────────────────┐
│  Step 3: Response Generator                                               │
│  Input:  {{original}} + {{sentiment}} + {{analysis}}                      │
│  Output: {"response": "Dear customer, I sincerely apologize..."}         │
└──────────────────────────────────────────────────────────────────────────┘
       │
       ▼
┌──────────────────────────────────────────────────────────────────────────┐
│  Step 4: Translation Agent                                                │
│  Input:  {{response}}                                                     │
│  Output: {"translated": "Estimado cliente, le pido disculpas..."}        │
└──────────────────────────────────────────────────────────────────────────┘

Running the Example

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

Access the Web UI at http://localhost:9000.

Java SDK Usage

Discovering Agents

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());
}

Registering an Agent Card

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;
    });

REST API Reference

Core A2A Endpoints

Endpoint Method Description

/.well-known/agent.json

GET

Get registry’s own Agent Card

/.well-known/agents

GET

Search registered Agent Cards

/.well-known/agents/{groupId}/{artifactId}

GET

Get specific Agent Card by artifact ID

/apis/registry/v3/groups/{groupId}/artifacts

POST

Create 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

Troubleshooting

A2A Endpoints Return 404

Ensure A2A is enabled:

apicurio.a2a.enabled=true

Agent Card Validation Fails

Check that: 1. The name field is present and non-empty 2. Skills have both id and name fields 3. Capabilities are boolean values 4. The JSON is well-formed

Search Returns No Results

Verify: 1. Agent Cards are stored with type AGENT_CARD 2. Labels were extracted (check artifact labels) 3. Search filters match stored values exactly