@microsoft/teams.a2a 2.0.0-preview.3

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 (44) hide show
  1. package/README.md +180 -0
  2. package/dist/chat-prompt/plugin.d.ts +24 -0
  3. package/dist/chat-prompt/plugin.js +153 -0
  4. package/dist/chat-prompt/types.d.ts +60 -0
  5. package/dist/chat-prompt/types.js +3 -0
  6. package/dist/client/agent-client.d.ts +58 -0
  7. package/dist/client/agent-client.js +177 -0
  8. package/dist/client/agent-manager.d.ts +57 -0
  9. package/dist/client/agent-manager.js +136 -0
  10. package/dist/client/agent-task-store.d.ts +25 -0
  11. package/dist/client/agent-task-store.js +47 -0
  12. package/dist/common/schema.d.ts +728 -0
  13. package/dist/common/schema.js +26 -0
  14. package/dist/common/type-utils.d.ts +11 -0
  15. package/dist/common/type-utils.js +3 -0
  16. package/dist/common/uuid.d.ts +1 -0
  17. package/dist/common/uuid.js +12 -0
  18. package/dist/index.d.ts +10 -0
  19. package/dist/index.js +50 -0
  20. package/dist/server/middleware/isTaskRequest.d.ts +2 -0
  21. package/dist/server/middleware/isTaskRequest.js +32 -0
  22. package/dist/server/plugin.d.ts +49 -0
  23. package/dist/server/plugin.js +130 -0
  24. package/dist/server/plugin.on-get-request.d.ts +3 -0
  25. package/dist/server/plugin.on-get-request.js +17 -0
  26. package/dist/server/plugin.on-send-request.d.ts +9 -0
  27. package/dist/server/plugin.on-send-request.js +107 -0
  28. package/dist/server/serverUtils.d.ts +13 -0
  29. package/dist/server/serverUtils.js +65 -0
  30. package/dist/server/tasks/task-manager.d.ts +22 -0
  31. package/dist/server/tasks/task-manager.js +205 -0
  32. package/dist/server/tasks/task-store.d.ts +8 -0
  33. package/dist/server/tasks/task-store.js +18 -0
  34. package/dist/server/tasks/task-utilities.d.ts +27 -0
  35. package/dist/server/tasks/task-utilities.js +139 -0
  36. package/dist/server/tasks/task-utils.d.ts +22 -0
  37. package/dist/server/tasks/task-utils.js +38 -0
  38. package/dist/server/types/a2a-error.d.ts +23 -0
  39. package/dist/server/types/a2a-error.js +95 -0
  40. package/dist/server/types/a2a-types.d.ts +56 -0
  41. package/dist/server/types/a2a-types.js +3 -0
  42. package/dist/server/types/event-types.d.ts +24 -0
  43. package/dist/server/types/event-types.js +3 -0
  44. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,180 @@
