Skip to content

Commit 70f1e2b

Browse files
mikeas1holtskinner
andauthored
feat: Add protocol support for extensions (#716)
# Description This updates the protocol to support Extensions. Extension profiles are documents that describe modifications or additions to the core A2A profile. AgentCards can declare supported extensions via `capabilities.extensions`. This declaration can include additional information via `capabilities.extensions.params`. Clients can use this as a basis for extension negotiation: if a client supports an extension that the server supports, the client can then follow the protocol defined by the extension. This can include, but is not specifically limited to: 1. Requiring specific structure of messages, such as following a specific schema for a DataPart. 2. Providing additional information in request/response Message and Artifact objects via their `metadata` field. 3. Exposing additional methods beyond the core A2A protocol methods. Messages and Artifacts can now include an indication of which extensions are present in their content. I do not yet know if extension indications are necessary on other data structures (such as `MessageSendParams` or `TaskStatus`). I'd say extension indications are not strictly necessary at all: it's possible to infer that an extension was followed by inspecting the message content itself (are the metadata fields you expect present, does the DataPart follow the schema you expect, etc). However, they are useful for validation and simplifying extension implementation logic: "you said you followed this extension, so I'll validate fields are present and then perform my processing". Fixes #585 --------- Co-authored-by: Holt Skinner <[email protected]>
1 parent bf5e809 commit 70f1e2b

File tree

5 files changed

+113
-5
lines changed

5 files changed

+113
-5
lines changed

docs/specification.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ A2A revolves around several key concepts. For detailed explanations, please refe
5151
- **Streaming (SSE):** Real-time, incremental updates for tasks (status changes, artifact chunks) delivered via Server-Sent Events.
5252
- **Push Notifications:** Asynchronous task updates delivered via server-initiated HTTP POST requests to a client-provided webhook URL, for long-running or disconnected scenarios.
5353
- **Context:** An optional, server-generated identifier to logically group related tasks.
54+
- **Extension:** A mechanism for agents to provide additional functionality or data beyond the core A2A specification.
5455

5556
## 3. Transport and Format
5657

@@ -194,11 +195,27 @@ Specifies optional A2A protocol features supported by the agent.
194195
--8<-- "types/src/types.ts:AgentCapabilities"
195196
```
196197

197-
| Field Name | Type | Required | Default | Description |
198-
| :----------------------- | :-------- | :------- | :------ | :----------------------------------------------------------------------------------- |
199-
| `streaming` | `boolean` | No | `false` | Indicates support for SSE streaming methods (`message/stream`, `tasks/resubscribe`). |
200-
| `pushNotifications` | `boolean` | No | `false` | Indicates support for push notification methods (`tasks/pushNotificationConfig/*`). |
201-
| `stateTransitionHistory` | `boolean` | No | `false` | Placeholder for future feature: exposing detailed task status change history. |
198+
| Field Name | Type | Required | Default | Description |
199+
| :----------------------- | :--------------- | :------- | :------ | :----------------------------------------------------------------------------------- |
200+
| `streaming` | `boolean` | No | `false` | Indicates support for SSE streaming methods (`message/stream`, `tasks/resubscribe`). |
201+
| `pushNotifications` | `boolean` | No | `false` | Indicates support for push notification methods (`tasks/pushNotificationConfig/*`). |
202+
| `stateTransitionHistory` | `boolean` | No | `false` | Placeholder for future feature: exposing detailed task status change history. |
203+
| `extensions` | [`AgentExtension`[]](#5521-agentextension-object) | No | `[]` | A list of extensions supported by this agent. |
204+
205+
#### 5.5.2.1. `AgentExtension` Object
206+
207+
Specifies an extension to the A2A protocol supported by the agent.
208+
209+
```ts { .no-copy }
210+
--8<-- "types/src/types.ts:AgentExtension"
211+
```
212+
213+
| Field Name | Type | Required | Description |
214+
| :-------------| :-------- | :------- | :------------------------------------------------------------------------------------------ |
215+
| `uri` | `string` | Yes | The URI for the supported extension. |
216+
| `required` | `boolean` | No | Whether the agent requires clients to follow some protocol logic specific to the extension. Clients should expect failures when attempting to interact with a server that requires an extension the client does not support. |
217+
| `description` | `string` | No | A description of how the extension is used by the agent. |
218+
| `params` | `object` | No | Configuration parameters specific to the extension |
202219

203220
#### 5.5.3. `SecurityScheme` Object
204221

@@ -361,6 +378,7 @@ Represents a single communication turn or a piece of contextual information betw
361378
| `role` | `"user"` \| `"agent"` | Yes | Indicates the sender: `"user"` (from A2A Client) or `"agent"` (from A2A Server). |
362379
| `parts` | [`Part[]`](#65-part-union-type) | Yes | Array of content parts. Must contain at least one part. |
363380
| `metadata` | `Record<string, any>` | No | Arbitrary key-value metadata associated with this message. |
381+
| `extensions` | `string[]` | No | A list of extension URIs that contributed to this message. |
364382
| `referenceTaskIds` | `string[]` | No | List of tasks referenced as contextual hint by this message. |
365383
| `messageId` | `string` | Yes | Message identifier generated by the message sender |
366384
| `taskId` | `string` | No | Task identifier the current message is related to |
@@ -462,6 +480,7 @@ Represents a tangible output generated by the agent during a task. Artifacts are
462480
| `description` | `string` | No | Human-readable description of the artifact. |
463481
| `parts` | [`Part[]`](#65-part-union-type) | Yes | Content of the artifact, as one or more `Part` objects. Must have at least one. |
464482
| `metadata` | `Record<string, any>` | No | Arbitrary key-value metadata associated with the artifact. |
483+
| `extensions` | `string[]` | No | A list of extension URIs that contributed to this artifact. |
465484

466485
### 6.8. `PushNotificationConfig` Object
467486

docs/topics/key-concepts.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,7 @@ The Agent2Agent (A2A) protocol is built around a set of core concepts that defin
7878
- Learn more about [Enterprise-Ready Features](./enterprise-ready.md).
7979
- **Agent Discovery:** The process by which clients find Agent Cards to learn about available A2A Servers and their capabilities.
8080
- Learn more about [Agent Discovery](./agent-discovery.md).
81+
- **Extensions:** A2A allows agents to declare custom protocol extensions as part of their AgentCard.
82+
- More documentation coming soon.
8183

8284
By understanding these core components and mechanisms, developers can effectively design, implement, and utilize A2A for building interoperable and collaborative AI agent systems.

specification/grpc/a2a.proto

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ message Message {
243243
// protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
244244
// Any optional metadata to provide along with the message.
245245
google.protobuf.Struct metadata = 6;
246+
// The URIs of extensions that are present or contributed to this Message.
247+
repeated string extensions = 7;
246248
}
247249

248250
// Artifacts are the container for task completed results. These are similar
@@ -259,6 +261,8 @@ message Artifact {
259261
repeated Part parts = 5;
260262
// Optional metadata included with the artifact.
261263
google.protobuf.Struct metadata = 6;
264+
// The URIs of extensions that are present or contributed to this Artifact.
265+
repeated string extensions = 7;
262266
}
263267

264268
// TaskStatusUpdateEvent is a delta even on a task indicating that a task
@@ -368,6 +372,20 @@ message AgentCapabilities {
368372
bool streaming = 1;
369373
// If the agent can send push notifications to the clients webhook
370374
bool push_notifications = 2;
375+
// Extensions supported by this agent.
376+
repeated AgentExtension extensions = 3;
377+
}
378+
379+
// A declaration of an extension supported by an Agent.
380+
message AgentExtension {
381+
// The URI of the extension.
382+
string uri = 1;
383+
// A description of how this agent uses this extension.
384+
string description = 2;
385+
// Whether the client must follow specific requirements of the extension.
386+
bool required = 3;
387+
// Optional configuration for the extension.
388+
google.protobuf.Struct params = 4;
371389
}
372390

373391
// AgentSkill represents a unit of action/solution that the agent can perform.

specification/json/a2a.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@
9999
"AgentCapabilities": {
100100
"description": "Defines optional capabilities supported by an agent.",
101101
"properties": {
102+
"extensions": {
103+
"description": "extensions supported by this agent.",
104+
"items": {
105+
"$ref": "#/definitions/AgentExtension"
106+
},
107+
"type": "array"
108+
},
102109
"pushNotifications": {
103110
"description": "true if the agent can notify updates to client.",
104111
"type": "boolean"
@@ -207,6 +214,32 @@
207214
],
208215
"type": "object"
209216
},
217+
"AgentExtension": {
218+
"description": "A declaration of an extension supported by an Agent.",
219+
"properties": {
220+
"description": {
221+
"description": "A description of how this agent uses this extension.",
222+
"type": "string"
223+
},
224+
"params": {
225+
"additionalProperties": {},
226+
"description": "Optional configuration for the extension.",
227+
"type": "object"
228+
},
229+
"required": {
230+
"description": "Whether the client must follow specific requirements of the extension.",
231+
"type": "boolean"
232+
},
233+
"uri": {
234+
"description": "The URI of the extension.",
235+
"type": "string"
236+
}
237+
},
238+
"required": [
239+
"uri"
240+
],
241+
"type": "object"
242+
},
210243
"AgentProvider": {
211244
"description": "Represents the service provider of an agent.",
212245
"properties": {
@@ -288,6 +321,13 @@
288321
"description": "Optional description for the artifact.",
289322
"type": "string"
290323
},
324+
"extensions": {
325+
"description": "The URIs of extensions that are present or contributed to this Artifact.",
326+
"items": {
327+
"type": "string"
328+
},
329+
"type": "array"
330+
},
291331
"metadata": {
292332
"additionalProperties": {},
293333
"description": "Extension metadata.",
@@ -1082,6 +1122,13 @@
10821122
"description": "The context the message is associated with",
10831123
"type": "string"
10841124
},
1125+
"extensions": {
1126+
"description": "The URIs of extensions that are present or contributed to this Message.",
1127+
"items": {
1128+
"type": "string"
1129+
},
1130+
"type": "array"
1131+
},
10851132
"kind": {
10861133
"const": "message",
10871134
"description": "Event type",

types/src/types.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,27 @@ export interface AgentCapabilities {
2525
pushNotifications?: boolean;
2626
/** true if the agent exposes status change history for tasks. */
2727
stateTransitionHistory?: boolean;
28+
/** extensions supported by this agent. */
29+
extensions?: AgentExtension[];
2830
}
2931
// --8<-- [end:AgentCapabilities]
3032

