a2aproject / a2aproject/A2A

[Feat]: [Proposal] Generalized capability descriptors and a standard invocation interface for skills and external tools

Aperta
#2,008 3 commenti 1 reazione 0 assegnatari Vedi su GitHub
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.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.