@inkeep/agents-run-api 0.1.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 (149) hide show
  1. package/README.md +117 -0
  2. package/dist/AgentExecutionServer.d.ts +23 -0
  3. package/dist/AgentExecutionServer.d.ts.map +1 -0
  4. package/dist/AgentExecutionServer.js +32 -0
  5. package/dist/__tests__/setup.d.ts +4 -0
  6. package/dist/__tests__/setup.d.ts.map +1 -0
  7. package/dist/__tests__/setup.js +50 -0
  8. package/dist/__tests__/utils/testProject.d.ts +18 -0
  9. package/dist/__tests__/utils/testProject.d.ts.map +1 -0
  10. package/dist/__tests__/utils/testProject.js +26 -0
  11. package/dist/__tests__/utils/testRequest.d.ts +8 -0
  12. package/dist/__tests__/utils/testRequest.d.ts.map +1 -0
  13. package/dist/__tests__/utils/testRequest.js +32 -0
  14. package/dist/__tests__/utils/testTenant.d.ts +64 -0
  15. package/dist/__tests__/utils/testTenant.d.ts.map +1 -0
  16. package/dist/__tests__/utils/testTenant.js +71 -0
  17. package/dist/a2a/client.d.ts +182 -0
  18. package/dist/a2a/client.d.ts.map +1 -0
  19. package/dist/a2a/client.js +645 -0
  20. package/dist/a2a/handlers.d.ts +4 -0
  21. package/dist/a2a/handlers.d.ts.map +1 -0
  22. package/dist/a2a/handlers.js +657 -0
  23. package/dist/a2a/transfer.d.ts +18 -0
  24. package/dist/a2a/transfer.d.ts.map +1 -0
  25. package/dist/a2a/transfer.js +22 -0
  26. package/dist/a2a/types.d.ts +63 -0
  27. package/dist/a2a/types.d.ts.map +1 -0
  28. package/dist/a2a/types.js +1 -0
  29. package/dist/agents/Agent.d.ts +154 -0
  30. package/dist/agents/Agent.d.ts.map +1 -0
  31. package/dist/agents/Agent.js +1105 -0
  32. package/dist/agents/ModelFactory.d.ts +62 -0
  33. package/dist/agents/ModelFactory.d.ts.map +1 -0
  34. package/dist/agents/ModelFactory.js +208 -0
  35. package/dist/agents/SystemPromptBuilder.d.ts +14 -0
  36. package/dist/agents/SystemPromptBuilder.d.ts.map +1 -0
  37. package/dist/agents/SystemPromptBuilder.js +62 -0
  38. package/dist/agents/ToolSessionManager.d.ts +61 -0
  39. package/dist/agents/ToolSessionManager.d.ts.map +1 -0
  40. package/dist/agents/ToolSessionManager.js +143 -0
  41. package/dist/agents/artifactTools.d.ts +30 -0
  42. package/dist/agents/artifactTools.d.ts.map +1 -0
  43. package/dist/agents/artifactTools.js +463 -0
  44. package/dist/agents/generateTaskHandler.d.ts +41 -0
  45. package/dist/agents/generateTaskHandler.d.ts.map +1 -0
  46. package/dist/agents/generateTaskHandler.js +350 -0
  47. package/dist/agents/relationTools.d.ts +33 -0
  48. package/dist/agents/relationTools.d.ts.map +1 -0
  49. package/dist/agents/relationTools.js +245 -0
  50. package/dist/agents/types.d.ts +23 -0
  51. package/dist/agents/types.d.ts.map +1 -0
  52. package/dist/agents/types.js +1 -0
  53. package/dist/agents/versions/V1Config.d.ts +21 -0
  54. package/dist/agents/versions/V1Config.d.ts.map +1 -0
  55. package/dist/agents/versions/V1Config.js +285 -0
  56. package/dist/app.d.ts +4 -0
  57. package/dist/app.d.ts.map +1 -0
  58. package/dist/app.js +194 -0
  59. package/dist/data/agentGraph.d.ts +4 -0
  60. package/dist/data/agentGraph.d.ts.map +1 -0
  61. package/dist/data/agentGraph.js +73 -0
  62. package/dist/data/agents.d.ts +4 -0
  63. package/dist/data/agents.d.ts.map +1 -0
  64. package/dist/data/agents.js +73 -0
  65. package/dist/data/conversations.d.ts +59 -0
  66. package/dist/data/conversations.d.ts.map +1 -0
  67. package/dist/data/conversations.js +216 -0
  68. package/dist/data/db/clean.d.ts +6 -0
  69. package/dist/data/db/clean.d.ts.map +1 -0
  70. package/dist/data/db/clean.js +77 -0
  71. package/dist/data/db/dbClient.d.ts +3 -0
  72. package/dist/data/db/dbClient.d.ts.map +1 -0
  73. package/dist/data/db/dbClient.js +13 -0
  74. package/dist/env.d.ts +43 -0
  75. package/dist/env.d.ts.map +1 -0
  76. package/dist/env.js +63 -0
  77. package/dist/handlers/executionHandler.d.ts +36 -0
  78. package/dist/handlers/executionHandler.d.ts.map +1 -0
  79. package/dist/handlers/executionHandler.js +402 -0
  80. package/dist/index.d.ts +5 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +43 -0
  83. package/dist/instrumentation.d.ts +13 -0
  84. package/dist/instrumentation.d.ts.map +1 -0
  85. package/dist/instrumentation.js +66 -0
  86. package/dist/logger.d.ts +4 -0
  87. package/dist/logger.d.ts.map +1 -0
  88. package/dist/logger.js +32 -0
  89. package/dist/middleware/api-key-auth.d.ts +22 -0
  90. package/dist/middleware/api-key-auth.d.ts.map +1 -0
  91. package/dist/middleware/api-key-auth.js +139 -0
  92. package/dist/middleware/index.d.ts +2 -0
  93. package/dist/middleware/index.d.ts.map +1 -0
  94. package/dist/middleware/index.js +1 -0
  95. package/dist/openapi.d.ts +2 -0
  96. package/dist/openapi.d.ts.map +1 -0
  97. package/dist/openapi.js +36 -0
  98. package/dist/routes/agents.d.ts +4 -0
  99. package/dist/routes/agents.d.ts.map +1 -0
  100. package/dist/routes/agents.js +155 -0
  101. package/dist/routes/chat.d.ts +4 -0
  102. package/dist/routes/chat.d.ts.map +1 -0
  103. package/dist/routes/chat.js +308 -0
  104. package/dist/routes/chatDataStream.d.ts +4 -0
  105. package/dist/routes/chatDataStream.d.ts.map +1 -0
  106. package/dist/routes/chatDataStream.js +179 -0
  107. package/dist/routes/mcp.d.ts +4 -0
  108. package/dist/routes/mcp.d.ts.map +1 -0
  109. package/dist/routes/mcp.js +500 -0
  110. package/dist/tracer.d.ts +24 -0
  111. package/dist/tracer.d.ts.map +1 -0
  112. package/dist/tracer.js +97 -0
  113. package/dist/types/chat.d.ts +25 -0
  114. package/dist/types/chat.d.ts.map +1 -0
  115. package/dist/types/chat.js +1 -0
  116. package/dist/types/execution-context.d.ts +14 -0
  117. package/dist/types/execution-context.d.ts.map +1 -0
  118. package/dist/types/execution-context.js +14 -0
  119. package/dist/utils/agent-operations.d.ts +79 -0
  120. package/dist/utils/agent-operations.d.ts.map +1 -0
  121. package/dist/utils/agent-operations.js +67 -0
  122. package/dist/utils/artifact-component-schema.d.ts +29 -0
  123. package/dist/utils/artifact-component-schema.d.ts.map +1 -0
  124. package/dist/utils/artifact-component-schema.js +119 -0
  125. package/dist/utils/artifact-parser.d.ts +71 -0
  126. package/dist/utils/artifact-parser.d.ts.map +1 -0
  127. package/dist/utils/artifact-parser.js +251 -0
  128. package/dist/utils/cleanup.d.ts +19 -0
  129. package/dist/utils/cleanup.d.ts.map +1 -0
  130. package/dist/utils/cleanup.js +66 -0
  131. package/dist/utils/data-component-schema.d.ts +6 -0
  132. package/dist/utils/data-component-schema.d.ts.map +1 -0
  133. package/dist/utils/data-component-schema.js +43 -0
  134. package/dist/utils/graph-session.d.ts +200 -0
  135. package/dist/utils/graph-session.d.ts.map +1 -0
  136. package/dist/utils/graph-session.js +1009 -0
  137. package/dist/utils/incremental-stream-parser.d.ts +57 -0
  138. package/dist/utils/incremental-stream-parser.d.ts.map +1 -0
  139. package/dist/utils/incremental-stream-parser.js +287 -0
  140. package/dist/utils/response-formatter.d.ts +27 -0
  141. package/dist/utils/response-formatter.d.ts.map +1 -0
  142. package/dist/utils/response-formatter.js +160 -0
  143. package/dist/utils/stream-helpers.d.ts +162 -0
  144. package/dist/utils/stream-helpers.d.ts.map +1 -0
  145. package/dist/utils/stream-helpers.js +385 -0
  146. package/dist/utils/stream-registry.d.ts +18 -0
  147. package/dist/utils/stream-registry.d.ts.map +1 -0
  148. package/dist/utils/stream-registry.js +33 -0
  149. package/package.json +88 -0