33+
// --8<-- [start:AgentExtension]
34+
/**
35+
* A declaration of an extension supported by an Agent.
36+
*/
37+
export interface AgentExtension {
38+
/** The URI of the extension. */
39+
uri: string;
40+
/** A description of how this agent uses this extension. */
41+
description?: string;
42+
/** Whether the client must follow specific requirements of the extension. */
43+
required?: boolean;
44+
/** Optional configuration for the extension. */
45+
params?: { [key: string]: any };
46+
}
47+
// --8<-- [end:AgentExtension]
48+
3149
// --8<-- [start:AgentSkill]
3250
/**
3351
* Represents a unit of capability that an agent can perform.
@@ -273,6 +291,8 @@ export interface Artifact {
273291
metadata?: {
274292
[key: string]: any;
275293
};
294+
/** The URIs of extensions that are present or contributed to this Artifact. */
295+
extensions?: string[];
276296
}
277297
// --8<-- [end:Artifact]
278298

@@ -287,6 +307,8 @@ export interface Message {
287307
metadata?: {
288308
[key: string]: any;
289309
};
310+
/** The URIs of extensions that are present or contributed to this Message. */
311+
extensions?: string[];
290312
/** List of tasks referenced as context by this message.*/
291313
referenceTaskIds?: string[];
292314
/** Identifier created by the message creator*/

0 commit comments

Comments
 (0)