@a2anet/a2a-utils 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +1412 -2
  2. package/dist/artifacts/data.d.ts +118 -0
  3. package/dist/artifacts/data.d.ts.map +1 -0
  4. package/dist/artifacts/data.js +583 -0
  5. package/dist/artifacts/data.js.map +1 -0
  6. package/dist/artifacts/index.d.ts +33 -0
  7. package/dist/artifacts/index.d.ts.map +1 -0
  8. package/dist/artifacts/index.js +131 -0
  9. package/dist/artifacts/index.js.map +1 -0
  10. package/dist/artifacts/text.d.ts +54 -0
  11. package/dist/artifacts/text.d.ts.map +1 -0
  12. package/dist/artifacts/text.js +151 -0
  13. package/dist/artifacts/text.js.map +1 -0
  14. package/dist/client/a2a-session.d.ts +94 -0
  15. package/dist/client/a2a-session.d.ts.map +1 -0
  16. package/dist/client/a2a-session.js +264 -0
  17. package/dist/client/a2a-session.js.map +1 -0
  18. package/dist/client/a2a-tools.d.ts +152 -0
  19. package/dist/client/a2a-tools.d.ts.map +1 -0
  20. package/dist/client/a2a-tools.js +470 -0
  21. package/dist/client/a2a-tools.js.map +1 -0
  22. package/dist/client/agent-manager.d.ts +94 -0
  23. package/dist/client/agent-manager.d.ts.map +1 -0
  24. package/dist/client/agent-manager.js +243 -0
  25. package/dist/client/agent-manager.js.map +1 -0
  26. package/dist/client/index.d.ts +4 -0
  27. package/dist/client/index.d.ts.map +1 -0
  28. package/dist/client/index.js +7 -0
  29. package/dist/client/index.js.map +1 -0
  30. package/dist/files/file-store.d.ts +24 -0
  31. package/dist/files/file-store.d.ts.map +1 -0
  32. package/dist/files/file-store.js +5 -0
  33. package/dist/files/file-store.js.map +1 -0
  34. package/dist/files/index.d.ts +3 -0
  35. package/dist/files/index.d.ts.map +1 -0
  36. package/dist/files/index.js +5 -0
  37. package/dist/files/index.js.map +1 -0
  38. package/dist/files/local-file-store.d.ts +26 -0
  39. package/dist/files/local-file-store.d.ts.map +1 -0
  40. package/dist/files/local-file-store.js +99 -0
  41. package/dist/files/local-file-store.js.map +1 -0
  42. package/dist/index.d.ts +11 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +14 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/tasks/index.d.ts +2 -0
  47. package/dist/tasks/index.d.ts.map +1 -0
  48. package/dist/tasks/index.js +5 -0
  49. package/dist/tasks/index.js.map +1 -0
  50. package/dist/tasks/json-task-store.d.ts +32 -0
  51. package/dist/tasks/json-task-store.d.ts.map +1 -0
  52. package/dist/tasks/json-task-store.js +66 -0
  53. package/dist/tasks/json-task-store.js.map +1 -0
  54. package/dist/types.d.ts +65 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +23 -0
  57. package/dist/types.js.map +1 -0
  58. package/package.json +17 -4
package/README.md CHANGED
@@ -1,3 +1,1413 @@
1
- # @a2anet/a2a-utils
1
+ # A2A Utils JavaScript
2
2
 
