A2A AgentSkill: Describing What an Agent Can Do
An AgentSkill is one entry in the skills array of an Agent Card
. It describes one thing the agent can do: a name, a description, some tags, and optionally example prompts, media types, and security requirements. In v1.0 skills is a required field of the card.
The proto definition is blunt about what a skill is: “largely a descriptive concept”, a focused set of behaviors the agent is likely to succeed at.
A skill is a description, not an endpoint
No A2A operation selects a skill. SendMessageRequest carries only tenant, message, configuration, and metadata, and SendMessageConfiguration has no skill field either. A client sends an ordinary Message
and the agent decides how to handle it.
So skills exist for the reader of the card. A client agent, or a person browsing a registry, uses them to judge whether this agent suits a task and which media types to send.
Fields
| Field | Required | Meaning |
|---|---|---|
id | Yes | Unique identifier of the skill |
name | Yes | Human-readable name |
description | Yes | Detailed description of the skill |
tags | Yes | Keywords describing the skill’s capabilities |
examples | No | Example prompts or scenarios the skill can handle |
inputModes | No | Supported input media types for this skill, overriding the agent’s defaults |
outputModes | No | Supported output media types for this skill, overriding the agent’s defaults |
securityRequirements | No | Security schemes necessary for this skill |
The specification says arrays marked as required MUST contain at least one element (section 5.7). By that rule a card with an empty skills list is invalid, and so is a skill with no tags.
An example from the specification
This is the first skill of the specification’s sample Agent Card (the GeoSpatial Route Planner Agent):
{
"id": "route-optimizer-traffic",
"name": "Traffic-Aware Route Optimizer",
"description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).",
"tags": ["maps", "routing", "navigation", "directions", "traffic"],
"examples": [
"Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.",
"{\"origin\": {\"lat\": 37.422, \"lng\": -122.084}, \"destination\": {\"lat\": 37.7749, \"lng\": -122.4194}, \"preferences\": [\"avoid_ferries\"]}"
],
"inputModes": ["application/json", "text/plain"],
"outputModes": ["application/json", "application/vnd.geo+json", "text/html"]
}examples is a list of strings. The second example is a JSON object serialized into a string, which matches the application/json entry in inputModes: an example is whatever a client would put in a request, not only natural language.
Per-skill input and output modes
defaultInputModes and defaultOutputModes on the card are required and apply to every skill. A skill’s own inputModes and outputModes replace them for that skill. The sample card shows both directions:
inputModes | outputModes | |
|---|---|---|
| Card defaults | application/json, text/plain | application/json, image/png |
route-optimizer-traffic | application/json, text/plain | application/json, application/vnd.geo+json, text/html |
custom-map-generator | application/json | image/png, image/jpeg, application/json, text/html |
The second skill narrows its input to JSON only, and the first lists output types that are not among the card defaults. Declare these accurately: the specification describes ContentTypeNotSupportedError as raised when a media type in the request is not supported “by the agent or the specific skill being invoked”. See A2A Error Codes
.
On the request side, a client can also say which media types it accepts back through acceptedOutputModes in SendMessageConfiguration.
Per-skill security requirements
A skill can carry its own securityRequirements, with the same structure as the card-level field: each entry maps scheme names, defined in the card’s securitySchemes, to a list of scopes. The specification’s sample card does not set one on a skill. This snippet reuses the card-level requirement from the same sample, only to show where the field goes:
{
"id": "route-optimizer-traffic",
"securityRequirements": [{ "schemes": { "google": { "list": ["openid"] } } }]
}How the schemes themselves are declared is covered in A2A SecurityScheme .
Coming from v0.3?
Per the proto definitions, AgentSkill kept its field numbers 1 to 7 and the meaning of those fields. One field changed:
| v0.3.0 | v1.0.1 |
|---|---|
security (field 8), type Security | security_requirements (field 8), type SecurityRequirement, so the JSON key is securityRequirements |
The structure of the message is the same (map<string, StringList> schemes); only the names changed. The official migration guide does not list this rename; the proto files of the two releases show it. The same rename applies to AgentCard.security (field 9). See Agent Card Proto Field Numbers: v0.3.0 vs v1.0.1
.
Related pages
- Agent Card
: where
skillssits, withcapabilitiesandsupportedInterfaces. - Part : how media types are carried in a message.
- Data Structures : every Agent Card object in one table.
Source: A2A official specification: AgentSkill and Sample Agent Card
; a2a.proto at v1.0.1
and v0.3.0