1
+ # Teams: a2a
2
+
3
+ <p>
4
+ <a href="https://www.npmjs.com/package/@microsoft/teams.a2a" target="_blank">
5
+ <img src="https://img.shields.io/npm/v/@microsoft/teams.a2a" />
6
+ </a>
7
+ <a href="https://www.npmjs.com/package/@microsoft/teams.a2a?activeTab=code" target="_blank">
8
+ <img src="https://img.shields.io/bundlephobia/min/@microsoft/teams.a2a" />
9
+ </a>
10
+ <a href="https://www.npmjs.com/package/@microsoft/teams.a2a?activeTab=dependencies" target="_blank">
11
+ <img src="https://img.shields.io/librariesio/release/npm/@microsoft/teams.a2a" />
12
+ </a>
13
+ <a href="https://www.npmjs.com/package/@microsoft/teams.a2a" target="_blank">
14
+ <img src="https://img.shields.io/npm/dw/@microsoft/teams.a2a" />
15
+ </a>
16
+ <a href="https://microsoft.github.io/teams.ts" target="_blank">
17
+ <img src="https://img.shields.io/badge/📖 docs-open-blue" />
18
+ </a>
19
+ </p>
20
+
21
+ This is a plugin that enables your Teams agent to be used as an A2A agent.
22
+
23
+ > [!NOTE]
24
+ > The A2A protocol is still early in development and hence this package is fairly experimental.
25
+
26
+ - [What is A2A?](https://google.github.io/A2A)
27
+
28
+ ## Server
29
+
30
+ Teams AI Library allows your applications to easily be accessible via Teams. However, using this plugin, you can also enable your agent to be used as an A2A agent so that it can be used by other A2A clients.
31
+
32
+ ### Configuration
33
+
34
+ Configuring the App to use the A2APlugin simply requires the `AgentCard`.
35
+
36
+ ```ts
37
+ import { schema, A2APlugin } from "@microsoft/teams.a2a";
38
+ import { App } from "@microsoft/teams.apps";
39
+
40
+ declare const myAgentCard: AgentCard;
41
+
42
+ const app = new App({
43
+ plugins: [
44
+ new A2APlugin({
45
+ agentCard: myAgentCard,
46
+ }),
47
+ ],
48
+ });
49
+ ```
50
+
51
+ With this simple configuration, the A2APlugin will listen for A2A requests on the `/a2a` path and return the agent card when requested.
52
+
53
+ ### Agent Card
54
+
55
+ The plugin automatically exposes the agent card at the path `/.well-known/agent.json`.
56
+
57
+ ```mermaid
58
+ sequenceDiagram
59
+ participant A2A Client
60
+ participant App
61
+ participant A2APlugin
62
+ A2A Client->>App: /.well-known/agent.json
63
+ App->>A2APlugin: Call A2APlugin
64
+ A2APlugin->>A2A Client: Return agent card
65
+ ```
66
+
67
+ ### A2A Requests
68
+
69
+ ```mermaid
70
+ sequenceDiagram
71
+ participant A2A Client
72
+ participant App
73
+ participant A2APlugin
74
+ participant YourEventHandler
75
+ A2A Client->>App: /task/send
76
+ App->>A2APlugin: Call A2APlugin
77
+ A2APlugin->>YourEventHandler: Call your event handler a2a:message
78
+ YourEventHandler->>A2APlugin: Call respond
79
+ A2APlugin->>A2A Client: Return response
80
+ ```
81
+
82
+ Handling A2A requests is similar to handling app-requests. Simply add an event handler for the `a2a:message` event. You may `accumulateArtifacts` to iteratively accumulate artifacts for the task, or simply `respond` with the final result.
83
+
84
+ > [!NOTE]
85
+ > You must have only a single handler that calls `respond`. And you **must** call `respond` as the last step in your handler. This is because the `respond` function resolves the open request to the caller.
86
+
87
+ ```ts
88
+ app.event(
89
+ "a2a:message",
90
+ async ({ taskContext, respond, accumulateArtifacts }) => {
91
+ // The taskContext contains details about the task request
92
+ const result = await myEventHandler(taskContext, accumulateArtifacts);
93
+ await respond(result);
94
+ }
95
+ );
96
+ ```
97
+
98
+ ## Client
99
+
100
+ The A2A client is able to call different A2A servers. You are able to use the `AgentManager` to call different A2A Servers.
101
+
102
+ ```ts
103
+ import { AgentManager } from "@microsoft/teams.a2a";
104
+
105
+ const agentManager = new AgentManager();
106
+
107
+ agentManager.use("my-agent", "https://my-agent.com/a2a");
108
+ await agentManager.sendTask("my-agent", {
109
+ id: continueTaskId || generateRequestId().toString(),
110
+ message: {
111
+ role: 'user',
112
+ parts: [{ type: 'text' as const, text: message }],
113
+ },
114
+ {},
115
+ });
116
+ ```
117
+
118
+ If you are using the `A2APlugin` described above, you can use the `clientManger` property in that plugin object to get an instance of the `AgentManager` and use it to send tasks proactively to different A2A servers.
119
+
120
+ ### Chat Prompt
121
+
122
+ A2A is most effective when used with an LLM. The `A2AClientPlugin` can be used to add a plugin to your chat prompt that will allow you to automatically include A2A agents as a possible source of interaction. The interaction can be outlined as below:
123
+
124
+ ```mermaid
125
+ sequenceDiagram
126
+ participant User
127
+ participant ChatPrompt
128
+ participant A2AClientPlugin
129
+ participant AgentManager
130
+ participant AgentClient
131
+ participant LLM
132
+ participant TargetAgent
133
+
134
+ alt config
135
+ User->>ChatPrompt: "use" with A2A server details
136
+ ChatPrompt->>A2AClientPlugin: configure usable a2a server
137
+ A2AClientPlugin->>AgentManager: register new potential client
138
+ end
139
+ alt send
140
+ User->>ChatPrompt: Send initial message
141
+ ChatPrompt->>A2AClientPlugin: configure system prompt
142
+ A2AClientPlugin->>AgentManager: get agent cards
143
+ AgentManager->>AgentClient: for each get agent card
144
+ AgentClient-->>AgentManager: agent card
145
+ AgentManager-->>A2AClientPlugin: all agent cards
146
+ A2AClientPlugin-->>ChatPrompt: updated system prompt
147
+ ChatPrompt->>A2AClientPlugin: configure tool-calls (onBuildFunctions)
148
+ A2AClientPlugin-->>ChatPrompt: Configured tool calls
149
+ ChatPrompt->>LLM: send-message
150
+ LLM-->>ChatPrompt: Call A2A TargetAgent
151
+ ChatPrompt->>A2AClientPlugin: Handler for calling A2A TargetAgent
152
+ A2AClientPlugin->>AgentManager: Call TargetAgent with message
153
+ AgentManager->>AgentClient: Call TargetAgent with message
154
+ TargetAgent-->>AgentClient: Return task (e.g., completed, input-required)
155
+ AgentClient->>AgentManager: Result task
156
+ AgentManager->>A2AClientPlugin: Result task
157
+ A2AClientPlugin->>ChatPrompt: Result task
158
+ ChatPrompt-->>User: Respond with final result or follow-up
159
+ end
160
+ ```
161
+
162
+ Usage:
163
+
164
+ ```ts
165
+ import { A2APlugin } from "@microsoft/teams.a2a";
166
+ import { ChatPrompt } from "@microsoft/teams.ai";
167
+
168
+ const plugin = new A2APlugin();
169
+
170
+ const chatPrompt = new ChatPrompt({
171
+ plugins: [plugin],
172
+ }).usePlugin("a2a", {
173
+ key: "my-agent",
174
+ url: "https://my-agent.com/a2a",
175
+ });
176
+
177
+ const result = await chatPrompt.sendMessage("Hello, world!");
178
+
179
+ console.log(result);
180
+ ```
@@ -0,0 +1,24 @@
1
+ import { Function as ChatFunction, ChatPromptPlugin } from '@microsoft/teams.ai';
2
+ import { AgentManager } from '../client/agent-manager';
3
+ import * as schema from '../common/schema';
4
+ import { A2APluginOptions, A2APluginUseParams, BuildFunctionMetadata, BuildPrompt, BuildTaskSendParams } from './types';
5
+ export declare class A2AClientPlugin implements ChatPromptPlugin<'a2a', A2APluginUseParams> {
6
+ readonly name = "a2a";
7
+ protected _manager: AgentManager;
8
+ protected buildFunctionMetadata?: BuildFunctionMetadata;
9
+ protected buildPrompt?: BuildPrompt;
10
+ protected buildTaskSendParams?: BuildTaskSendParams;
11
+ protected _agentConfig: Map<string, Partial<A2APluginUseParams>>;
12
+ constructor(options?: A2APluginOptions);
13
+ onUsePlugin(args: A2APluginUseParams): void;
14
+ onBuildFunctions(functions: ChatFunction[]): Promise<ChatFunction[]>;
15
+ /**
16
+ * Modify the system prompt before it is sent to the model.
17
+ * If the user supplies a buildPrompt function, it is used. Otherwise, a default is built.
18
+ */
19
+ onBuildPrompt(systemPrompt: string | undefined): Promise<string | undefined>;
20
+ private _defaultFunctionMetadata;
21
+ private _defaultBuildPrompt;
22
+ private _defaultBuildTaskSendParams;
23
+ }
24
+ export declare const buildTaskSendParams: (message: string, metadata?: Record<string, any>, continueTaskId?: string | null) => schema.TaskSendParams;
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildTaskSendParams = exports.A2AClientPlugin = void 0;
7
+ const camelcase_1 = __importDefault(require("camelcase"));
8
+ const agent_manager_1 = require("../client/agent-manager");
9
+ const uuid_1 = require("../common/uuid");
10
+ class A2AClientPlugin {
11
+ name = 'a2a';
12
+ _manager;
13
+ buildFunctionMetadata;
14
+ buildPrompt;
15
+ buildTaskSendParams;
16
+ _agentConfig = new Map();
17
+ constructor(options = {}) {
18
+ this._manager = options.manager instanceof agent_manager_1.AgentManager ? options.manager : new agent_manager_1.AgentManager(options.manager);
19
+ this.buildFunctionMetadata = options.buildFunctionMetadata;
20
+ this.buildPrompt = options.buildPrompt;
21
+ this.buildTaskSendParams = options.buildTaskSendParams;
22
+ }
23
+ onUsePlugin(args) {
24
+ this._manager.use(args.key, args.url, args.agentCard);
25
+ // Store per-agent config (excluding agentCard and url)
26
+ const { key, url, agentCard, ...rest } = args;
27
+ this._agentConfig.set(key, rest);
28
+ }
29
+ async onBuildFunctions(functions) {
30
+ const cards = await this._manager.getAgentCards();
31
+ const allFunctions = [];
32
+ for (const cardWithMeta of cards) {
33
+ if (!cardWithMeta) {
34
+ continue;
35
+ }
36
+ const { key, card } = cardWithMeta;
37
+ const agentConfig = this._agentConfig.get(key) || {};
38
+ const buildFunctionMetadata = agentConfig.buildFunctionMetadata ||
39
+ this.buildFunctionMetadata ||
40
+ this._defaultFunctionMetadata;
41
+ const buildTaskSendParams = agentConfig.buildTaskSendParams ||
42
+ this.buildTaskSendParams ||
43
+ this._defaultBuildTaskSendParams;
44
+ const { name, description } = buildFunctionMetadata(card);
45
+ allFunctions.push({
46
+ name,
47
+ description,
48
+ parameters: {
49
+ type: 'object',
50
+ properties: {
51
+ message: {
52
+ type: 'string',
53
+ description: 'Message to send to the agent',
54
+ },
55
+ continueTaskId: {
56
+ type: 'string',
57
+ description: 'If provided, continue an existing task with this ID (string). Otherwise send null or NONE to indicate a new task.',
58
+ },
59
+ },
60
+ required: ['message'],
61
+ },
62
+ handler: async (args) => {
63
+ const agentMessage = args.message;
64
+ if (!agentMessage) {
65
+ throw new Error(`An input message is required to call Agent ${name}!`);
66
+ }
67
+ const continueTaskId = args.continueTaskId != null
68
+ ? args.continueTaskId.toLowerCase() === 'none'
69
+ ? null
70
+ : args.continueTaskId || null
71
+ : null;
72
+ const sendParams = buildTaskSendParams(card, agentMessage, continueTaskId);
73
+ const result = await this._manager.sendTask(key, sendParams);
74
+ return result;
75
+ },
76
+ });
77
+ }
78
+ return functions.concat(allFunctions);
79
+ }
80
+ /**
81
+ * Modify the system prompt before it is sent to the model.
82
+ * If the user supplies a buildPrompt function, it is used. Otherwise, a default is built.
83
+ */
84
+ async onBuildPrompt(systemPrompt) {
85
+ const cardsWithMeta = await this._manager.getAgentCards();
86
+ // Lookup latest tasks for all agents first
87
+ const agentsWithLatestTask = [];
88
+ for (const cardWithMeta of cardsWithMeta) {
89
+ if (!cardWithMeta) {
90
+ continue;
91
+ }
92
+ const { key, card } = cardWithMeta;
93
+ const latestTask = await this._manager.getLatestTask(key);
94
+ agentsWithLatestTask.push({ card, latestTask });
95
+ }
96
+ // If the user supplied a buildPrompt, use it
97
+ if (this.buildPrompt) {
98
+ return this.buildPrompt(systemPrompt, agentsWithLatestTask);
99
+ }
100
+ const prompt = (systemPrompt || '') +
101
+ '\n' +
102
+ this._defaultBuildPrompt(agentsWithLatestTask);
103
+ return prompt;
104
+ }
105
+ _defaultFunctionMetadata(card) {
106
+ const name = `message${(0, camelcase_1.default)(card.name, { pascalCase: true })}`;
107
+ const description = card.description || `Interact with agent at ${card.url}`;
108
+ return { name, description };
109
+ }
110
+ _defaultBuildPrompt(agentDetails) {
111
+ let details = 'Here are details about available agents that you can message. Determine the best phrasing to use when you are attempting to message them.';
112
+ for (const { card, latestTask } of agentDetails) {
113
+ details += '<Agent Details>\n';
114
+ details += `<Name>\n${card.name || card.url}\n</Name>\n`;
115
+ if (card.description) {
116
+ details += `<Description>\n${card.description}\n</Description>\n`;
117
+ }
118
+ for (const skill of card.skills || []) {
119
+ details += `<SKILL name=${skill.name} description=${skill.description} />\n`;
120
+ if (skill.examples) {
121
+ details += `<EXAMPLES>\n${skill.examples.join('\n')}\n</EXAMPLES>\n`;
122
+ }
123
+ details += '</SKILL>\n';
124
+ }
125
+ if (latestTask) {
126
+ const lastMessage = latestTask.history && latestTask.history.length > 0
127
+ ? latestTask.history[latestTask.history.length - 1].parts
128
+ .map((p) => p.type === 'text' ? p.text : '[non-text]')
129
+ .join(' ')
130
+ : '';
131
+ details += `<PREVIOUS_TASK_DETAILS taskId=${latestTask.task.id} state=${latestTask.task.status.state} lastMessage=${lastMessage}\n</PREVIOUS_TASK_DETAILS>`;
132
+ }
133
+ details += '</Agent Details>\n';
134
+ }
135
+ return details;
136
+ }
137
+ _defaultBuildTaskSendParams(_card, message, continueTaskId, metadata) {
138
+ return (0, exports.buildTaskSendParams)(message, metadata, continueTaskId);
139
+ }
140
+ }
141
+ exports.A2AClientPlugin = A2AClientPlugin;
142
+ const buildTaskSendParams = (message, metadata, continueTaskId) => {
143
+ return {
144
+ id: continueTaskId || (0, uuid_1.generateRequestId)().toString(),
145
+ message: {
146
+ role: 'user',
147
+ parts: [{ type: 'text', text: message }],
148
+ },
149
+ metadata,
150
+ };
151
+ };
152
+ exports.buildTaskSendParams = buildTaskSendParams;
153
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NoYXQtcHJvbXB0L3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwwREFBa0M7QUFPbEMsMkRBQTZFO0FBRTdFLHlDQUFtRDtBQVduRCxNQUFhLGVBQWU7SUFFakIsSUFBSSxHQUFHLEtBQUssQ0FBQztJQUNaLFFBQVEsQ0FBZTtJQUN2QixxQkFBcUIsQ0FBeUI7SUFDOUMsV0FBVyxDQUFlO0lBQzFCLG1CQUFtQixDQUF1QjtJQUMxQyxZQUFZLEdBQTZDLElBQUksR0FBRyxFQUFFLENBQUM7SUFFN0UsWUFBWSxVQUE0QixFQUFFO1FBQ3hDLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDLE9BQU8sWUFBWSw0QkFBWSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLDRCQUFZLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlHLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxPQUFPLENBQUMscUJBQXFCLENBQUM7UUFDM0QsSUFBSSxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUM7SUFDekQsQ0FBQztJQUVELFdBQVcsQ0FBQyxJQUF3QjtRQUNsQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3RELHVEQUF1RDtRQUN2RCxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFDOUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0lB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
@@ -0,0 +1,60 @@
1
+ import { AgentManager, AgentManagerOptions } from '../client/agent-manager';
2
+ import * as schema from '../common/schema';
3
+ import { TaskAndHistory } from '../server/types/a2a-types';
4
+ /**
5
+ * Parameters for registering an agent with the A2A plugin.
6
+ * usage: new ChatPrompt(..., [new A2APlugin(...)]).use(A2APluginParams)
7
+ */
8
+ export type A2APluginUseParams = {
9
+ /**
10
+ * Unique key for this agent (used for config and lookup)
11
+ */
12
+ key: string;
13
+ /**
14
+ * The agent's base URL
15
+ */
16
+ url: string;
17
+ /**
18
+ * Optional agent card for the agent
19
+ */
20
+ agentCard?: schema.AgentCard;
21
+ /**
22
+ * Optional function to customize function metadata for this agent
23
+ */
24
+ buildFunctionMetadata?: BuildFunctionMetadata;
25
+ /**
26
+ * Optional function to customize TaskSendParams for this agent
27
+ */
28
+ buildTaskSendParams?: BuildTaskSendParams;
29
+ };
30
+ export type AgentPromptParams = {
31
+ card: schema.AgentCard;
32
+ latestTask?: TaskAndHistory | null;
33
+ };
34
+ export type BuildFunctionMetadata = (card: schema.AgentCard) => {
35
+ name: string;
36
+ description: string;
37
+ };
38
+ export type BuildTaskSendParams = (card: schema.AgentCard, input: string, continueTaskId?: string | null, metadata?: Record<string, any>) => schema.TaskSendParams;
39
+ export type BuildPrompt = (incomingSystemPrompt: string | undefined, agentDetails: AgentPromptParams[]) => string | undefined;
40
+ /**
41
+ * Options for constructing an A2APlugin.
42
+ */
43
+ export type A2APluginOptions = {
44
+ /**
45
+ * Optional A2AAgentManager instance to use for agent management.
46
+ */
47
+ manager?: AgentManager | AgentManagerOptions;
48
+ /**
49
+ * Optional function to customize the function name and description for each agent card.
50
+ */
51
+ buildFunctionMetadata?: BuildFunctionMetadata;
52
+ /**
53
+ * Optional function to customize the prompt given all agent cards.
54
+ */
55
+ buildPrompt?: BuildPrompt;
56
+ /**
57
+ * Optional function to customize TaskSendParams given the input and context.
58
+ */
59
+ buildTaskSendParams?: BuildTaskSendParams;
60
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2hhdC1wcm9tcHQvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
@@ -0,0 +1,58 @@
1
+ import { ILogger } from '@microsoft/teams.common';
2
+ import { type AgentCard, type Task, type TaskSendParams } from '../common/schema';
3
+ /**
4
+ * Options for constructing an A2AAgentClient.
5
+ */
6
+ export type A2AAgentClientOptions = {
7
+ /**
8
+ * The base URL of the A2A agent endpoint. The client will fetch the agent card from this URL if agentCard is not provided.
9
+ */
10
+ baseUrl: string;
11
+ /**
12
+ * The agent card object. If provided, the client will use this directly and will not fetch it from the network.
13
+ */
14
+ agentCard?: AgentCard;
15
+ /**
16
+ * Optional custom fetch implementation (e.g., for Node.js environments without global fetch). Defaults to global fetch.
17
+ */
18
+ fetchImpl?: typeof fetch;
19
+ /**
20
+ *
21
+ */
22
+ logger?: ILogger;
23
+ };
24
+ export declare class AgentCardNotFoundError extends Error {
25
+ constructor(message: string);
26
+ }
27
+ /**
28
+ * A2AAgentClient can be constructed with either a baseUrl (to fetch the agent card) or a direct AgentCard object.
29
+ * Optionally, a custom fetch implementation can be provided.
30
+ */
31
+ export declare class AgentClient {
32
+ private _agentCard;
33
+ private _baseUrl;
34
+ get baseUrl(): string;
35
+ private _a2aUrl;
36
+ get a2aUrl(): string | null;
37
+ private _fetchImpl;
38
+ private _logger;
39
+ constructor(options: A2AAgentClientOptions);
40
+ /**
41
+ * Returns the agent card, fetching it if necessary.
42
+ */
43
+ agentCard(): Promise<AgentCard>;
44
+ /**
45
+ * Sends a task request to the agent (non-streaming).
46
+ * @param params The parameters for the tasks/send method.
47
+ * @returns A promise resolving to the Task object or null.
48
+ */
49
+ sendTask(params: TaskSendParams): Promise<Task | null>;
50
+ /**
51
+ * Internal helper to make JSON-RPC HTTP requests.
52
+ */
53
+ private _makeHttpRequest;
54
+ /**
55
+ * Handles standard JSON-RPC responses (non-streaming).
56
+ */
57
+ private _handleJsonResponse;
58
+ }