3
- JavaScript/TypeScript implementation. See the [project README](../README.md) for details.
3
+ [![npm version](https://img.shields.io/npm/v/@a2anet/a2a-utils.svg)](https://www.npmjs.com/package/@a2anet/a2a-utils) [![License](https://img.shields.io/github/license/a2anet/a2a-utils)](https://github.com/a2anet/a2a-utils/blob/main/LICENSE) [![A2A Protocol](https://img.shields.io/badge/A2A-Protocol-blue)](https://a2a-protocol.org) [![Discord](https://img.shields.io/discord/1391916121589944320?color=7289da&label=Discord&logo=discord&logoColor=white)](https://discord.gg/674NGXpAjU)
4
+
5
+ This package is a comprehensive set of utility functions for using [A2A servers (remote agents)](https://a2a-protocol.org/latest/topics/key-concepts/#core-actors-in-a2a-interactions), it powers the [A2A MCP Server](https://github.com/a2anet/a2a-mcp).
6
+
7
+ `A2ASession` is at the core of the package, it takes an `AgentManager` (for connecting to agents, viewing Agent Cards, etc.), and optionally a `TaskStore` (for saving Tasks) and `FileStore` (for saving files).
8
+ It has two methods, `sendMessage` and `getTask`.
9
+
10
+ These methods are more sophisticated versions of the same methods in the [A2A SDKs](https://github.com/orgs/a2aproject/repositories).
11
+ For example, `sendMessage` abstracts retrieving Agent Cards, sending headers, etc., allowing you to send a message with an agent's ID, e.g. `sendMessage("research-bot", "Find recent papers on quantum computing")`.
12
+ It also sends the message as non-blocking and streams the response until the Task reaches a terminal state or times out.
13
+ If `sendMessage` times out, `getTask` can be called with the Task ID to start streaming the response again.
14
+ If `TaskStore` and `FileStore` are set, the Task, Artifacts, and files will automatically be saved.
15
+
16
+ `AgentManager` stores user-defined agent IDs that link to Agent Card URLs and headers.
17
+ Agents are stored this way so that Agent Card URLs and headers are not exposed to the agent and because Agent Cards can be dynamic (i.e. change depending on the headers).
18
+ It has five methods, `getAgents`, `getAgentsForLlm`, `getAgent`, `getAgentForLlm`, and `addAgent`.
19
+ See the API reference below for more information.
20
+
21
+ Lastly, `A2ATools` is the most sophisticated class in the package, it takes an `A2ASession` and provides six LLM-friendly tools that can be used out-of-the-box with agent frameworks: `getAgents`, `getAgent`, `sendMessage`, `getTask`, `viewTextArtifact`, and `viewDataArtifact`.
22
+ The tools are based on [Writing effective tools for AI agents](https://www.anthropic.com/engineering/writing-tools-for-agents): they have LLM-friendly docstrings, return JSON-serialisable objects, and return actionable error messages.
23
+
24
+ Tool outputs are also optimised for LLMs.
25
+ For example, `getAgents` returns a list of agent names and descriptions, whereas `getAgent` also returns an agent's skill names and descriptions.
26
+ `sendMessage` and `getTask` return LLM-friendly types that are subsets of A2A types (e.g. `TaskForLLM`, `MessageForLLM`, and `ArtifactForLLM`) and automatically minimise large Artifacts, which can be viewed with `viewTextArtifact` and `viewDataArtifact`.
27
+
28
+ ## 📦 Installation
29
+
30
+ To install with npm:
31
+
32
+ ```bash
33
+ npm install @a2anet/a2a-utils
34
+ ```
35
+
36
+ To install with bun:
37
+
38
+ ```bash
39
+ bun add @a2anet/a2a-utils
40
+ ```
41
+
42
+ ## 🚀 Quick Start
43
+
44
+ Create an `A2ASession`, then `A2ATools` to get LLM-friendly tools that can be used out-of-the-box with agent frameworks.
45
+
46
+ ```typescript
47
+ import { A2ATools, A2ASession, AgentManager, JSONTaskStore, LocalFileStore } from "@a2anet/a2a-utils";
48
+
49
+ const agentManager = new AgentManager({
50
+ "weather": { url: "https://weather.example.com/.well-known/agent-card.json" },
51
+ "research-bot": {
52
+ url: "https://research.example.com/.well-known/agent-card.json",
53
+ custom_headers: { "X-API-Key": "key_123" },
54
+ },
55
+ });
56
+
57
+ const a2aSession = new A2ASession(agentManager, {
58
+ taskStore: new JSONTaskStore("./storage/tasks"),
59
+ fileStore: new LocalFileStore("./storage/files"),
60
+ });
61
+
62
+ const a2aTools = new A2ATools(a2aSession);
63
+
64
+ // Pass a2aTools into your agent framework of choice.
65
+ ```
66
+
67
+ ## 📖 API Reference
68
+
69
+ ### A2ATools
70
+
71
+ Ready-made tools for agents to communicate with A2A servers. Every method has LLM-friendly docstrings, returns JSON-serialisable objects, and returns actionable error messages.
72
+
73
+ ```typescript
74
+ import { A2ATools, A2ASession, AgentManager } from "@a2anet/a2a-utils";
75
+
76
+ const tools = new A2ATools(session);
77
+ ```
78
+
79
+ | Parameter | Type | Required | Description |
80
+ |---|---|---|---|
81
+ | `session` | `A2ASession` | Yes | The session instance for sending messages and managing agents |
82
+ | `artifactSettings` | `ArtifactSettings \| null` | No | Minimization/view settings (default: `new ArtifactSettings()`) |
83
+
84
+ `artifactSettings` determines how Artifacts are minimized and viewed:
85
+
86
+ ```typescript
87
+ import { ArtifactSettings } from "@a2anet/a2a-utils";
88
+
89
+ const settings = new ArtifactSettings({
90
+ sendMessageCharacterLimit: 100_000,
91
+ minimizedObjectStringLength: 10_000,
92
+ viewArtifactCharacterLimit: 100_000,
93
+ });
94
+ const tools = new A2ATools(session, { artifactSettings: settings });
95
+ ```
96
+
97
+ | Field | Type | Default | Description |
98
+ |---|---|---|---|
99
+ | `sendMessageCharacterLimit` | `number` | `50,000` | Character limit above which artifacts are minimized in `sendMessage` |
100
+ | `minimizedObjectStringLength` | `number` | `5,000` | Max length for individual string values within minimized data objects |
101
+ | `viewArtifactCharacterLimit` | `number` | `50,000` | Character limit for output from `viewTextArtifact` / `viewDataArtifact` |
102
+
103
+ #### `async getAgents(): Promise<Record<string, unknown>>`
104
+
105
+ List all available agents with their names and descriptions.
106
+
107
+ ```typescript
108
+ const result = await tools.getAgents();
109
+ ```
110
+
111
+ Example result:
112
+
113
+ ```json
114
+ {
115
+ "research-bot": {
116
+ "name": "Research Bot",
117
+ "description": "Find and summarize research papers"
118
+ },
119
+ "weather": {
120
+ "name": "Weather Agent",
121
+ "description": "Get weather forecasts for any location"
122
+ }
123
+ }
124
+ ```
125
+
126
+ #### `async getAgent(agentId: string): Promise<Record<string, unknown>>`
127
+
128
+ Get detailed information about a specific agent, including its skills.
129
+
130
+ ```typescript
131
+ const result = await tools.getAgent("research-bot");
132
+ ```
133
+
134
+ Example result:
135
+
136
+ ```json
137
+ {
138
+ "name": "Research Bot",
139
+ "description": "Find and summarize research papers",
140
+ "skills": [
141
+ {
142
+ "name": "Search Papers",
143
+ "description": "Search for papers by topic, author, or keyword"
144
+ },
145
+ {
146
+ "name": "Summarize Paper",
147
+ "description": "Generate a summary of a specific paper"
148
+ }
149
+ ]
150
+ }
151
+ ```
152
+
153
+ #### `async sendMessage(agentId, message, contextId?, taskId?, timeout?): Promise<Record<string, unknown>>`
154
+
155
+ Send a message to an agent and receive a structured response. The response includes the agent's reply and any generated Artifacts. Artifacts are automatically minimized to fit the context window.
156
+
157
+ | Parameter | Type | Required | Description |
158
+ |---|---|---|---|
159
+ | `agentId` | `string` | Yes | ID of the agent to message (from getAgents) |
160
+ | `message` | `string` | Yes | The message content to send |
161
+ | `contextId` | `string \| null` | No | Continue an existing conversation by providing its context ID |
162
+ | `taskId` | `string \| null` | No | Attach to an existing task (for input-required flows) |
163
+ | `timeout` | `number \| null` | No | Override the default timeout in seconds |
164
+
165
+ ```typescript
166
+ const result = await tools.sendMessage(
167
+ "research-bot", "Find recent papers on quantum computing"
168
+ );
169
+ ```
170
+
171
+ Example result:
172
+
173
+ ```json
174
+ {
175
+ "id": "task-123",
176
+ "contextId": "ctx-456",
177
+ "kind": "task",
178
+ "status": {
179
+ "state": "completed",
180
+ "message": "I found three recent papers on quantum computing and retrieved the abstract for the most recent one."
181
+ },
182
+ "artifacts": [
183
+ {
184
+ "artifactId": "art-789",
185
+ "description": "Search results for quantum computing papers",
186
+ "name": "Search Results",
187
+ "parts": [
188
+ {
189
+ "kind": "data",
190
+ "data": [
191
+ {
192
+ "title": "Quantum Error Correction Advances",
193
+ "year": 2025,
194
+ "authors": "Chen et al."
195
+ },
196
+ {
197
+ "title": "Topological Quantum Computing Survey",
198
+ "year": 2024,
199
+ "authors": "Nakamura et al."
200
+ },
201
+ {
202
+ "title": "Fault-Tolerant Logical Qubits",
203
+ "year": 2024,
204
+ "authors": "Wang et al."
205
+ }
206
+ ]
207
+ }
208
+ ]
209
+ },
210
+ {
211
+ "artifactId": "art-790",
212
+ "description": "Abstract of 'Quantum Error Correction Advances' by Chen et al.",
213
+ "name": "Abstract",
214
+ "parts": [
215
+ {
216
+ "kind": "text",
217
+ "text": "Quantum computing has seen rapid advances in error correction.\nRecent work demonstrates fault-tolerant logical qubits at scale.\nThis paper surveys progress in quantum error correction from 2023-2025.\nWe review surface codes, color codes, and novel hybrid approaches.\nKey results include a 10x reduction in logical error rates.\nThese improvements bring practical quantum computing closer to reality.\nWe also discuss remaining challenges in qubit connectivity.\nFinally, we outline a roadmap for achieving fault-tolerant quantum computation."
218
+ }
219
+ ]
220
+ }
221
+ ]
222
+ }
223
+ ```
224
+
225
+ Continue the conversation using `contextId`:
226
+
227
+ ```typescript
228
+ const result2 = await tools.sendMessage(
229
+ "research-bot",
230
+ "Summarize the most recent result",
231
+ "ctx-456",
232
+ );
233
+ ```
234
+
235
+ #### `async getTask(agentId, taskId, timeout?, pollInterval?): Promise<Record<string, unknown>>`
236
+
237
+ Check the progress of a task that is still in progress. Use this after `sendMessage` returns a task in a non-terminal state (e.g. `"working"`).
238
+
239
+ | Parameter | Type | Required | Description |
240
+ |---|---|---|---|
241
+ | `agentId` | `string` | Yes | ID of the agent that owns the task |
242
+ | `taskId` | `string` | Yes | Task ID from a previous sendMessage response |
243
+ | `timeout` | `number \| null` | No | Override the monitoring timeout in seconds |
244
+ | `pollInterval` | `number \| null` | No | Override the interval between status checks in seconds |
245
+
246
+ ```typescript
247
+ const result = await tools.getTask("research-bot", "task-123");
248
+ ```
249
+
250
+ #### `async viewTextArtifact(agentId, taskId, artifactId, lineStart?, lineEnd?, characterStart?, characterEnd?): Promise<Record<string, unknown>>`
251
+
252
+ View text content from an artifact, optionally selecting a range. Use this for artifacts containing text (documents, logs, code, etc.).
253
+
254
+ | Parameter | Type | Required | Description |
255
+ |---|---|---|---|
256
+ | `agentId` | `string` | Yes | ID of the agent that produced the artifact |
257
+ | `taskId` | `string` | Yes | Task ID containing the artifact |
258
+ | `artifactId` | `string` | Yes | The artifact's unique identifier |
259
+ | `lineStart` | `number \| null` | No | Starting line number (1-based, inclusive) |
260
+ | `lineEnd` | `number \| null` | No | Ending line number (1-based, inclusive) |
261
+ | `characterStart` | `number \| null` | No | Starting character index (0-based, inclusive) |
262
+ | `characterEnd` | `number \| null` | No | Ending character index (0-based, exclusive) |
263
+
264
+ ```typescript
265
+ const result = await tools.viewTextArtifact(
266
+ "research-bot", "task-123", "art-790", 1, 3
267
+ );
268
+ ```
269
+
270
+ Example result:
271
+
272
+ ```json
273
+ {
274
+ "artifactId": "art-790",
275
+ "description": "Abstract of 'Quantum Error Correction Advances' by Chen et al.",
276
+ "name": "Abstract",
277
+ "parts": [
278
+ {
279
+ "kind": "text",
280
+ "text": "Quantum computing has seen rapid advances in error correction.\nRecent work demonstrates fault-tolerant logical qubits at scale.\nThis paper surveys progress in quantum error correction from 2023-2025."
281
+ }
282
+ ]
283
+ }
284
+ ```
285
+
286
+ #### `async viewDataArtifact(agentId, taskId, artifactId, jsonPath?, rows?, columns?): Promise<Record<string, unknown>>`
287
+
288
+ View structured data from an artifact with optional filtering. Use this for artifacts containing JSON data (objects, arrays, tables).
289
+
290
+ | Parameter | Type | Required | Description |
291
+ |---|---|---|---|
292
+ | `agentId` | `string` | Yes | ID of the agent that produced the artifact |
293
+ | `taskId` | `string` | Yes | Task ID containing the artifact |
294
+ | `artifactId` | `string` | Yes | The artifact's unique identifier |
295
+ | `jsonPath` | `string \| null` | No | Dot-separated path to navigate into the data (e.g. `"results.items"`) |
296
+ | `rows` | `string \| null` | No | Row selection: `"0"`, `"0-10"`, `"0,2,5"`, `"all"` |
297
+ | `columns` | `string \| null` | No | Column selection: `"name"`, `"name,age"`, `"all"` |
298
+
299
+ ```typescript
300
+ const result = await tools.viewDataArtifact(
301
+ "research-bot", "task-123", "art-789",
302
+ undefined, "0-1", "title,year",
303
+ );
304
+ ```
305
+
306
+ Example result:
307
+
308
+ ```json
309
+ {
310
+ "artifactId": "art-789",
311
+ "description": "Search results for quantum computing papers",
312
+ "name": "Search Results",
313
+ "parts": [
314
+ {
315
+ "kind": "data",
316
+ "data": [
317
+ {"title": "Quantum Error Correction Advances", "year": 2025},
318
+ {"title": "Topological Quantum Computing Survey", "year": 2024}
319
+ ]
320
+ }
321
+ ]
322
+ }
323
+ ```
324
+
325
+ ### A2ASession
326
+
327
+ Programmatic interface for sending messages to A2A agents. Returns full A2A SDK types (`Task`, `Message`) for direct use.
328
+
329
+ ```typescript
330
+ import { A2ASession, AgentManager, JSONTaskStore, LocalFileStore } from "@a2anet/a2a-utils";
331
+
332
+ const session = new A2ASession(
333
+ new AgentManager({
334
+ "research-bot": { url: "https://research-bot.example.com/.well-known/agent-card.json" },
335
+ }),
336
+ {
337
+ taskStore: new JSONTaskStore("./storage/tasks"),
338
+ fileStore: new LocalFileStore("./storage/files"),
339
+ },
340
+ );
341
+ ```
342
+
343
+ | Parameter | Type | Required | Description |
344
+ |---|---|---|---|
345
+ | `agentManager` | `AgentManager` | Yes | The agent manager instance |
346
+ | `taskStore` | `TaskStore \| undefined` | No | Task store for persistence (default: `InMemoryTaskStore`) |
347
+ | `fileStore` | `FileStore \| null` | No | File store for saving file artifacts (default: `null`) |
348
+ | `sendMessageTimeout` | `number` | No | HTTP timeout in seconds for `sendMessage` (default: `60.0`) |
349
+ | `getTaskTimeout` | `number` | No | Total monitoring timeout in seconds for `getTask` (default: `60.0`) |
350
+ | `getTaskPollInterval` | `number` | No | Interval in seconds between `getTask` polls (default: `5.0`) |
351
+
352
+ #### `async sendMessage(agentId: string, message: string, opts?): Promise<Task | Message>`
353
+
354
+ Send a message to an A2A agent. The returned task is automatically saved to the task store. File artifacts are saved via the file store.
355
+
356
+ | Parameter | Type | Required | Description |
357
+ |---|---|---|---|
358
+ | `agentId` | `string` | Yes | Registered agent identifier |
359
+ | `message` | `string` | Yes | The message content to send |
360
+ | `opts.contextId` | `string \| null` | No | Context ID to continue a conversation (auto-generated when null) |
361
+ | `opts.taskId` | `string \| null` | No | Task ID to attach to the message |
362
+ | `opts.timeout` | `number \| null` | No | Override HTTP timeout in seconds (default: `sendMessageTimeout`) |
363
+
364
+ ```typescript
365
+ import type { Task, Message } from "@a2a-js/sdk";
366
+
367
+ const response = await session.sendMessage(
368
+ "research-bot", "Find recent papers on quantum computing"
369
+ );
370
+ ```
371
+
372
+ Continue the conversation using `contextId`:
373
+
374
+ ```typescript
375
+ const response2 = await session.sendMessage(
376
+ "research-bot",
377
+ "Summarize the most recent result",
378
+ { contextId: response.contextId },
379
+ );
380
+ ```
381
+
382
+ **Returns:** `Task | Message` (from `@a2a-js/sdk`)
383
+
384
+ #### `async getTask(agentId: string, taskId: string, opts?): Promise<Task>`
385
+
386
+ Get the current state of a task. Monitors until a terminal state (`completed`, `canceled`, `failed`, `rejected`) or actionable state (`input-required`, `auth-required`) is reached, or until timeout. Uses SSE resubscription if the agent supports streaming, otherwise polls at regular intervals.
387
+
388
+ On monitoring timeout, returns the current task state (which may still be non-terminal, e.g. `working`). The only errors from `getTask` are failed HTTP requests (agent down, network error).
389
+
390
+ | Parameter | Type | Required | Description |
391
+ |---|---|---|---|
392
+ | `agentId` | `string` | Yes | Registered agent identifier |
393
+ | `taskId` | `string` | Yes | Task ID from a previous `sendMessage` call |
394
+ | `opts.timeout` | `number \| null` | No | Override monitoring timeout in seconds (default: `getTaskTimeout`) |
395
+ | `opts.pollInterval` | `number \| null` | No | Override interval between polls in seconds (default: `getTaskPollInterval`) |
396
+
397
+ ```typescript
398
+ const task = await session.getTask("research-bot", "task-123");
399
+ ```
400
+
401
+ **Returns:** `Task` (from `@a2a-js/sdk`)
402
+
403
+ ### AgentManager
404
+
405
+ Manages A2A agent cards keyed by user-defined agent IDs.
406
+
407
+ ```typescript
408
+ import { AgentManager } from "@a2anet/a2a-utils";
409
+
410
+ // From object
411
+ const manager = new AgentManager({
412
+ "language-translator": {
413
+ url: "https://example.com/language-translator/agent-card.json",
414
+ custom_headers: { "Authorization": "Bearer tok_123" },
415
+ },
416
+ });
417
+
418
+ // From JSON file
419
+ const manager2 = new AgentManager("./agents.json");
420
+
421
+ // Empty — add agents later
422
+ const manager3 = new AgentManager();
423
+ ```
424
+
425
+ #### `async getAgents(): Promise<Record<string, AgentURLAndCustomHeaders>>`
426
+
427
+ Get all registered agents.
428
+ Note: this should NOT be added to the LLM's context, use `getAgentsForLlm` instead.
429
+
430
+ **Returns:** `Record<string, AgentURLAndCustomHeaders>`
431
+
432
+ ```typescript
433
+ const agents = await manager.getAgents();
434
+ ```
435
+
436
+ #### `async getAgentsForLlm(detail?: string): Promise<Record<string, Record<string, unknown>>>`
437
+
438
+ Generate summary of all agents, sorted by agent_id.
439
+
440
+ | Parameter | Type | Required | Description |
441
+ |---|---|---|---|
442
+ | `detail` | `string` | No | Detail level: `"name"`, `"basic"` (default), `"skills"`, or `"full"` |
443
+
444
+ **Returns:** `Record<string, Record<string, unknown>>`
445
+
446
+ `"name"`:
447
+
448
+ ```typescript
449
+ const summaries = await manager.getAgentsForLlm("name");
450
+ ```
451
+
452
+ ```json
453
+ {
454
+ "code-reviewer": {"name": "Code Reviewer"},
455
+ "language-translator": {"name": "Universal Translator"}
456
+ }
457
+ ```
458
+
459
+ `"basic"` (default):
460
+
461
+ ```typescript
462
+ const summaries = await manager.getAgentsForLlm();
463
+ ```
464
+
465
+ ```json
466
+ {
467
+ "code-reviewer": {
468
+ "name": "Code Reviewer",
469
+ "description": "Review code for best practices"
470
+ },
471
+ "language-translator": {
472
+ "name": "Universal Translator",
473
+ "description": "Translate text and audio between 50+ languages"
474
+ }
475
+ }
476
+ ```
477
+
478
+ `"skills"`:
479
+
480
+ ```typescript
481
+ const summaries = await manager.getAgentsForLlm("skills");
482
+ ```
483
+
484
+ ```json
485
+ {
486
+ "code-reviewer": {
487
+ "name": "Code Reviewer",
488
+ "description": "Review code for best practices",
489
+ "skills": ["Review Code"]
490
+ },
491
+ "language-translator": {
492
+ "name": "Universal Translator",
493
+ "description": "Translate text between 50+ languages",
494
+ "skills": ["Translate Text", "Translate Audio"]
495
+ }
496
+ }
497
+ ```
498
+
499
+ `"full"`:
500
+
501
+ ```typescript
502
+ const summaries = await manager.getAgentsForLlm("full");
503
+ ```
504
+
505
+ ```json
506
+ {
507
+ "code-reviewer": {
508
+ "name": "Code Reviewer",
509
+ "description": "Review code for best practices",
510
+ "skills": [
511
+ {
512
+ "name": "Review Code",
513
+ "description": "Review code for best practices, identify bugs, and suggest improvements"
514
+ }
515
+ ]
516
+ },
517
+ "language-translator": {
518
+ "name": "Universal Translator",
519
+ "description": "Translate text between 50+ languages",
520
+ "skills": [
521
+ {
522
+ "name": "Translate Text",
523
+ "description": "Translate text between any supported language pair"
524
+ },
525
+ {
526
+ "name": "Translate Audio",
527
+ "description": "Translate audio between any supported language pair"
528
+ }
529
+ ]
530
+ }
531
+ }
532
+ ```
533
+
534
+ #### `async getAgent(agentId: string): Promise<AgentURLAndCustomHeaders | null>`
535
+
536
+ Retrieve agent by ID.
537
+ Note: this should NOT be added to the LLM's context, use `getAgentForLlm` instead.
538
+
539
+ | Parameter | Type | Required | Description |
540
+ |---|---|---|---|
541
+ | `agentId` | `string` | Yes | User-defined agent identifier |
542
+
543
+ **Returns:** [`AgentURLAndCustomHeaders`](#agenturlandcustomheaders) | `null`
544
+
545
+ ```typescript
546
+ const agent = await manager.getAgent("language-translator");
547
+ ```
548
+
549
+ Returns `null` if the agent ID is not registered.
550
+
551
+ #### `async getAgentForLlm(agentId: string, detail?: string): Promise<Record<string, unknown> | null>`
552
+
553
+ Generate summary for a single agent.
554
+
555
+ | Parameter | Type | Required | Description |
556
+ |---|---|---|---|
557
+ | `agentId` | `string` | Yes | User-defined agent identifier |
558
+ | `detail` | `string` | No | Detail level: `"name"`, `"basic"` (default), `"skills"`, or `"full"` |
559
+
560
+ **Returns:** `Record<string, unknown> | null` — summary object or `null` if not found.
561
+
562
+ ```typescript
563
+ const summary = await manager.getAgentForLlm("language-translator");
564
+ ```
565
+
566
+ ```json
567
+ {
568
+ "name": "Universal Translator",
569
+ "description": "Translate text and audio between 50+ languages"
570
+ }
571
+ ```
572
+
573
+ #### `async addAgent(agentId: string, url: string, customHeaders?: Record<string, string>): Promise<void>`
574
+
575
+ Register a new agent at runtime.
576
+
577
+ | Parameter | Type | Required | Description |
578
+ |---|---|---|---|
579
+ | `agentId` | `string` | Yes | User-defined agent identifier |
580
+ | `url` | `string` | Yes | Agent card URL |
581
+ | `customHeaders` | `Record<string, string>` | No | Custom HTTP headers |
582
+
583
+ **Throws:** `Error` if `agentId` is already registered.
584
+
585
+ ```typescript
586
+ await manager.addAgent(
587
+ "code-reviewer",
588
+ "https://review.example.com/.well-known/agent-card.json",
589
+ { "X-API-Key": "key_123" },
590
+ );
591
+ ```
592
+
593
+ ### 💾 JSONTaskStore
594
+
595
+ Persists Task objects as individual JSON files. Implements the A2A SDK `TaskStore` interface.
596
+
597
+ ```typescript
598
+ import { JSONTaskStore } from "@a2anet/a2a-utils";
599
+
600
+ const taskStore = new JSONTaskStore("./storage/tasks");
601
+ ```
602
+
603
+ #### `async save(task: Task): Promise<void>`
604
+
605
+ Save a task to disk. Creates `./storage/tasks/{task_id}.json`.
606
+
607
+ #### `async load(taskId: string): Promise<Task | undefined>`
608
+
609
+ Load a task from disk.
610
+
611
+ Returns `undefined` if the task file does not exist.
612
+
613
+ #### `async delete(taskId: string): Promise<void>`
614
+
615
+ Delete a task from disk.
616
+
617
+ ### 📁 Files
618
+
619
+ #### FileStore
620
+
621
+ Interface for file storage. Implement this to use custom storage backends (S3, GCS, etc.).
622
+
623
+ ```typescript
624
+ import type { Artifact } from "@a2a-js/sdk";
625
+
626
+ interface FileStore {
627
+ save(taskId: string, artifact: Artifact): Promise<string[]>;
628
+ get(taskId: string, artifactId: string): Promise<string[]>;
629
+ delete(taskId: string, artifactId: string): Promise<void>;
630
+ }
631
+ ```
632
+
633
+ #### LocalFileStore
634
+
635
+ Saves artifact file parts to the local filesystem. Files are stored at `storageDir/taskId/artifactId/filename`.
636
+
637
+ ```typescript
638
+ import { LocalFileStore } from "@a2anet/a2a-utils";
639
+
640
+ const fileStore = new LocalFileStore("./storage/files");
641
+ ```
642
+
643
+ ##### `async save(taskId: string, artifact: Artifact): Promise<string[]>`
644
+
645
+ Save file parts from an artifact to disk.
646
+
647
+ ```typescript
648
+ const savedPaths = await fileStore.save("task-123", artifact);
649
+ ```
650
+
651
+ Example result:
652
+
653
+ ```typescript
654
+ ["./storage/files/task-123/art-789/quarterly_report.pdf"]
655
+ ```
656
+
657
+ ##### `async get(taskId: string, artifactId: string): Promise<string[]>`
658
+
659
+ Get saved file paths for an artifact.
660
+
661
+ ```typescript
662
+ const paths = await fileStore.get("task-123", "art-789");
663
+ ```
664
+
665
+ Example result:
666
+
667
+ ```typescript
668
+ ["./storage/files/task-123/art-789/quarterly_report.pdf"]
669
+ ```
670
+
671
+ Returns an empty array if no files are found.
672
+
673
+ ##### `async delete(taskId: string, artifactId: string): Promise<void>`
674
+
675
+ Delete saved files for an artifact.
676
+
677
+ ```typescript
678
+ await fileStore.delete("task-123", "art-789");
679
+ ```
680
+
681
+ ### 🎨 Artifacts
682
+
683
+ `A2ATools` uses the `TextArtifacts` and `DataArtifacts` classes to automatically minimize Artifacts returned from `sendMessage` and view Artifacts using `viewTextArtifact` and `viewDataArtifact`. They can also be used independently on raw data.
684
+
685
+ #### TextArtifacts
686
+
687
+ ##### `TextArtifacts.view(text, opts?): string`
688
+
689
+ View text content with optional line or character range selection. Supports line selection (1-based, inclusive) or character selection (0-based, slice semantics). These are mutually exclusive — providing both throws an `Error`.
690
+
691
+ | Parameter | Type | Required | Description |
692
+ |---|---|---|---|
693
+ | `text` | `string` | Yes | The text to view |
694
+ | `opts.lineStart` | `number \| null` | No | Starting line number (1-based, inclusive) |
695
+ | `opts.lineEnd` | `number \| null` | No | Ending line number (1-based, inclusive) |
696
+ | `opts.characterStart` | `number \| null` | No | Starting character index (0-based, inclusive) |
697
+ | `opts.characterEnd` | `number \| null` | No | Ending character index (0-based, exclusive) |
698
+ | `opts.characterLimit` | `number` | No | Maximum output size (default: `50,000`) |
699
+
700
+ **Returns:** `string`
701
+
702
+ Line selection:
703
+
704
+ ```typescript
705
+ import { TextArtifacts } from "@a2anet/a2a-utils";
706
+
707
+ const text = "[INFO] Server started\n[INFO] Connected to DB\n[WARN] Cache miss\n[INFO] Request OK";
708
+ TextArtifacts.view(text, { lineStart: 1, lineEnd: 2 });
709
+ ```
710
+
711
+ Example result:
712
+
713
+ ```
714
+ "[INFO] Server started\n[INFO] Connected to DB"
715
+ ```
716
+
717
+ Character selection:
718
+
719
+ ```typescript
720
+ TextArtifacts.view("Hello, World!", { characterStart: 0, characterEnd: 5 });
721
+ ```
722
+
723
+ Example result:
724
+
725
+ ```
726
+ "Hello"
727
+ ```
728
+
729
+ ##### `TextArtifacts.minimize(text, opts?): Record<string, unknown>`
730
+
731
+ Minimize text content for display. If text is within the character limit, returns it unchanged. If over the limit, shows first and last halves with metadata.
732
+
733
+ | Parameter | Type | Required | Description |
734
+ |---|---|---|---|
735
+ | `text` | `string` | Yes | The text content to minimize |
736
+ | `opts.characterLimit` | `number` | No | Character limit (default: `50,000`) |
737
+ | `opts.tip` | `string \| null` | No | Tip string (default: `null`; pass a string to include one) |
738
+
739
+ **Returns:** `Record<string, unknown>`
740
+
741
+ Short text (under limit):
742
+
743
+ ```typescript
744
+ import { TextArtifacts } from "@a2anet/a2a-utils";
745
+
746
+ TextArtifacts.minimize("Hello, world!");
747
+ ```
748
+
749
+ ```json
750
+ {"text": "Hello, world!"}
751
+ ```
752
+
753
+ Long text (over limit):
754
+
755
+ ```typescript
756
+ TextArtifacts.minimize("x".repeat(60_000));
757
+ ```
758
+
759
+ ```json
760
+ {
761
+ "text": "xxxxxxx...\n\n[... 10,000 characters omitted ...]\n\nxxxxxxx...",
762
+ "_total_lines": 1,
763
+ "_total_characters": 60000,
764
+ "_start_line_range": "1-1",
765
+ "_end_line_range": "1-1",
766
+ "_start_character_range": "0-25000",
767
+ "_end_character_range": "35000-60000"
768
+ }
769
+ ```
770
+
771
+ #### DataArtifacts
772
+
773
+ ##### `DataArtifacts.view(data, opts?): unknown`
774
+
775
+ View structured data with optional filtering. Navigate with `jsonPath`, then filter with `rows`/`columns`.
776
+
777
+ | Parameter | Type | Required | Description |
778
+ |---|---|---|---|
779
+ | `data` | `unknown` | Yes | The data to view |
780
+ | `opts.jsonPath` | `string \| null` | No | Dot-separated path to extract specific fields |
781
+ | `opts.rows` | `number \| number[] \| string \| null` | No | Row selection |
782
+ | `opts.columns` | `string \| string[] \| null` | No | Column selection |
783
+ | `opts.characterLimit` | `number` | No | Maximum output size (default: `50,000`) |
784
+
785
+ **Returns:** `unknown` (filtered data)
786
+
787
+ ```typescript
788
+ import { DataArtifacts } from "@a2anet/a2a-utils";
789
+
790
+ const data = {
791
+ employees: [
792
+ { name: "Alice", department: "Engineering", level: 5 },
793
+ { name: "Bob", department: "Design", level: 3 },
794
+ { name: "Carol", department: "Engineering", level: 4 },
795
+ ],
796
+ };
797
+
798
+ DataArtifacts.view(data, { jsonPath: "employees", rows: "0-2", columns: ["name", "department"] });
799
+ ```
800
+
801
+ Example result:
802
+
803
+ ```json
804
+ [
805
+ {"name": "Alice", "department": "Engineering"},
806
+ {"name": "Bob", "department": "Design"}
807
+ ]
808
+ ```
809
+
810
+ ##### `DataArtifacts.minimize(data, opts?): Record<string, unknown>`
811
+
812
+ Minimize data content for display based on type. Automatically selects the best strategy: list-of-objects gets a table summary, dicts get string truncation, strings delegate to `TextArtifacts.minimize`.
813
+
814
+ | Parameter | Type | Required | Description |
815
+ |---|---|---|---|
816
+ | `data` | `unknown` | Yes | The data to minimize |
817
+ | `opts.characterLimit` | `number` | No | Character limit (default: `50,000`) |
818
+ | `opts.minimizedObjectStringLength` | `number` | No | Max string length in objects (default: `5,000`) |
819
+ | `opts.tip` | `string \| null` | No | Tip string (default: `null`; pass a string to include one) |
820
+
821
+ **Returns:** `Record<string, unknown>`
822
+
823
+ Lists of objects are summarized as table summaries (see `summarizeTable`) and lists of values as value summaries (see `summarizeValues`).
824
+
825
+ ```typescript
826
+ import { DataArtifacts } from "@a2anet/a2a-utils";
827
+
828
+ const data = {
829
+ title: "Quarterly Report Q4 2025",
830
+ summary: "x".repeat(10_000),
831
+ metrics: { revenue: 1_250_000, growth: 12.5 },
832
+ employees: Array.from({ length: 100 }, (_, i) => ({
833
+ name: `Employee ${i}`,
834
+ department: ["Eng", "Marketing", "Design", "Sales"][i % 4],
835
+ salary: 60_000 + i * 500,
836
+ })),
837
+ tags: ["finance", "quarterly", "internal"],
838
+ };
839
+
840
+ DataArtifacts.minimize(data, { characterLimit: 100, minimizedObjectStringLength: 10 });
841
+ ```
842
+
843
+ ```json
844
+ {
845
+ "data": {
846
+ "title": "Quarterly ... [14 more chars]",
847
+ "summary": "xxxxxxxxxx... [9,990 more chars]",
848
+ "metrics": {
849
+ "revenue": 1250000,
850
+ "growth": 12.5
851
+ },
852
+ "employees": {
853
+ "_total_rows": 100,
854
+ "_columns": [
855
+ {
856
+ "count": 100,
857
+ "unique_count": 100,
858
+ "types": [{
859
+ "name": "string",
860
+ "count": 100,
861
+ "percentage": 100.0,
862
+ "sample_value": "Employee 42",
863
+ "length_minimum": 10,
864
+ "length_maximum": 11,
865
+ "length_average": 10.9,
866
+ "length_stdev": 0.3
867
+ }],
868
+ "name": "name"
869
+ },
870
+ {
871
+ "count": 100,
872
+ "unique_count": 4,
873
+ "types": [{
874
+ "name": "string",
875
+ "count": 100,
876
+ "percentage": 100.0,
877
+ "sample_value": "Engineering",
878
+ "length_minimum": 5,
879
+ "length_maximum": 11,
880
+ "length_average": 7.75,
881
+ "length_stdev": 2.4
882
+ }],
883
+ "name": "department"
884
+ },
885
+ {
886
+ "count": 100,
887
+ "unique_count": 100,
888
+ "types": [{
889
+ "name": "int",
890
+ "count": 100,
891
+ "percentage": 100.0,
892
+ "sample_value": 75000,
893
+ "minimum": 60000,
894
+ "maximum": 109500,
895
+ "average": 84750,
896
+ "stdev": 14505.75
897
+ }],
898
+ "name": "salary"
899
+ }
900
+ ],
901
+ "_json_path": "employees"
902
+ },
903
+ "tags": ["finance", "quarterly", "internal"]
904
+ }
905
+ }
906
+ ```
907
+
908
+ ##### `DataArtifacts.summarizeTable(data): Record<string, unknown>[]`
909
+
910
+ Generate a summary of tabular data (array of objects). Returns one summary object per column with count, unique count, and per-type statistics.
911
+
912
+ | Parameter | Type | Required | Description |
913
+ |---|---|---|---|
914
+ | `data` | `Record<string, unknown>[]` | Yes | Table rows |
915
+
916
+ **Returns:** `Record<string, unknown>[]`
917
+
918
+ ```typescript
919
+ import { DataArtifacts } from "@a2anet/a2a-utils";
920
+
921
+ const data = Array.from({ length: 100 }, (_, i) => ({
922
+ name: `Employee ${i}`,
923
+ department: ["Eng", "Marketing", "Design", "Sales"][i % 4],
924
+ salary: 60_000 + i * 500,
925
+ }));
926
+
927
+ DataArtifacts.summarizeTable(data);
928
+ ```
929
+
930
+ ```json
931
+ [
932
+ {
933
+ "count": 100,
934
+ "unique_count": 100,
935
+ "types": [
936
+ {
937
+ "name": "string",
938
+ "count": 100,
939
+ "percentage": 100.0,
940
+ "sample_value": "Employee 42",
941
+ "length_minimum": 10,
942
+ "length_maximum": 11,
943
+ "length_average": 10.9,
944
+ "length_stdev": 0.3
945
+ }
946
+ ],
947
+ "name": "name"
948
+ },
949
+ {
950
+ "count": 100,
951
+ "unique_count": 4,
952
+ "types": [
953
+ {
954
+ "name": "string",
955
+ "count": 100,
956
+ "percentage": 100.0,
957
+ "sample_value": "Engineering",
958
+ "length_minimum": 5,
959
+ "length_maximum": 11,
960
+ "length_average": 7.75,
961
+ "length_stdev": 2.4
962
+ }
963
+ ],
964
+ "name": "department"
965
+ },
966
+ {
967
+ "count": 100,
968
+ "unique_count": 100,
969
+ "types": [
970
+ {
971
+ "name": "int",
972
+ "count": 100,
973
+ "percentage": 100.0,
974
+ "sample_value": 75000,
975
+ "minimum": 60000,
976
+ "maximum": 109500,
977
+ "average": 84750,
978
+ "stdev": 14505.75
979
+ }
980
+ ],
981
+ "name": "salary"
982
+ }
983
+ ]
984
+ ```
985
+
986
+ ##### `DataArtifacts.summarizeValues(values): Record<string, unknown> | unknown[]`
987
+
988
+ Generate statistics for a list of values (like a single column). Includes count, unique count, and per-type statistics (min/max/avg/stdev for numbers, length stats for strings, etc.). If the summary would be larger than the original values, the original list is returned instead (inflation guard).
989
+
990
+ | Parameter | Type | Required | Description |
991
+ |---|---|---|---|
992
+ | `values` | `unknown[]` | Yes | Values to summarize |
993
+
994
+ **Returns:** `Record<string, unknown> | unknown[]`
995
+
996
+ ```typescript
997
+ import { DataArtifacts } from "@a2anet/a2a-utils";
998
+
999
+ const salaries = [
1000
+ 95000, 72000, 105000, 68000, 88000,
1001
+ // ... ~100 salary values total, with some nulls
1002
+ null, 115000, 92000, null, 78000,
1003
+ ];
1004
+
1005
+ DataArtifacts.summarizeValues(salaries);
1006
+ ```
1007
+
1008
+ ```json
1009
+ {
1010
+ "count": 100,
1011
+ "unique_count": 87,
1012
+ "types": [
1013
+ {
1014
+ "name": "int",
1015
+ "count": 92,
1016
+ "percentage": 92.0,
1017
+ "sample_value": 95000,
1018
+ "minimum": 45000,
1019
+ "maximum": 185000,
1020
+ "average": 87250.5,
1021
+ "stdev": 28430.12
1022
+ },
1023
+ {
1024
+ "name": "null",
1025
+ "count": 8,
1026
+ "percentage": 8.0,
1027
+ "sample_value": null
1028
+ }
1029
+ ]
1030
+ }
1031
+ ```
1032
+
1033
+ #### `minimizeArtifacts(artifacts, opts?): ArtifactForLLM[]`
1034
+
1035
+ Minimize a list of artifacts for LLM display. Called automatically by `A2ATools.sendMessage`. Combines all TextParts within each artifact into a single [`TextPartForLLM`](#textpartforllm). Handles `FilePart`s by including file metadata and saved paths.
1036
+
1037
+ | Parameter | Type | Required | Description |
1038
+ |---|---|---|---|
1039
+ | `artifacts` | `Artifact[]` | Yes | List of artifacts to minimize |
1040
+ | `opts.characterLimit` | `number` | No | Character limit (default: `50,000`) |
1041
+ | `opts.minimizedObjectStringLength` | `number` | No | Max string length in objects (default: `5,000`) |
1042
+ | `opts.savedFilePaths` | `Record<string, string[]> \| null` | No | Mapping of artifactId to saved file paths |
1043
+ | `opts.textTip` | `string \| null` | No | Tip string for minimized text artifacts (default: `null`) |
1044
+ | `opts.dataTip` | `string \| null` | No | Tip string for minimized data artifacts (default: `null`) |
1045
+
1046
+ **Returns:** [`ArtifactForLLM`](#artifactforllm)`[]`
1047
+
1048
+ ```typescript
1049
+ import type { Artifact } from "@a2a-js/sdk";
1050
+ import { minimizeArtifacts } from "@a2anet/a2a-utils";
1051
+
1052
+ const artifacts: Artifact[] = [
1053
+ {
1054
+ artifactId: "art-123",
1055
+ description: "Full text of a research paper abstract spanning several pages.",
1056
+ name: "Research Paper Abstract",
1057
+ parts: [{ kind: "text", text: "x".repeat(60_000) }],
1058
+ },
1059
+ {
1060
+ artifactId: "art-456",
1061
+ description: "Company employee directory with names, departments, and salaries.",
1062
+ name: "Employee Directory",
1063
+ parts: [{
1064
+ kind: "data",
1065
+ data: Array.from({ length: 100 }, (_, i) => ({
1066
+ name: `Employee ${i}`,
1067
+ department: ["Eng", "Marketing", "Design", "Sales"][i % 4],
1068
+ salary: 60_000 + i * 500,
1069
+ })),
1070
+ }],
1071
+ },
1072
+ {
1073
+ artifactId: "art-789",
1074
+ description: "Generated quarterly financial report in PDF format.",
1075
+ name: "Quarterly Report",
1076
+ parts: [
1077
+ {
1078
+ kind: "file",
1079
+ file: {
1080
+ name: "q4-report.pdf",
1081
+ mimeType: "application/pdf",
1082
+ bytes: "base64encodeddata...",
1083
+ },
1084
+ },
1085
+ ],
1086
+ },
1087
+ ];
1088
+
1089
+ const minimized = minimizeArtifacts(artifacts, {
1090
+ textTip: "Text was minimized. Call viewTextArtifact() to see specific line ranges.",
1091
+ dataTip: "Data was minimized. Call viewDataArtifact() to navigate to specific data.",
1092
+ savedFilePaths: { "art-789": ["./storage/files/task-123/art-789/q4-report.pdf"] },
1093
+ });
1094
+ ```
1095
+
1096
+ Example result:
1097
+
1098
+ ```json
1099
+ [
1100
+ {
1101
+ "artifactId": "art-123",
1102
+ "description": "Full text of a research paper abstract spanning several pages.",
1103
+ "name": "Research Paper Abstract",
1104
+ "parts": [
1105
+ {
1106
+ "kind": "text",
1107
+ "text": "xxxxxxx...\n\n[... 10,000 characters omitted ...]\n\nxxxxxxx..."
1108
+ }
1109
+ ]
1110
+ },
1111
+ {
1112
+ "artifactId": "art-456",
1113
+ "description": "Company employee directory with names, departments, and salaries.",
1114
+ "name": "Employee Directory",
1115
+ "parts": [
1116
+ {
1117
+ "kind": "data",
1118
+ "data": {
1119
+ "data": {
1120
+ "_total_rows": 100,
1121
+ "_columns": ["..."],
1122
+ "_tip": "Data was minimized. Call viewDataArtifact() to navigate to specific data."
1123
+ }
1124
+ }
1125
+ }
1126
+ ]
1127
+ },
1128
+ {
1129
+ "artifactId": "art-789",
1130
+ "description": "Generated quarterly financial report in PDF format.",
1131
+ "name": "Quarterly Report",
1132
+ "parts": [
1133
+ {
1134
+ "kind": "file",
1135
+ "name": "q4-report.pdf",
1136
+ "mimeType": "application/pdf",
1137
+ "uri": null,
1138
+ "bytes": {
1139
+ "_saved_to": ["./storage/files/task-123/art-789/q4-report.pdf"]
1140
+ }
1141
+ }
1142
+ ]
1143
+ }
1144
+ ]
1145
+ ```
1146
+
1147
+ ### 📋 Types
1148
+
1149
+ All types are readonly interfaces exported from `@a2anet/a2a-utils`.
1150
+
1151
+ #### `AgentURLAndCustomHeaders`
1152
+
1153
+ Returned by `AgentManager.getAgent()` and `AgentManager.getAgents()`.
1154
+
1155
+ ```typescript
1156
+ const agent: AgentURLAndCustomHeaders = {
1157
+ agentCard: {
1158
+ name: "Universal Translator",
1159
+ description: "Translate text and audio between 50+ languages",
1160
+ url: "https://translate.example.com",
1161
+ version: "1.0.0",
1162
+ capabilities: { streaming: false, pushNotifications: false },
1163
+ skills: [
1164
+ {
1165
+ id: "translate-text",
1166
+ name: "Translate Text",
1167
+ description: "Translate text between any supported language pair",
1168
+ tags: ["translate", "text", "language"],
1169
+ examples: ["Translate 'hello' to French"],
1170
+ },
1171
+ {
1172
+ id: "translate-audio",
1173
+ name: "Translate Audio",
1174
+ description: "Translate audio between any supported language pair",
1175
+ tags: ["translate", "audio", "language"],
1176
+ },
1177
+ ],
1178
+ defaultInputModes: ["text", "audio/mpeg"],
1179
+ defaultOutputModes: ["text", "audio/mpeg"],
1180
+ },
1181
+ customHeaders: { Authorization: "Bearer tok_123" },
1182
+ };
1183
+ ```
1184
+
1185
+ | Field | Type |
1186
+ |---|---|
1187
+ | `agentCard` | `AgentCard` |
1188
+ | `customHeaders` | `Record<string, string>` |
1189
+
1190
+ #### `TaskForLLM`
1191
+
1192
+ Returned by `A2ATools.sendMessage()` for task responses.
1193
+
1194
+ ```typescript
1195
+ const task: TaskForLLM = {
1196
+ id: "task-123",
1197
+ contextId: "ctx-456",
1198
+ kind: "task",
1199
+ status: {
1200
+ state: "completed",
1201
+ message: {
1202
+ contextId: "ctx-456",
1203
+ kind: "message",
1204
+ parts: [
1205
+ {
1206
+ kind: "text",
1207
+ text: "I found three recent papers on quantum computing and retrieved the abstract for the most recent one.",
1208
+ },
1209
+ ],
1210
+ },
1211
+ },
1212
+ artifacts: [
1213
+ {
1214
+ artifactId: "art-789",
1215
+ description: "Search results for quantum computing papers",
1216
+ name: "Search Results",
1217
+ parts: [
1218
+ {
1219
+ kind: "data",
1220
+ data: [
1221
+ {
1222
+ title: "Quantum Error Correction Advances",
1223
+ year: 2025,
1224
+ authors: "Chen et al.",
1225
+ },
1226
+ {
1227
+ title: "Topological Quantum Computing Survey",
1228
+ year: 2024,
1229
+ authors: "Nakamura et al.",
1230
+ },
1231
+ {
1232
+ title: "Fault-Tolerant Logical Qubits",
1233
+ year: 2024,
1234
+ authors: "Wang et al.",
1235
+ },
1236
+ ],
1237
+ },
1238
+ ],
1239
+ },
1240
+ {
1241
+ artifactId: "art-790",
1242
+ description: "Abstract of 'Quantum Error Correction Advances' by Chen et al.",
1243
+ name: "Abstract",
1244
+ parts: [
1245
+ {
1246
+ kind: "text",
1247
+ text: "Quantum computing has seen rapid advances in error correction.\nRecent work demonstrates fault-tolerant logical qubits at scale.\nThis paper surveys progress in quantum error correction from 2023-2025.\nWe review surface codes, color codes, and novel hybrid approaches.\nKey results include a 10x reduction in logical error rates.\nThese improvements bring practical quantum computing closer to reality.\nWe also discuss remaining challenges in qubit connectivity.\nFinally, we outline a roadmap for achieving fault-tolerant quantum computation.",
1248
+ },
1249
+ ],
1250
+ },
1251
+ ],
1252
+ };
1253
+ ```
1254
+
1255
+ | Field | Type |
1256
+ |---|---|
1257
+ | `id` | `string` |
1258
+ | `contextId` | `string` |
1259
+ | `kind` | `string` (`"task"`) |
1260
+ | `status` | [`TaskStatusForLLM`](#taskstatusforllm) |
1261
+ | `artifacts` | [`ArtifactForLLM`](#artifactforllm)`[]` |
1262
+
1263
+ #### `MessageForLLM`
1264
+
1265
+ Returned by `A2ATools.sendMessage()` for message-only responses, or as `TaskStatusForLLM.message`.
1266
+
1267
+ ```typescript
1268
+ const message: MessageForLLM = {
1269
+ contextId: "ctx-456",
1270
+ kind: "message",
1271
+ parts: [
1272
+ {
1273
+ kind: "text",
1274
+ text: "I found three recent papers on quantum computing and retrieved the abstract for the most recent one.",
1275
+ },
1276
+ ],
1277
+ };
1278
+ ```
1279
+
1280
+ | Field | Type |
1281
+ |---|---|
1282
+ | `contextId` | `string \| null` |
1283
+ | `kind` | `string` (`"message"`) |
1284
+ | `parts` | ([`TextPartForLLM`](#textpartforllm) \| [`DataPartForLLM`](#datapartforllm) \| [`FilePartForLLM`](#filepartforllm))[] |
1285
+
1286
+ #### `TaskStatusForLLM`
1287
+
1288
+ ```typescript
1289
+ const taskStatus: TaskStatusForLLM = {
1290
+ state: "completed",
1291
+ message: {
1292
+ contextId: "ctx-456",
1293
+ kind: "message",
1294
+ parts: [
1295
+ {
1296
+ kind: "text",
1297
+ text: "I found three recent papers on quantum computing and retrieved the abstract for the most recent one.",
1298
+ },
1299
+ ],
1300
+ },
1301
+ };
1302
+ ```
1303
+
1304
+ | Field | Type |
1305
+ |---|---|
1306
+ | `state` | `TaskState` |
1307
+ | `message` | [`MessageForLLM`](#messageforllm) `\| null` |
1308
+
1309
+ #### `ArtifactForLLM`
1310
+
1311
+ Returned by `viewTextArtifact()`, `viewDataArtifact()`, and `minimizeArtifacts()`. Used in `TaskForLLM.artifacts`.
1312
+
1313
+ ```typescript
1314
+ const artifact: ArtifactForLLM = {
1315
+ artifactId: "art-790",
1316
+ description: "Abstract of 'Quantum Error Correction Advances' by Chen et al.",
1317
+ name: "Abstract",
1318
+ parts: [
1319
+ {
1320
+ kind: "text",
1321
+ text: "Quantum computing has seen rapid advances in error correction.\nRecent work demonstrates fault-tolerant logical qubits at scale.\nThis paper surveys progress in quantum error correction from 2023-2025.\nWe review surface codes, color codes, and novel hybrid approaches.\nKey results include a 10x reduction in logical error rates.\nThese improvements bring practical quantum computing closer to reality.\nWe also discuss remaining challenges in qubit connectivity.\nFinally, we outline a roadmap for achieving fault-tolerant quantum computation.",
1322
+ },
1323
+ ],
1324
+ };
1325
+ ```
1326
+
1327
+ | Field | Type |
1328
+ |---|---|
1329
+ | `artifactId` | `string` |
1330
+ | `description` | `string \| null` |
1331
+ | `name` | `string \| null` |
1332
+ | `parts` | ([`TextPartForLLM`](#textpartforllm) \| [`DataPartForLLM`](#datapartforllm) \| [`FilePartForLLM`](#filepartforllm))[] |
1333
+
1334
+ #### `TextPartForLLM`
1335
+
1336
+ ```typescript
1337
+ const textPart: TextPartForLLM = {
1338
+ kind: "text",
1339
+ text: "Quantum computing has seen rapid advances in error correction.\nRecent work demonstrates fault-tolerant logical qubits at scale.\nThis paper surveys progress in quantum error correction from 2023-2025.",
1340
+ };
1341
+ ```
1342
+
1343
+ | Field | Type |
1344
+ |---|---|
1345
+ | `kind` | `string` (`"text"`) |
1346
+ | `text` | `string` |
1347
+
1348
+ #### `DataPartForLLM`
1349
+
1350
+ ```typescript
1351
+ const dataPart: DataPartForLLM = {
1352
+ kind: "data",
1353
+ data: [
1354
+ {
1355
+ title: "Quantum Error Correction Advances",
1356
+ year: 2025,
1357
+ authors: "Chen et al.",
1358
+ },
1359
+ {
1360
+ title: "Topological Quantum Computing Survey",
1361
+ year: 2024,
1362
+ authors: "Nakamura et al.",
1363
+ },
1364
+ {
1365
+ title: "Fault-Tolerant Logical Qubits",
1366
+ year: 2024,
1367
+ authors: "Wang et al.",
1368
+ },
1369
+ ],
1370
+ };
1371
+ ```
1372
+
1373
+ | Field | Type |
1374
+ |---|---|
1375
+ | `kind` | `string` (`"data"`) |
1376
+ | `data` | `unknown` |
1377
+
1378
+ #### `FilePartForLLM`
1379
+
1380
+ Represents a file part in artifacts and messages. `uri` and `bytes` are mutually exclusive — at most one is set.
1381
+
1382
+ ```typescript
1383
+ const filePart: FilePartForLLM = {
1384
+ kind: "file",
1385
+ name: "q4-report.pdf",
1386
+ mimeType: "application/pdf",
1387
+ uri: null,
1388
+ bytes: {
1389
+ _saved_to: [
1390
+ "./storage/files/task-123/art-789/q4-report.pdf",
1391
+ ],
1392
+ },
1393
+ };
1394
+ ```
1395
+
1396
+ | Field | Type | Description |
1397
+ |---|---|---|
1398
+ | `kind` | `string` (`"file"`) | Always `"file"` |
1399
+ | `name` | `string \| null` | Filename from the original FilePart |
1400
+ | `mimeType` | `string \| null` | MIME type from the original FilePart |
1401
+ | `uri` | `string \| Record<string, unknown> \| null` | Raw URI (no FileStore) or `{"_saved_to": [...]}` (FileStore saved it) |
1402
+ | `bytes` | `Record<string, unknown> \| null` | `{"_saved_to": [...]}` (FileStore saved it) or `{"_error": "..."}` (no FileStore) |
1403
+
1404
+ ## 📄 License
1405
+
1406
+ `@a2anet/a2a-utils` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
1407
+
1408
+ ## 🤝 Join the A2A Net Community
1409
+
1410
+ A2A Net is a site to find and share AI agents and open-source community.
1411
+
1412
+ - 🌍 Site: [A2A Net](https://a2anet.com)
1413
+ - 🤖 Discord: [Join the Discord](https://discord.gg/674NGXpAjU)