[Feat]: [Proposal] Generalized capability descriptors and a standard invocation interface for skills and external tools
- Lingua principale
- Shell
- Stelle
- 25.7k
- Fork
- 2.6k
- Merge medio
- 3g 6h
- PR unite (30g)
- 16
Descrizione
### Is your feature request related to a problem? Please describe.
## Background
The current discussion in #1989 on **client-directed skill selection**: an Agent Card may advertise multiple `AgentSkill`s, but a client currently has no standard way to indicate which advertised skill it intends to use when sending a message.
I think this is an important gap. However, I wonder whether the problem may be slightly broader than selecting an `AgentSkill`.
In real agent implementations, an agent’s executable capabilities are often not only represented as A2A `skills`. They may also be backed by, or mapped to, different types of invocation targets, such as:
* model-native function calling
* MCP tools
* CLI tools
* HTTP / REST / GraphQL APIs
* local SDK functions
* workflow engines
* RAG pipelines
* open-ended natural-language handlers
* multimodal handlers
* other custom tool or execution backends
Therefore, while `skill_id` is useful as a routing hint, A2A may eventually need a more general way to describe:
1. what capabilities an agent has;
2. what concrete invocation interfaces back those capabilities;
3. how a client or orchestrator can optionally express its routing intent;
4. how the receiving agent can validate, route, reject, clarify, or execute the request.
The goal is not to turn A2A into RPC, nor to make every skill a strict method endpoint. Instead, the goal is to make capability discovery and optional invocation routing more interoperable while preserving the flexible, agentic interaction model.
## Problem
Today, `AgentSkill` is the main structured concept for advertising what an agent can do. This works well for high-level capability discovery, but it leaves several questions open:
### 1. A skill may not map 1:1 to an executable tool
For example, a skill like `customer_support` may internally use multiple tools:
* `search_orders`
* `refund_payment`
* `update_shipping_address`
* `send_email`
* `escalate_to_human`
In this case, selecting the skill is useful, but it does not fully describe the possible execution targets.
### 2. Some execution targets are not naturally “skills”
A function call, MCP tool, CLI command, or HTTP API may be a low-level capability. It may be used by one or more skills, or it may be exposed directly to orchestrators in controlled environments.
For example:
* an MCP tool may be used by several skills;
* a CLI tool may be an internal implementation detail;
* an HTTP API may be a stable enterprise integration point;
* a natural-language handler may have no discrete tool boundary.
A2A currently has no standard way to describe this spectrum.
### 3. Implementations may introduce incompatible private routing fields
Without a standard capability / invocation descriptor, implementations may use private metadata fields such as:
```json
{
"metadata": {
"task_type": "refund_payment",
"tool": "refund_api",
"intent": "order_refund"
}
}
```
This can work locally, but it does not provide interoperable discovery, validation, or routing semantics across A2A implementations.
### 4. Schema and mode negotiation are not enough by themselves
`inputModes` and `outputModes` can describe supported data formats, but they do not fully describe the concrete capability, schema, execution target, or handler dispatch behavior.
For structured invocation, clients may also need to know:
* what input schema is expected;
* what output schema may be produced;
* whether the invocation target is an A2A skill, MCP tool, function call, CLI command, HTTP API, or custom adapter;
* whether the target is directly invocable or only internally usable by the agent;
* what error semantics apply if the target is unknown, unsupported, unauthorized, or ambiguous.
### Describe the solution you'd like
## Proposal
I propose introducing a **generalized capability descriptor** concept, while keeping the existing `AgentSkill` model intact.
This could be introduced as an additive extension first, and only promoted into the core spec if the pattern proves useful.
There are two possible design directions.
## Option A: Minimal extension under `AgentSkill`
Keep `AgentSkill` as the high-level advertised capability, but allow it to optionally declare one or more backing invocation interfaces.
Example:
```json
{
"skills": [
{
"id": "customer_support",
"name": "Customer Support",
"description": "Handles customer support tasks such as order lookup, refund, address change, and escalation.",
"inputModes": ["text/plain", "application/json"],
"outputModes": ["text/plain", "application/json"],
"interfaces": [
{
"id": "order_lookup_api",
"kind": "http_api",
"description": "Looks up order status by order id.",
"inputSchemaRef": "#/extensions/schemas/order_lookup_input",
"outputSchemaRef": "#/extensions/schemas/order_lookup_output",
"visibility": "orchestrator_hint"
},
{
"id": "refund_mcp_tool",
"kind": "mcp_tool",
"description": "Issues a refund after policy validation.",
"inputSchemaRef": "#/extensions/schemas/refund_input",
"outputSchemaRef": "#/extensions/schemas/refund_output",
"visibility": "agent_internal"
},
{
"id": "support_dialogue_handler",
"kind": "natural_language_handler",
"description": "Handles ambiguous support requests through multi-turn clarification.",
"visibility": "public"
}
]
}
]
}
```
This has relatively small impact on the current model:
* `skills[]` remains the main discovery unit.
* Existing clients can ignore `interfaces`.
* Advanced clients and orchestrators can use `interfaces` for planning, validation, and routing.
* The receiving agent still owns the final routing and policy decision.
## Option B: General `capabilities[]` at Agent Card level
Alternatively, A2A could introduce a top-level `capabilities[]` section, where `AgentSkill` becomes one kind of capability among others.
Example:
```json
{
"capabilities": [
{
"id": "customer_support",
"kind": "agent_skill",
"name": "Customer Support",
"description": "Handles customer support tasks.",
"inputModes": ["text/plain"],
"outputModes": ["text/plain"]
},
{
"id": "refund_mcp_tool",
"kind": "mcp_tool",
"name": "Refund Tool",
"description": "Issues a refund after policy validation.",
"parentCapabilityIds": ["customer_support"],
"inputSchemaRef": "#/extensions/schemas/refund_input",
"outputSchemaRef": "#/extensions/schemas/refund_output",
"visibility": "agent_internal"
},
{
"id": "order_lookup_api",
"kind": "http_api",
"name": "Order Lookup API",
"description": "Looks up order status.",
"parentCapabilityIds": ["customer_support"],
"inputSchemaRef": "#/extensions/schemas/order_lookup_input",
"outputSchemaRef": "#/extensions/schemas/order_lookup_output",
"visibility": "orchestrator_hint"
}
]
}
```
This is more general, but also a larger conceptual change. Therefore, Option A may be better as a first step.
## Suggested runtime hint model
Building on #1989, `SendMessageConfiguration` could support optional routing hints at two levels:
```json
{
"configuration": {
"skill_id": "customer_support",
"interface_id": "order_lookup_api"
}
}
```
Possible semantics:
* If neither `skill_id` nor `interface_id` is provided, behavior remains unchanged.
* If only `skill_id` is provided, the agent routes the request to the matching high-level skill using its normal internal logic.
* If both `skill_id` and `interface_id` are provided, the agent treats `interface_id` as an additional routing hint under that skill.
* If `interface_id` is unknown, unsupported, unauthorized, or not compatible with the selected skill, the agent may reject the request or ask for clarification.
* These fields are advisory routing hints, not strict RPC method names.
* The receiving agent remains responsible for policy checks, validation, clarification, and final execution.
## End-to-end flow
```mermaid
flowchart TD
C[Client / Orchestrator] -->|1. Fetch Agent Card| AC[Agent Card]
AC -->|2. Read skills and optional capability/interface descriptors| CR[Client-side router or planner]
CR -->|3. Select optional skill_id and/or interface_id| MSG[message/send]
MSG --> A2A[Receiving A2A Agent]
A2A --> POL[Policy, auth, and compatibility checks]
POL -->|invalid / unauthorized / unsupported| ERR[Return error or clarification request]
POL -->|valid hint| ROUTER[Capability Router]
ROUTER --> SKILL[High-level AgentSkill handler]
ROUTER --> FUNC[Function-calling adapter]
ROUTER --> MCP[MCP tool adapter]
ROUTER --> CLI[CLI tool adapter]
ROUTER --> API[HTTP / API adapter]
ROUTER --> NL[Natural-language / interactive handler]
SKILL --> EXEC[Execution]
FUNC --> EXEC
MCP --> EXEC
CLI --> EXEC
API --> EXEC
NL --> CLARIFY[Optional multi-turn clarification]
CLARIFY --> EXEC
EXEC --> ART[Task result / artifacts / status updates]
ART --> C
```
## Why this should remain additive
This proposal should not require existing A2A agents to change.
A minimal implementation could continue to publish only:
```json
{
"skills": [
{
"id": "general",
"name": "General Assistant",
"description": "Handles general user requests."
}
]
}
```
More advanced implementations could gradually add capability or interface descriptors when they need:
* deterministic routing;
* orchestration across many tools;
* typed input/output validation;
* enterprise governance;
* auditability;
* tool-level policy enforcement;
* compatibility with MCP, function calling, CLI, or API-based backends.
This allows A2A to support both open-ended agentic interaction and more structured enterprise integration.
## Benefits
### 1. Better capability discovery
Clients and orchestrators can discover not only high-level skills, but also the concrete invocation surfaces available behind those skills.
### 2. Better routing without forcing RPC semantics
The client can provide routing hints, but the agent still decides whether to execute, clarify, reject, or fallback.
### 3. Better interoperability with external tool ecosystems
A2A agents commonly use MCP tools, function calls, APIs, local commands, and workflow systems. A general descriptor would give these systems a standard place in the Agent Card.
### 4. Better governance and auditability
Enterprise deployments often need to know which capability or tool was selected, whether it was authorized, and which schema or policy applied.
### 5. Smaller implementation-specific hacks
This could reduce the need for private metadata fields such as `task_type`, `tool_name`, `route`, or `intent`.
### Describe alternatives you've considered
_No response_
### Additional context
_No response_
### Code of Conduct
- [x] I agree to follow this project's Code of Conduct
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.