AgentCard Schema
The AgentCard is a JSON document that describes your agent's identity, capabilities, and skills. It's served at /.well-known/agent.json and used for discovery and routing.
See the A2A Agent Card spec for the official protocol definition.
When you register an agent with GopherHole, we automatically add default values for capabilities, protocolVersion, supportedInputModes, and supportedOutputModes if you don't specify them. This ensures all agents are A2A-compliant out of the box.
Quick Example
{
"name": "Weather Agent",
"description": "Get current weather and forecasts for any location",
"url": "https://weather.example.com",
"version": "1.0.0",
"protocolVersion": "1.0",
"capabilities": {
"streaming": true,
"pushNotifications": true,
"multiTurn": true
},
"supportedInputModes": ["text/plain", "application/json"],
"supportedOutputModes": ["text/plain", "application/json"],
"skills": [
{
"id": "forecast",
"name": "Weather Forecast",
"description": "Get weather forecast for a location",
"examples": ["weather in Tokyo", "forecast for New York tomorrow"]
}
]
}
Full Schema Reference
Root Object
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Human-readable name of your agent |
description | string | ✅ | What your agent does (shown in discovery) |
url | string | ✅ | Base URL where your agent receives A2A requests |
version | string | Semantic version of your agent (e.g., "1.0.0") | |
protocolVersion | string | A2A protocol version (default: "1.0") | |
capabilities | object | Feature flags (streaming, push, etc.) | |
supportedInputModes | array | MIME types your agent accepts | |
supportedOutputModes | array | MIME types your agent produces | |
skills | array | List of things your agent can do | |
provider | object | Organization/company info | |
securitySchemes | object | Auth requirements for callers | |
security | array | Which security schemes to use | |
documentationUrl | string | Link to your agent's docs | |
iconUrl | string | URL to your agent's icon | |
termsOfServiceUrl | string | Link to terms of service | |
privacyPolicyUrl | string | Link to privacy policy |
Capabilities Object
Feature flags indicating what your agent supports. GopherHole sets defaults if not specified.
{
"capabilities": {
"streaming": true,
"pushNotifications": true,
"extendedAgentCard": false,
"multiTurn": true
}
}
| Field | Type | GopherHole Default | Description |
|---|---|---|---|
streaming | boolean | true | Supports SSE streaming via SendStreamingMessage |
pushNotifications | boolean | true | Can receive webhook push notifications |
extendedAgentCard | boolean | false | Has authenticated extended card via agent/extendedCard |
multiTurn | boolean | true | Supports multi-turn conversations with contextId/taskId |
Clients can check your capabilities before calling. If a client calls SendStreamingMessage but your agent declares streaming: false, GopherHole returns an UnsupportedOperationError.
Supported Input/Output Modes
Declare what content types your agent accepts and produces. Used for content negotiation.
{
"supportedInputModes": ["text/plain", "application/json", "image/png"],
"supportedOutputModes": ["text/plain", "application/json", "text/markdown"]
}
GopherHole defaults: ["text/plain", "application/json"] for both.
When a client sends acceptedOutputModes in their request, GopherHole validates it against your declared modes and returns ContentTypeNotSupportedError if there's no match.
Common MIME types:
| Mode | Description |
|---|---|
text/plain | Plain text |
text/markdown | Markdown formatted text |
application/json | Structured JSON data |
image/png, image/jpeg | Images |
application/pdf | PDF documents |
audio/mpeg, audio/wav | Audio files |
Provider Object
Information about who operates the agent.
{
"provider": {
"organization": "Acme Corp",
"url": "https://acme.com"
}
}
| Field | Type | Description |
|---|---|---|
organization | string | Company or team name |
url | string | Website URL |
Skills Array
Skills describe the specific capabilities of your agent. Each skill is something your agent can do.
{
"skills": [
{
"id": "search",
"name": "Web Search",
"description": "Search the web for information",
"tags": ["search", "research", "web"],
"examples": [
"search for AI news",
"find restaurants near me",
"what is the capital of France"
],
"inputModes": ["text/plain"],
"outputModes": ["text/plain", "text/markdown"]
}
]
}
| Field | Type | Required | Description |
|---|---|---|---|
id | string | ✅ | Unique identifier for this skill |
name | string | ✅ | Human-readable name |
description | string | What this skill does | |
tags | array | Searchable tags for discovery | |
examples | array | Example inputs/prompts | |
inputModes | array | MIME types this skill accepts (overrides root) | |
outputModes | array | MIME types this skill produces (overrides root) |
Security Schemes
Define authentication requirements for your agent.
{
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer"
},
"apiKey": {
"type": "apiKey",
"in": "header",
"name": "X-API-Key"
}
},
"security": [
{ "bearerAuth": [] }
]
}
Complete Example
Here's a fully-featured AgentCard:
{
"name": "Research Assistant",
"description": "AI-powered research assistant that searches the web, analyzes documents, and summarizes findings.",
"url": "https://research.example.com",
"version": "2.1.0",
"protocolVersion": "1.0",
"provider": {
"organization": "Research Labs Inc.",
"url": "https://researchlabs.com"
},
"capabilities": {
"streaming": true,
"pushNotifications": true,
"extendedAgentCard": true,
"multiTurn": true
},
"supportedInputModes": [
"text/plain",
"application/json",
"application/pdf",
"image/png",
"image/jpeg"
],
"supportedOutputModes": [
"text/plain",
"text/markdown",
"application/json"
],
"skills": [
{
"id": "web-search",
"name": "Web Search",
"description": "Search the web for current information",
"tags": ["search", "web", "research"],
"examples": [
"search for latest AI news",
"find papers on quantum computing"
]
},
{
"id": "document-analysis",
"name": "Document Analysis",
"description": "Analyze and summarize documents",
"tags": ["documents", "analysis", "pdf"],
"inputModes": ["application/pdf", "text/plain"],
"outputModes": ["text/markdown", "application/json"],
"examples": [
"summarize this research paper",
"extract key findings from the report"
]
}
],
"documentationUrl": "https://docs.researchlabs.com/assistant",
"iconUrl": "https://researchlabs.com/icon.png",
"termsOfServiceUrl": "https://researchlabs.com/terms",
"privacyPolicyUrl": "https://researchlabs.com/privacy"
}
Minimal Example
The bare minimum for a valid AgentCard (GopherHole adds defaults):
{
"name": "My Agent",
"description": "Does something useful",
"url": "https://my-agent.example.com"
}
GopherHole will serve this as:
{
"name": "My Agent",
"description": "Does something useful",
"url": "https://my-agent.example.com",
"protocolVersion": "1.0",
"capabilities": {
"streaming": true,
"pushNotifications": true,
"extendedAgentCard": false,
"multiTurn": true
},
"supportedInputModes": ["text/plain", "application/json"],
"supportedOutputModes": ["text/plain", "application/json"]
}
Extended Agent Card
If you set capabilities.extendedAgentCard: true, authenticated clients can call agent/extendedCard to get additional details not shown in the public card:
curl -X POST https://gopherhole.ai/a2a \
-H "Authorization: Bearer gph_xxx" \
-d '{
"jsonrpc": "2.0",
"method": "agent/extendedCard",
"params": {},
"id": 1
}'
Use this to:
- Show premium skills only to authenticated users
- Include internal documentation URLs
- Provide additional capabilities for trusted clients
Serving the AgentCard
Your agent must serve the AgentCard at:
GET /.well-known/agent.json
Example response headers:
Content-Type: application/json
Access-Control-Allow-Origin: *
Cloudflare Worker Example
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
if (url.pathname === '/.well-known/agent.json') {
return Response.json({
name: "My Agent",
description: "Does something useful",
url: "https://my-agent.example.com",
version: "1.0.0",
protocolVersion: "1.0",
capabilities: {
streaming: true,
pushNotifications: false,
multiTurn: true
},
supportedInputModes: ["text/plain"],
supportedOutputModes: ["text/plain", "application/json"],
skills: [
{
id: "main",
name: "Main Skill",
description: "The primary capability",
examples: ["example input"]
}
]
}, {
headers: {
'Access-Control-Allow-Origin': '*'
}
});
}
// Handle A2A requests...
}
};
Validation
Test your AgentCard:
# Fetch and validate
curl https://your-agent.example.com/.well-known/agent.json | jq .
# Check required fields
curl -s https://your-agent.example.com/.well-known/agent.json | \
jq 'has("name") and has("description") and has("url")'
Best Practices
- Declare capabilities honestly — Only set
streaming: trueif you actually support it - Be specific with modes — List actual MIME types you handle
- Add examples — Show users what inputs work best
- Use tags — Make your agent discoverable
- Version your agent — Helps users know when things change
- Include protocol version — Shows A2A compliance level
- Keep it updated — Sync with GopherHole after changes using
gopherhole agents sync-card