@@ -0,0 +1,350 @@
1
+ import destr from 'destr'; // safe JSON.parse-if-JSON
2
+ import { nanoid } from 'nanoid';
3
+ import traverse from 'traverse'; // tiny object walker
4
+ import { TaskState, getAgentGraph, getRelatedAgentsForGraph, getToolsForAgent, getAgentById, getArtifactComponentsForAgent, getDataComponentsForAgent, } from '@inkeep/agents-core';
5
+ import { getLogger } from '../logger.js';
6
+ import { Agent } from './Agent.js';
7
+ import dbClient from '../data/db/dbClient.js';
8
+ /** Turn any string value that is valid JSON into an object/array (in place). */
9
+ export function parseEmbeddedJson(data) {
10
+ return traverse(data).map(function (x) {
11
+ if (typeof x === 'string') {
12
+ const v = destr(x); // returns original string if not JSON
13
+ if (v !== x && (Array.isArray(v) || (v && typeof v === 'object'))) {
14
+ this.update(v); // replace the string with the parsed value
15
+ }
16
+ }
17
+ });
18
+ }
19
+ const logger = getLogger('generateTaskHandler');
20
+ export const createTaskHandler = (config) => {
21
+ return async (task) => {
22
+ try {
23
+ // Extract the user message from the task
24
+ const userMessage = task.input.parts
25
+ .filter((part) => part.text)
26
+ .map((part) => part.text)
27
+ .join(' ');
28
+ if (!userMessage.trim()) {
29
+ return {
30
+ status: {
31
+ state: TaskState.Failed,
32
+ message: 'No text content found in task input',
33
+ },
34
+ artifacts: [],
35
+ };
36
+ }
37
+ const [{ internalRelations, externalRelations }, toolsForAgent, dataComponents, artifactComponents,] = await Promise.all([
38
+ getRelatedAgentsForGraph(dbClient)({
39
+ scopes: {
40
+ tenantId: config.tenantId,
41
+ projectId: config.projectId,
42
+ },
43
+ graphId: config.graphId,
44
+ agentId: config.agentId,
45
+ }),
46
+ getToolsForAgent(dbClient)({
47
+ scopes: {
48
+ tenantId: config.tenantId,
49
+ projectId: config.projectId,
50
+ },
51
+ agentId: config.agentId,
52
+ }),
53
+ getDataComponentsForAgent(dbClient)({
54
+ scopes: {
55
+ tenantId: config.tenantId,
56
+ projectId: config.projectId,
57
+ },
58
+ agentId: config.agentId,
59
+ }),
60
+ getArtifactComponentsForAgent(dbClient)({
61
+ scopes: {
62
+ tenantId: config.tenantId,
63
+ projectId: config.projectId,
64
+ },
65
+ agentId: config.agentId,
66
+ }),
67
+ ]);
68
+ logger.info({ toolsForAgent, internalRelations, externalRelations }, 'agent stuff');
69
+ // Check if this is an internal agent (has prompt)
70
+ const agentPrompt = 'prompt' in config.agentSchema ? config.agentSchema.prompt : '';
71
+ const models = 'models' in config.agentSchema ? config.agentSchema.models : undefined;
72
+ const stopWhen = 'stopWhen' in config.agentSchema ? config.agentSchema.stopWhen : undefined;
73
+ const agent = new Agent({
74
+ id: config.agentId,
75
+ tenantId: config.tenantId,
76
+ projectId: config.projectId,
77
+ graphId: config.graphId,
78
+ baseUrl: config.baseUrl,
79
+ apiKey: config.apiKey,
80
+ name: config.name,
81
+ description: config.description || '',
82
+ agentPrompt,
83
+ models: models || undefined,
84
+ stopWhen: stopWhen || undefined,
85
+ agentRelations: internalRelations.map((relation) => ({
86
+ id: relation.id,
87
+ tenantId: config.tenantId,
88
+ projectId: config.projectId,
89
+ graphId: config.graphId,
90
+ baseUrl: config.baseUrl,
91
+ apiKey: config.apiKey,
92
+ name: relation.name,
93
+ description: relation.description,
94
+ agentPrompt: '',
95
+ delegateRelations: [],
96
+ agentRelations: [],
97
+ transferRelations: [],
98
+ })),
99
+ transferRelations: internalRelations
100
+ .filter((relation) => relation.relationType === 'transfer')
101
+ .map((relation) => ({
102
+ baseUrl: config.baseUrl,
103
+ apiKey: config.apiKey,
104
+ id: relation.id,
105
+ tenantId: config.tenantId,
106
+ projectId: config.projectId,
107
+ graphId: config.graphId,
108
+ name: relation.name,
109
+ description: relation.description,
110
+ agentPrompt: '',
111
+ delegateRelations: [],
112
+ agentRelations: [],
113
+ transferRelations: [],
114
+ })),
115
+ delegateRelations: [
116
+ // Internal delegate relations
117
+ ...internalRelations
118
+ .filter((relation) => relation.relationType === 'delegate')
119
+ .map((relation) => ({
120
+ type: 'internal',
121
+ config: {
122
+ id: relation.id,
123
+ tenantId: config.tenantId,
124
+ projectId: config.projectId,
125
+ graphId: config.graphId,
126
+ baseUrl: config.baseUrl,
127
+ apiKey: config.apiKey,
128
+ name: relation.name,
129
+ description: relation.description,
130
+ agentPrompt: '',
131
+ delegateRelations: [],
132
+ agentRelations: [],
133
+ transferRelations: [],
134
+ },
135
+ })),
136
+ // External delegate relations
137
+ ...externalRelations.map((relation) => ({
138
+ type: 'external',
139
+ config: {
140
+ id: relation.externalAgent.id,
141
+ name: relation.externalAgent.name,
142
+ description: relation.externalAgent.description || '',
143
+ baseUrl: relation.externalAgent.baseUrl,
144
+ relationType: relation.relationType || undefined,
145
+ },
146
+ })),
147
+ ],
148
+ tools: toolsForAgent.data.map((item) => ({
149
+ ...item.tool,
150
+ capabilities: item.tool.capabilities || undefined,
151
+ lastHealthCheck: item.tool.lastHealthCheck
152
+ ? new Date(item.tool.lastHealthCheck)
153
+ : undefined,
154
+ lastToolsSync: item.tool.lastToolsSync
155
+ ? new Date(item.tool.lastToolsSync)
156
+ : undefined,
157
+ createdAt: new Date(item.tool.createdAt),
158
+ updatedAt: new Date(item.tool.updatedAt),
159
+ })) ?? [],
160
+ functionTools: [], // All tools are now handled via MCP servers
161
+ dataComponents: dataComponents,
162
+ artifactComponents: artifactComponents,
163
+ contextConfigId: config.contextConfigId || undefined,
164
+ conversationHistoryConfig: config.conversationHistoryConfig,
165
+ });
166
+ // More robust contextId resolution for delegation scenarios
167
+ let contextId = task.context?.conversationId;
168
+ // If contextId is not set in task.context, try to extract it from the task.id
169
+ // Many tasks are created with IDs like "task_math-demo-123456-chatcmpl-789"
170
+ if (!contextId || contextId === 'default' || contextId === '') {
171
+ const taskIdMatch = task.id.match(/^task_([^-]+-[^-]+-\d+)-/);
172
+ if (taskIdMatch) {
173
+ contextId = taskIdMatch[1];
174
+ logger.info({
175
+ taskId: task.id,
176
+ extractedContextId: contextId,
177
+ agentId: config.agentId,
178
+ }, 'Extracted contextId from task ID for delegation');
179
+ }
180
+ else {
181
+ contextId = 'default';
182
+ }
183
+ }
184
+ // Extract streaming context from task metadata and get streamHelper from registry
185
+ const streamRequestId = task.context?.metadata?.stream_request_id || task.context?.metadata?.streamRequestId;
186
+ // Check if this is a delegation - delegated agents should not stream to user
187
+ const isDelegation = task.context?.metadata?.isDelegation === true;
188
+ agent.setDelegationStatus(isDelegation);
189
+ if (isDelegation) {
190
+ logger.info({ agentId: config.agentId, taskId: task.id }, 'Delegated agent - streaming disabled');
191
+ }
192
+ const response = await agent.generate(userMessage, {
193
+ contextId,
194
+ metadata: {
195
+ conversationId: contextId,
196
+ taskId: task.id,
197
+ threadId: contextId, // using conversationId as threadId for now
198
+ streamRequestId: streamRequestId,
199
+ },
200
+ });
201
+ // Process steps to extract tool calls and results from content arrays
202
+ const stepContents = response.steps && Array.isArray(response.steps)
203
+ ? response.steps.flatMap((step) => {
204
+ return step.content && Array.isArray(step.content) ? step.content : [];
205
+ })
206
+ : [];
207
+ const allToolCalls = stepContents.filter((content) => content.type === 'tool-call');
208
+ const allToolResults = stepContents.filter((content) => content.type === 'tool-result');
209
+ const allThoughts = stepContents.filter((content) => content.type === 'text');
210
+ if (allToolCalls.length > 0) {
211
+ for (const toolCall of allToolCalls) {
212
+ // Check for transfer tool calls (we support multiple patterns)
213
+ if (toolCall.toolName.includes('transfer') ||
214
+ toolCall.toolName.includes('transferToRefundAgent')) {
215
+ // Look for the tool result
216
+ const toolResult = allToolResults.find((result) => result.toolCallId === toolCall.toolCallId);
217
+ // Validate transfer result with proper type checking
218
+ const isValidTransferResult = (output) => {
219
+ return (typeof output === 'object' &&
220
+ output !== null &&
221
+ 'type' in output &&
222
+ 'target' in output &&
223
+ output.type === 'transfer' &&
224
+ typeof output.target === 'string' &&
225
+ (output.reason === undefined || typeof output.reason === 'string'));
226
+ };
227
+ //In the agent.generate response, response.text is not always populated. In that case, use allThoughts to get the last text part found in the steps array.
228
+ const responseText = response.text ||
229
+ (response.object ? JSON.stringify(response.object) : '');
230
+ const transferReason = responseText ||
231
+ allThoughts[allThoughts.length - 1]?.text ||
232
+ 'Agent requested transfer. No reason provided.';
233
+ if (toolResult?.output && isValidTransferResult(toolResult.output)) {
234
+ const transferResult = toolResult.output;
235
+ // Return transfer indication in A2A format
236
+ return {
237
+ status: {
238
+ state: TaskState.Completed,
239
+ message: `Transfer requested to ${transferResult.target}`,
240
+ },
241
+ artifacts: [
242
+ {
243
+ artifactId: nanoid(),
244
+ parts: [
245
+ {
246
+ kind: 'data',
247
+ data: {
248
+ type: 'transfer',
249
+ target: transferResult.target,
250
+ task_id: task.id,
251
+ reason: transferReason,
252
+ original_message: userMessage,
253
+ },
254
+ },
255
+ ],
256
+ },
257
+ ],
258
+ };
259
+ }
260
+ }
261
+ }
262
+ }
263
+ // Use formatted content parts if available, otherwise fall back to response.text
264
+ const parts = (response.formattedContent?.parts || []).map((part) => ({
265
+ kind: part.kind,
266
+ ...(part.kind === 'text' && { text: part.text }),
267
+ ...(part.kind === 'data' && { data: part.data }),
268
+ }));
269
+ return {
270
+ status: { state: TaskState.Completed },
271
+ artifacts: [
272
+ {
273
+ artifactId: nanoid(),
274
+ parts,
275
+ },
276
+ ],
277
+ };
278
+ }
279
+ catch (error) {
280
+ console.error('Task handler error:', error);
281
+ return {
282
+ status: {
283
+ state: TaskState.Failed,
284
+ message: error instanceof Error ? error.message : 'Unknown error occurred',
285
+ },
286
+ artifacts: [],
287
+ };
288
+ }
289
+ };
290
+ };
291
+ /**
292
+ * Serializes a TaskHandlerConfig to JSON
293
+ */
294
+ export const serializeTaskHandlerConfig = (config) => {
295
+ return JSON.stringify(config, null, 2);
296
+ };
297
+ /**
298
+ * Deserializes a TaskHandlerConfig from JSON
299
+ */
300
+ export const deserializeTaskHandlerConfig = (configJson) => {
301
+ return JSON.parse(configJson);
302
+ };
303
+ /**
304
+ * Creates a task handler configuration from agent data
305
+ */
306
+ export const createTaskHandlerConfig = async (params) => {
307
+ const agent = await getAgentById(dbClient)({
308
+ scopes: {
309
+ tenantId: params.tenantId,
310
+ projectId: params.projectId,
311
+ },
312
+ agentId: params.agentId,
313
+ });
314
+ const agentGraph = await getAgentGraph(dbClient)({
315
+ scopes: {
316
+ tenantId: params.tenantId,
317
+ projectId: params.projectId,
318
+ },
319
+ graphId: params.graphId,
320
+ });
321
+ if (!agent) {
322
+ throw new Error(`Agent not found: ${params.agentId}`);
323
+ }
324
+ // Inherit graph models if agent doesn't have one
325
+ const effectiveModels = agent.models || agentGraph?.models || undefined;
326
+ const effectiveConversationHistoryConfig = agent.conversationHistoryConfig || { mode: 'full' };
327
+ return {
328
+ tenantId: params.tenantId,
329
+ projectId: params.projectId,
330
+ graphId: params.graphId,
331
+ agentId: params.agentId,
332
+ agentSchema: {
333
+ id: agent.id,
334
+ name: agent.name,
335
+ description: agent.description,
336
+ prompt: agent.prompt,
337
+ models: effectiveModels || null,
338
+ conversationHistoryConfig: effectiveConversationHistoryConfig || null,
339
+ stopWhen: agent.stopWhen || null,
340
+ createdAt: agent.createdAt,
341
+ updatedAt: agent.updatedAt,
342
+ },
343
+ baseUrl: params.baseUrl,
344
+ apiKey: params.apiKey,
345
+ name: agent.name,
346
+ description: agent.description,
347
+ conversationHistoryConfig: effectiveConversationHistoryConfig,
348
+ contextConfigId: agentGraph?.contextConfigId || undefined,
349
+ };
350
+ };
@@ -0,0 +1,33 @@
1
+ import type { AgentConfig, DelegateRelation } from './Agent.js';
2
+ export declare const createTransferToAgentTool: ({ transferConfig, callingAgentId, agent, streamRequestId, }: {
3
+ transferConfig: AgentConfig;
4
+ callingAgentId: string;
5
+ agent: any;
6
+ streamRequestId?: string;
7
+ }) => import("ai").Tool<Record<string, never>, {
8
+ type: string;
9
+ target: string;
10
+ fromAgentId: string;
11
+ }>;
12
+ export declare function createDelegateToAgentTool({ delegateConfig, callingAgentId, tenantId, projectId, graphId, contextId, metadata, sessionId, agent, }: {
13
+ delegateConfig: DelegateRelation;
14
+ callingAgentId: string;
15
+ tenantId: string;
16
+ projectId: string;
17
+ graphId: string;
18
+ contextId: string;
19
+ metadata: {
20
+ conversationId: string;
21
+ threadId: string;
22
+ streamRequestId?: string;
23
+ streamBaseUrl?: string;
24
+ };
25
+ sessionId?: string;
26
+ agent: any;
27
+ }): import("ai").Tool<{
28
+ message: string;
29
+ }, {
30
+ toolCallId: any;
31
+ result: import("@inkeep/agents-core").Message | import("@inkeep/agents-core").Task;
32
+ }>;
33
+ //# sourceMappingURL=relationTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relationTools.d.ts","sourceRoot":"","sources":["../../src/agents/relationTools.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA2BhE,eAAO,MAAM,yBAAyB,GAAI,6DAKvC;IACD,cAAc,EAAE,WAAW,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,GAAG,CAAC;IACX,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;;;;EAsCA,CAAC;AAEF,wBAAgB,yBAAyB,CAAC,EACxC,cAAc,EACd,cAAc,EACd,QAAQ,EACR,SAAS,EACT,OAAO,EACP,SAAS,EACT,QAAQ,EACR,SAAS,EACT,KAAK,GACN,EAAE;IACD,cAAc,EAAE,gBAAgB,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QACR,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,GAAG,CAAC;CACZ;;;;;GAkNA"}
@@ -0,0 +1,245 @@
1
+ import { trace } from '@opentelemetry/api';
2
+ import { tool } from 'ai';
3
+ import { nanoid } from 'nanoid';
4
+ import z from 'zod';
5
+ import { A2AClient } from '../a2a/client.js';
6
+ import { createMessage, getCredentialReference, getExternalAgent, CredentialStuffer, ContextResolver, } from '@inkeep/agents-core';
7
+ import { saveA2AMessageResponse } from '../data/conversations.js';
8
+ import dbClient from '../data/db/dbClient.js';
9
+ import { executionServer } from '../index.js';
10
+ import { getLogger } from '../logger.js';
11
+ import { graphSessionManager } from '../utils/graph-session.js';
12
+ import { toolSessionManager } from './ToolSessionManager.js';
13
+ const logger = getLogger('relationships Tools');
14
+ const generateTransferToolDescription = (config) => {
15
+ return `Hand off the conversation to agent ${config.id}.
16
+
17
+ Agent Information:
18
+ - ID: ${config.id}
19
+ - Name: ${config.name ?? 'No name provided'}
20
+ - Description: ${config.description ?? 'No description provided'}
21
+
22
+ Hand off the conversation to agent ${config.id} when the user's request would be better handled by this specialized agent.`;
23
+ };
24
+ const generateDelegateToolDescription = (config) => {
25
+ return `Delegate a specific task to another agent.
26
+
27
+ Agent Information:
28
+ - ID: ${config.id}
29
+ - Name: ${config.name}
30
+ - Description: ${config.description || 'No description provided'}
31
+
32
+ Delegate a specific task to agent ${config.id} when it seems like the agent can do relevant work.`;
33
+ };
34
+ export const createTransferToAgentTool = ({ transferConfig, callingAgentId, agent, streamRequestId, }) => {
35
+ return tool({
36
+ description: generateTransferToolDescription(transferConfig),
37
+ inputSchema: z.object({}),
38
+ execute: async () => {
39
+ // Add span attributes to indicate transfer source and target
40
+ const activeSpan = trace.getActiveSpan();
41
+ if (activeSpan) {
42
+ activeSpan.setAttributes({
43
+ 'transfer.from_agent_id': callingAgentId,
44
+ 'transfer.to_agent_id': transferConfig.id ?? 'unknown',
45
+ });
46
+ }
47
+ logger.info({
48
+ transferTo: transferConfig.id ?? 'unknown',
49
+ fromAgent: callingAgentId,
50
+ }, 'invoked transferToAgentTool');
51
+ // Record transfer event in GraphSession
52
+ if (streamRequestId) {
53
+ graphSessionManager.recordEvent(streamRequestId, 'transfer', callingAgentId, {
54
+ fromAgent: callingAgentId,
55
+ targetAgent: transferConfig.id ?? 'unknown',
56
+ reason: `Transfer to ${transferConfig.name || transferConfig.id}`,
57
+ });
58
+ }
59
+ return {
60
+ type: 'transfer',
61
+ target: transferConfig.id ?? 'unknown',
62
+ fromAgentId: callingAgentId, // Include the calling agent ID for tracking
63
+ };
64
+ },
65
+ });
66
+ };
67
+ export function createDelegateToAgentTool({ delegateConfig, callingAgentId, tenantId, projectId, graphId, contextId, metadata, sessionId, agent, }) {
68
+ return tool({
69
+ description: generateDelegateToolDescription(delegateConfig.config),
70
+ inputSchema: z.object({ message: z.string() }),
71
+ execute: async (input, context) => {
72
+ // Generate unique delegation ID for tracking
73
+ const delegationId = `del_${nanoid()}`;
74
+ // Add span attributes to indicate delegation source and target
75
+ const activeSpan = trace.getActiveSpan();
76
+ if (activeSpan) {
77
+ activeSpan.setAttributes({
78
+ 'delegation.from_agent_id': callingAgentId,
79
+ 'delegation.to_agent_id': delegateConfig.config.id ?? 'unknown',
80
+ 'delegation.id': delegationId,
81
+ });
82
+ }
83
+ // Record delegation sent event in GraphSession
84
+ if (metadata.streamRequestId) {
85
+ graphSessionManager.recordEvent(metadata.streamRequestId, 'delegation_sent', callingAgentId, {
86
+ delegationId,
87
+ fromAgent: callingAgentId,
88
+ targetAgent: delegateConfig.config.id,
89
+ taskDescription: input.message,
90
+ });
91
+ }
92
+ const isInternal = delegateConfig.type === 'internal';
93
+ // Get the base URL for the agent
94
+ let agentBaseUrl;
95
+ let resolvedHeaders = {};
96
+ if (!isInternal) {
97
+ agentBaseUrl = delegateConfig.config.baseUrl;
98
+ // For external agents, fetch configuration
99
+ const externalAgent = await getExternalAgent(dbClient)({
100
+ scopes: {
101
+ tenantId,
102
+ projectId,
103
+ },
104
+ agentId: delegateConfig.config.id,
105
+ });
106
+ // If the external agent has a credential reference ID or headers, resolve them
107
+ if (externalAgent && (externalAgent.credentialReferenceId || externalAgent.headers)) {
108
+ const contextResolver = new ContextResolver(tenantId, projectId, dbClient, executionServer);
109
+ const credentialStuffer = new CredentialStuffer(executionServer, contextResolver);
110
+ const credentialContext = {
111
+ tenantId,
112
+ projectId,
113
+ conversationId: metadata.conversationId,
114
+ contextConfigId: contextId,
115
+ metadata: metadata,
116
+ };
117
+ let storeReference;
118
+ if (externalAgent.credentialReferenceId) {
119
+ // Get credential store configuration
120
+ const credentialReference = await getCredentialReference(dbClient)({
121
+ scopes: {
122
+ tenantId,
123
+ projectId,
124
+ },
125
+ id: externalAgent.credentialReferenceId,
126
+ });
127
+ if (credentialReference) {
128
+ storeReference = {
129
+ credentialStoreId: credentialReference.credentialStoreId,
130
+ retrievalParams: credentialReference.retrievalParams || {},
131
+ };
132
+ }
133
+ }
134
+ // Resolve credentials using CredentialStuffer
135
+ resolvedHeaders = await credentialStuffer.getCredentialHeaders({
136
+ context: credentialContext,
137
+ storeReference,
138
+ headers: externalAgent.headers || undefined,
139
+ });
140
+ }
141
+ }
142
+ else {
143
+ resolvedHeaders = {
144
+ Authorization: `Bearer ${delegateConfig.config.apiKey}`,
145
+ 'x-inkeep-tenant-id': tenantId,
146
+ 'x-inkeep-project-id': projectId,
147
+ 'x-inkeep-graph-id': graphId,
148
+ 'x-inkeep-agent-id': delegateConfig.config.id,
149
+ };
150
+ }
151
+ // Configure retry behavior for A2A client with custom settings and resolved headers
152
+ const a2aClient = new A2AClient(delegateConfig.config.baseUrl, {
153
+ headers: resolvedHeaders,
154
+ retryConfig: {
155
+ strategy: 'backoff',
156
+ retryConnectionErrors: true,
157
+ statusCodes: ['429', '500', '502', '503', '504'],
158
+ backoff: {
159
+ initialInterval: 100,
160
+ maxInterval: 10000,
161
+ exponent: 2,
162
+ maxElapsedTime: 20000, // 1 minute max retry time
163
+ },
164
+ },
165
+ });
166
+ // Create the message to send to the agent
167
+ // Keep streamRequestId for GraphSession access, add isDelegation flag to prevent streaming
168
+ const messageToSend = {
169
+ role: 'agent',
170
+ parts: [{ text: input.message, kind: 'text' }],
171
+ messageId: nanoid(),
172
+ kind: 'message',
173
+ contextId,
174
+ metadata: {
175
+ ...metadata, // Keep all metadata including streamRequestId
176
+ isDelegation: true, // Flag to prevent streaming in delegated agents
177
+ delegationId, // Include delegation ID for tracking
178
+ ...(isInternal
179
+ ? { fromAgentId: callingAgentId }
180
+ : { fromExternalAgentId: callingAgentId }),
181
+ },
182
+ };
183
+ logger.info({ messageToSend }, 'messageToSend');
184
+ // Record the outgoing message to the agent
185
+ await createMessage(dbClient)({
186
+ id: nanoid(),
187
+ tenantId: tenantId,
188
+ projectId: projectId,
189
+ conversationId: contextId,
190
+ role: 'agent',
191
+ content: {
192
+ text: input.message,
193
+ },
194
+ visibility: isInternal ? 'internal' : 'external',
195
+ messageType: 'a2a-request',
196
+ fromAgentId: callingAgentId,
197
+ ...(isInternal
198
+ ? { toAgentId: delegateConfig.config.id }
199
+ : { toExternalAgentId: delegateConfig.config.id }),
200
+ });
201
+ const response = await a2aClient.sendMessage({
202
+ message: messageToSend,
203
+ });
204
+ if (response.error) {
205
+ throw new Error(response.error.message);
206
+ }
207
+ // Save the response using the reusable function
208
+ await saveA2AMessageResponse(response, {
209
+ tenantId,
210
+ projectId,
211
+ conversationId: contextId,
212
+ messageType: 'a2a-response',
213
+ visibility: isInternal ? 'internal' : 'external',
214
+ toAgentId: callingAgentId,
215
+ ...(isInternal
216
+ ? { fromAgentId: delegateConfig.config.id }
217
+ : { fromExternalAgentId: delegateConfig.config.id }),
218
+ });
219
+ // Record the delegation result as a tool result for the parent agent
220
+ if (sessionId && context?.toolCallId) {
221
+ const toolResult = {
222
+ toolCallId: context.toolCallId,
223
+ toolName: `delegate_to_${delegateConfig.config.id}`,
224
+ args: input,
225
+ result: response.result,
226
+ timestamp: Date.now(),
227
+ };
228
+ toolSessionManager.recordToolResult(sessionId, toolResult);
229
+ }
230
+ // Record delegation returned event in GraphSession
231
+ if (metadata.streamRequestId) {
232
+ graphSessionManager.recordEvent(metadata.streamRequestId, 'delegation_returned', callingAgentId, {
233
+ delegationId,
234
+ fromAgent: delegateConfig.config.id,
235
+ targetAgent: callingAgentId,
236
+ result: response.result,
237
+ });
238
+ }
239
+ return {
240
+ toolCallId: context?.toolCallId,
241
+ result: response.result,
242
+ };
243
+ },
244
+ });
245
+ }
@@ -0,0 +1,23 @@
1
+ import type { DataComponentApiInsert, ArtifactComponentApiInsert, Artifact } from '@inkeep/agents-core';
2
+ export interface VersionConfig<TConfig> {
3
+ templateFiles: string[];
4
+ assemble(templates: Map<string, string>, config: TConfig): string;
5
+ }
6
+ export interface SystemPromptV1 {
7
+ corePrompt: string;
8
+ graphPrompt?: string;
9
+ artifacts: Artifact[];
10
+ tools: ToolData[];
11
+ dataComponents: DataComponentApiInsert[];
12
+ artifactComponents?: ArtifactComponentApiInsert[];
13
+ isThinkingPreparation?: boolean;
14
+ hasTransferRelations?: boolean;
15
+ hasDelegateRelations?: boolean;
16
+ }
17
+ export interface ToolData {
18
+ name: string;
19
+ description?: string;
20
+ inputSchema?: Record<string, unknown>;
21
+ usageGuidelines?: string;
22
+ }
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGxG,MAAM,WAAW,aAAa,CAAC,OAAO;IACpC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CACnE;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,cAAc,EAAE,sBAAsB,EAAE,CAAC;IACzC,kBAAkB,CAAC,EAAE,0BAA0B,EAAE,CAAC;IAClD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
@@ -0,0 +1 @@
1
+ export {};