Agent Card Configuration

The Agent Card is your agent's identity document. Published at /.well-known/agent.json, it tells clients what your agent does, what skills it offers, how to authenticate, and what payment is required.

Agent Card Structure

Here's the complete Agent Card from the GitHub Repo Analyzer reference agent:

{
  "name": "GitHub Repo Analyzer",
  "description": "Analyzes GitHub repositories for code complexity, dependencies, and security vulnerabilities.",
  "protocolVersion": "0.3.0",
  "version": "1.0.0",
  "url": "http://localhost:3000/api/a2a",
  "securitySchemes": {
    "github_oauth": {
      "type": "oauth2",
      "description": "GitHub OAuth2 Device Flow authentication.",
      "flows": {
        "deviceCode": {
          "deviceAuthorizationUrl": "http://localhost:3000/auth/device",
          "tokenUrl": "http://localhost:3000/auth/token"
        }
      }
    }
  },
  "security": [{ "github_oauth": [] }],
  "skills": [
    {
      "id": "analyze-repo",
      "name": "Analyze Repository",
      "description": "Analyzes a GitHub repository and returns a structured report covering code complexity, language distribution, dependencies, and security issues.",
      "tags": ["github", "analysis", "security", "dependencies"],
      "inputModes": ["text/plain"],
      "outputModes": ["text/plain"]
    }
  ],
  "capabilities": {
    "streaming": true,
    "extensions": [
      {
        "uri": "https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2",
        "required": true
      }
    ]
  },
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"]
}

Required Fields

FieldTypeDescription
namestringHuman-readable agent name. Keep it concise and descriptive.
descriptionstringWhat the agent does. Clients (and the Agent Registry) use this for discovery.
protocolVersionstringA2A protocol version. Currently "0.3.0".
versionstringYour agent's version. Follow semver.
urlstringThe A2A endpoint URL where JSON-RPC requests are sent.
skillsSkill[]Array of skills the agent offers. At least one is required.
capabilitiesobjectAgent capabilities including streaming and extensions.

Skills Definition

Skills describe what your agent can do. Each skill has an ID, name, description, and supported MIME types.

{
  "id": "analyze-repo",
  "name": "Analyze Repository",
  "description": "Analyzes a GitHub repository and returns a structured report.",
  "tags": ["github", "analysis", "security"],
  "inputModes": ["text/plain"],
  "outputModes": ["text/plain"]
}
FieldTypeDescription
idstringUnique identifier for the skill. Use kebab-case.
namestringHuman-readable skill name.
descriptionstringClear description of what the skill does. Clients use this to decide whether to call your agent.
tagsstring[]Searchable tags for discovery.
inputModesstring[]MIME types the skill accepts as input.
outputModesstring[]MIME types the skill produces as output.

Tip

Write skill descriptions as if they're API documentation. Be specific about what the skill expects as input and what it returns.

Capabilities and X402 Extension

The capabilities object declares what protocol features your agent supports.

Streaming

{
  "capabilities": {
    "streaming": true
  }
}

Set streaming: true if your agent supports the message/stream method for real-time SSE responses.

X402 Extension Declaration

To enable paid services, declare the X402 extension:

{
  "capabilities": {
    "extensions": [
      {
        "uri": "https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2",
        "description": "Supports payments using the x402 protocol for on-chain settlement.",
        "required": true
      }
    ]
  }
}
FieldDescription
uriThe canonical extension URI. Must match exactly.
descriptionOptional human-readable description.
requiredIf true, clients must implement X402 to use this agent. Recommended for paid agents.

Supported MIME Types

Define what content types your agent accepts and produces:

MIME TypeUse Case
text/plainPlain text messages (most common)
application/jsonStructured JSON data
image/png, image/jpegImage generation or analysis
application/pdfDocument processing

The defaultInputModes and defaultOutputModes at the agent level serve as defaults when a skill doesn't specify its own:

{
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"]
}

Dynamic URL Injection

Hard-coding localhost:3000in the Agent Card won't work in production. Use dynamic URL injection to set the correct URLs at runtime based on the NEXT_PUBLIC_BASE_URL environment variable.

import type { AgentCard } from '@a2a-js/sdk';
import agentCardJson from './agent-card.json';

const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL ?? 'http://localhost:3000';

export const agentCard: AgentCard = {
  ...(agentCardJson as Omit<AgentCard, 'url'>),
  url: `${BASE_URL}/api/a2a`,
  securitySchemes: {
    github_oauth: {
      type: 'oauth2',
      description: agentCardJson.securitySchemes.github_oauth.description,
      flows: {
        deviceCode: {
          deviceAuthorizationUrl: `${BASE_URL}/auth/device`,
          tokenUrl: `${BASE_URL}/auth/token`,
        },
      },
    },
  },
  security: [{ github_oauth: [] }],
};

This pattern:

  • Keeps the static JSON file as the source of truth for non-URL fields
  • Injects the correct URLs at runtime based on the environment
  • Works seamlessly across development (localhost:3000) and production (your-agent.fly.dev)

Then serve it from the well-known endpoint:

// src/app/.well-known/agent.json/route.ts
import { NextResponse } from 'next/server';
import { agentCard } from '@/lib/a2a/a2a-handler';

export async function GET() {
  return NextResponse.json(agentCard);
}

Multi-Skill Agent Configuration

An agent can expose multiple skills. Each skill can have different input/output modes:

{
  "skills": [
    {
      "id": "analyze-repo",
      "name": "Analyze Repository",
      "description": "Analyzes a GitHub repository for complexity and security issues.",
      "tags": ["github", "analysis", "security"],
      "inputModes": ["text/plain"],
      "outputModes": ["text/plain"]
    },
    {
      "id": "generate-report",
      "name": "Generate PDF Report",
      "description": "Generates a downloadable PDF report from analysis results.",
      "tags": ["report", "pdf"],
      "inputModes": ["application/json"],
      "outputModes": ["application/pdf"]
    }
  ]
}

Note

When implementing multi-skill agents, your executor should inspect the incoming message to determine which skill is being invoked and route accordingly. You can also implement different pricing per skill (see the Payment Integration guide).

Security Schemes

Define how clients authenticate with your agent:

{
  "securitySchemes": {
    "github_oauth": {
      "type": "oauth2",
      "description": "GitHub OAuth2 Device Flow authentication.",
      "flows": {
        "deviceCode": {
          "deviceAuthorizationUrl": "http://localhost:3000/auth/device",
          "tokenUrl": "http://localhost:3000/auth/token"
        }
      }
    }
  },
  "security": [{ "github_oauth": [] }]
}

The securityarray lists which schemes are required. The GitHub Device Flow is recommended for CLI-based clients (like the A2X CLI) because it doesn't require a browser redirect.

Validation Checklist

Before deploying your agent, verify:

  • name is set and descriptive
  • description clearly explains what the agent does
  • protocolVersion matches "0.3.0"
  • url points to your A2A endpoint (will be overridden by dynamic URL injection)
  • skills has at least one skill with id, name, description
  • inputModes/outputModes are correct for each skill
  • capabilities.extensions includes the X402 URI if your agent is paid
  • securitySchemes is configured if authentication is required
  • /.well-known/agent.json returns the correct card with dynamic URLs
  • /.well-known/agent-card.json also returns the card (alias endpoint)
  • Agent Card is valid JSON with no trailing commas or syntax errors
  • All URLs use the correct protocol (https:// in production)