@aigne/core 1.15.0 → 1.17.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 (194) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +9 -7
  3. package/README.zh.md +9 -7
  4. package/lib/cjs/agents/agent.d.ts +168 -29
  5. package/lib/cjs/agents/agent.js +152 -56
  6. package/lib/cjs/agents/ai-agent.d.ts +7 -7
  7. package/lib/cjs/agents/ai-agent.js +19 -15
  8. package/lib/{esm/models → cjs/agents}/chat-model.d.ts +29 -19
  9. package/lib/cjs/{models → agents}/chat-model.js +56 -15
  10. package/lib/cjs/agents/guide-rail-agent.d.ts +62 -0
  11. package/lib/cjs/agents/guide-rail-agent.js +14 -0
  12. package/lib/cjs/agents/mcp-agent.d.ts +3 -4
  13. package/lib/cjs/agents/mcp-agent.js +11 -11
  14. package/lib/cjs/agents/team-agent.d.ts +7 -8
  15. package/lib/cjs/agents/team-agent.js +10 -10
  16. package/lib/cjs/agents/user-agent.d.ts +4 -4
  17. package/lib/cjs/agents/user-agent.js +10 -10
  18. package/lib/cjs/aigne/aigne.d.ts +13 -11
  19. package/lib/cjs/aigne/aigne.js +7 -6
  20. package/lib/cjs/aigne/context.d.ts +19 -8
  21. package/lib/cjs/aigne/context.js +27 -7
  22. package/lib/cjs/index.d.ts +2 -1
  23. package/lib/cjs/index.js +2 -1
  24. package/lib/cjs/loader/agent-yaml.d.ts +2 -2
  25. package/lib/cjs/loader/index.d.ts +18 -11
  26. package/lib/cjs/loader/index.js +8 -27
  27. package/lib/cjs/memory/default-memory/default-memory-storage/index.d.ts +30 -0
  28. package/lib/cjs/memory/default-memory/default-memory-storage/index.js +69 -0
  29. package/lib/cjs/memory/default-memory/default-memory-storage/migrate.d.ts +7 -0
  30. package/lib/cjs/memory/default-memory/default-memory-storage/migrate.js +53 -0
  31. package/lib/cjs/memory/default-memory/default-memory-storage/migrations/20250523165801-init.d.ts +7 -0
  32. package/lib/cjs/memory/default-memory/default-memory-storage/migrations/20250523165801-init.js +33 -0
  33. package/lib/cjs/memory/default-memory/default-memory-storage/models/memory.d.ts +10 -0
  34. package/lib/cjs/memory/default-memory/default-memory-storage/models/memory.js +32 -0
  35. package/lib/cjs/memory/default-memory/index.d.ts +10 -0
  36. package/lib/cjs/memory/{default-memory.js → default-memory/index.js} +16 -25
  37. package/lib/cjs/memory/default-memory/storage.d.ts +13 -0
  38. package/lib/cjs/memory/default-memory/storage.js +6 -0
  39. package/lib/cjs/memory/memory.d.ts +3 -2
  40. package/lib/cjs/memory/memory.js +1 -1
  41. package/lib/cjs/memory/retriever.d.ts +2 -2
  42. package/lib/cjs/prompt/prompt-builder.d.ts +10 -4
  43. package/lib/cjs/prompt/prompt-builder.js +4 -4
  44. package/lib/cjs/prompt/template.d.ts +3 -3
  45. package/lib/cjs/utils/json-schema.js +1 -1
  46. package/lib/cjs/utils/logger.d.ts +33 -8
  47. package/lib/cjs/utils/logger.js +63 -5
  48. package/lib/cjs/utils/model-utils.d.ts +1 -1
  49. package/lib/cjs/utils/stream-utils.d.ts +3 -1
  50. package/lib/cjs/utils/stream-utils.js +31 -1
  51. package/lib/cjs/utils/type-utils.d.ts +7 -2
  52. package/lib/dts/agents/agent.d.ts +168 -29
  53. package/lib/dts/agents/ai-agent.d.ts +7 -7
  54. package/lib/{cjs/models → dts/agents}/chat-model.d.ts +29 -19
  55. package/lib/dts/agents/guide-rail-agent.d.ts +62 -0
  56. package/lib/dts/agents/mcp-agent.d.ts +3 -4
  57. package/lib/dts/agents/team-agent.d.ts +7 -8
  58. package/lib/dts/agents/user-agent.d.ts +4 -4
  59. package/lib/dts/aigne/aigne.d.ts +13 -11
  60. package/lib/dts/aigne/context.d.ts +19 -8
  61. package/lib/dts/index.d.ts +2 -1
  62. package/lib/dts/loader/agent-yaml.d.ts +2 -2
  63. package/lib/dts/loader/index.d.ts +18 -11
  64. package/lib/dts/memory/default-memory/default-memory-storage/index.d.ts +30 -0
  65. package/lib/dts/memory/default-memory/default-memory-storage/migrate.d.ts +7 -0
  66. package/lib/dts/memory/default-memory/default-memory-storage/migrations/20250523165801-init.d.ts +7 -0
  67. package/lib/dts/memory/default-memory/default-memory-storage/models/memory.d.ts +10 -0
  68. package/lib/dts/memory/default-memory/index.d.ts +10 -0
  69. package/lib/dts/memory/default-memory/storage.d.ts +13 -0
  70. package/lib/dts/memory/memory.d.ts +3 -2
  71. package/lib/dts/memory/retriever.d.ts +2 -2
  72. package/lib/dts/prompt/prompt-builder.d.ts +10 -4
  73. package/lib/dts/prompt/template.d.ts +3 -3
  74. package/lib/dts/utils/logger.d.ts +33 -8
  75. package/lib/dts/utils/model-utils.d.ts +1 -1
  76. package/lib/dts/utils/stream-utils.d.ts +3 -1
  77. package/lib/dts/utils/type-utils.d.ts +7 -2
  78. package/lib/esm/agents/agent.d.ts +168 -29
  79. package/lib/esm/agents/agent.js +152 -56
  80. package/lib/esm/agents/ai-agent.d.ts +7 -7
  81. package/lib/esm/agents/ai-agent.js +18 -14
  82. package/lib/{dts/models → esm/agents}/chat-model.d.ts +29 -19
  83. package/lib/esm/{models → agents}/chat-model.js +56 -15
  84. package/lib/esm/agents/guide-rail-agent.d.ts +62 -0
  85. package/lib/esm/agents/guide-rail-agent.js +11 -0
  86. package/lib/esm/agents/mcp-agent.d.ts +3 -4
  87. package/lib/esm/agents/mcp-agent.js +11 -11
  88. package/lib/esm/agents/team-agent.d.ts +7 -8
  89. package/lib/esm/agents/team-agent.js +10 -10
  90. package/lib/esm/agents/user-agent.d.ts +4 -4
  91. package/lib/esm/agents/user-agent.js +10 -10
  92. package/lib/esm/aigne/aigne.d.ts +13 -11
  93. package/lib/esm/aigne/aigne.js +7 -6
  94. package/lib/esm/aigne/context.d.ts +19 -8
  95. package/lib/esm/aigne/context.js +28 -8
  96. package/lib/esm/index.d.ts +2 -1
  97. package/lib/esm/index.js +2 -1
  98. package/lib/esm/loader/agent-yaml.d.ts +2 -2
  99. package/lib/esm/loader/index.d.ts +18 -11
  100. package/lib/esm/loader/index.js +8 -27
  101. package/lib/esm/memory/default-memory/default-memory-storage/index.d.ts +30 -0
  102. package/lib/esm/memory/default-memory/default-memory-storage/index.js +64 -0
  103. package/lib/esm/memory/default-memory/default-memory-storage/migrate.d.ts +7 -0
  104. package/lib/esm/memory/default-memory/default-memory-storage/migrate.js +16 -0
  105. package/lib/esm/memory/default-memory/default-memory-storage/migrations/20250523165801-init.d.ts +7 -0
  106. package/lib/esm/memory/default-memory/default-memory-storage/migrations/20250523165801-init.js +28 -0
  107. package/lib/esm/memory/default-memory/default-memory-storage/models/memory.d.ts +10 -0
  108. package/lib/esm/memory/default-memory/default-memory-storage/models/memory.js +29 -0
  109. package/lib/esm/memory/default-memory/index.d.ts +10 -0
  110. package/lib/esm/memory/{default-memory.js → default-memory/index.js} +15 -24
  111. package/lib/esm/memory/default-memory/storage.d.ts +13 -0
  112. package/lib/esm/memory/default-memory/storage.js +2 -0
  113. package/lib/esm/memory/memory.d.ts +3 -2
  114. package/lib/esm/memory/memory.js +2 -2
  115. package/lib/esm/memory/retriever.d.ts +2 -2
  116. package/lib/esm/prompt/prompt-builder.d.ts +10 -4
  117. package/lib/esm/prompt/prompt-builder.js +4 -4
  118. package/lib/esm/prompt/template.d.ts +3 -3
  119. package/lib/esm/utils/json-schema.js +1 -1
  120. package/lib/esm/utils/logger.d.ts +33 -8
  121. package/lib/esm/utils/logger.js +61 -4
  122. package/lib/esm/utils/model-utils.d.ts +1 -1
  123. package/lib/esm/utils/stream-utils.d.ts +3 -1
  124. package/lib/esm/utils/stream-utils.js +29 -1
  125. package/lib/esm/utils/type-utils.d.ts +7 -2
  126. package/package.json +4 -20
  127. package/lib/cjs/client/client.d.ts +0 -97
  128. package/lib/cjs/client/client.js +0 -87
  129. package/lib/cjs/client/index.d.ts +0 -1
  130. package/lib/cjs/client/index.js +0 -17
  131. package/lib/cjs/memory/default-memory.d.ts +0 -16
  132. package/lib/cjs/models/bedrock-chat-model.d.ts +0 -79
  133. package/lib/cjs/models/bedrock-chat-model.js +0 -303
  134. package/lib/cjs/models/claude-chat-model.d.ts +0 -114
  135. package/lib/cjs/models/claude-chat-model.js +0 -317
  136. package/lib/cjs/models/deepseek-chat-model.d.ts +0 -23
  137. package/lib/cjs/models/deepseek-chat-model.js +0 -35
  138. package/lib/cjs/models/gemini-chat-model.d.ts +0 -23
  139. package/lib/cjs/models/gemini-chat-model.js +0 -35
  140. package/lib/cjs/models/ollama-chat-model.d.ts +0 -22
  141. package/lib/cjs/models/ollama-chat-model.js +0 -34
  142. package/lib/cjs/models/open-router-chat-model.d.ts +0 -22
  143. package/lib/cjs/models/open-router-chat-model.js +0 -34
  144. package/lib/cjs/models/openai-chat-model.d.ts +0 -166
  145. package/lib/cjs/models/openai-chat-model.js +0 -415
  146. package/lib/cjs/models/xai-chat-model.d.ts +0 -21
  147. package/lib/cjs/models/xai-chat-model.js +0 -33
  148. package/lib/cjs/server/error.d.ts +0 -15
  149. package/lib/cjs/server/error.js +0 -22
  150. package/lib/cjs/server/index.d.ts +0 -2
  151. package/lib/cjs/server/index.js +0 -18
  152. package/lib/cjs/server/server.d.ts +0 -135
  153. package/lib/cjs/server/server.js +0 -187
  154. package/lib/dts/client/client.d.ts +0 -97
  155. package/lib/dts/client/index.d.ts +0 -1
  156. package/lib/dts/memory/default-memory.d.ts +0 -16
  157. package/lib/dts/models/bedrock-chat-model.d.ts +0 -79
  158. package/lib/dts/models/claude-chat-model.d.ts +0 -114
  159. package/lib/dts/models/deepseek-chat-model.d.ts +0 -23
  160. package/lib/dts/models/gemini-chat-model.d.ts +0 -23
  161. package/lib/dts/models/ollama-chat-model.d.ts +0 -22
  162. package/lib/dts/models/open-router-chat-model.d.ts +0 -22
  163. package/lib/dts/models/openai-chat-model.d.ts +0 -166
  164. package/lib/dts/models/xai-chat-model.d.ts +0 -21
  165. package/lib/dts/server/error.d.ts +0 -15
  166. package/lib/dts/server/index.d.ts +0 -2
  167. package/lib/dts/server/server.d.ts +0 -135
  168. package/lib/esm/client/client.d.ts +0 -97
  169. package/lib/esm/client/client.js +0 -83
  170. package/lib/esm/client/index.d.ts +0 -1
  171. package/lib/esm/client/index.js +0 -1
  172. package/lib/esm/memory/default-memory.d.ts +0 -16
  173. package/lib/esm/models/bedrock-chat-model.d.ts +0 -79
  174. package/lib/esm/models/bedrock-chat-model.js +0 -298
  175. package/lib/esm/models/claude-chat-model.d.ts +0 -114
  176. package/lib/esm/models/claude-chat-model.js +0 -310
  177. package/lib/esm/models/deepseek-chat-model.d.ts +0 -23
  178. package/lib/esm/models/deepseek-chat-model.js +0 -31
  179. package/lib/esm/models/gemini-chat-model.d.ts +0 -23
  180. package/lib/esm/models/gemini-chat-model.js +0 -31
  181. package/lib/esm/models/ollama-chat-model.d.ts +0 -22
  182. package/lib/esm/models/ollama-chat-model.js +0 -30
  183. package/lib/esm/models/open-router-chat-model.d.ts +0 -22
  184. package/lib/esm/models/open-router-chat-model.js +0 -30
  185. package/lib/esm/models/openai-chat-model.d.ts +0 -166
  186. package/lib/esm/models/openai-chat-model.js +0 -405
  187. package/lib/esm/models/xai-chat-model.d.ts +0 -21
  188. package/lib/esm/models/xai-chat-model.js +0 -29
  189. package/lib/esm/server/error.d.ts +0 -15
  190. package/lib/esm/server/error.js +0 -18
  191. package/lib/esm/server/index.d.ts +0 -2
  192. package/lib/esm/server/index.js +0 -2
  193. package/lib/esm/server/server.d.ts +0 -135
  194. package/lib/esm/server/server.js +0 -180
@@ -19,6 +19,16 @@ export const agentOptionsSchema = z.object({
19
19
  skills: z.array(z.union([z.custom(), z.custom()])).optional(),
20
20
  disableEvents: z.boolean().optional(),
21
21
  memory: z.union([z.custom(), z.array(z.custom())]).optional(),
22
+ hooks: z
23
+ .object({
24
+ onStart: z.custom().optional(),
25
+ onEnd: z.custom().optional(),
26
+ onSkillStart: z.custom().optional(),
27
+ onSkillEnd: z.custom().optional(),
28
+ onHandoff: z.custom().optional(),
29
+ })
30
+ .optional(),
31
+ guideRails: z.array(z.custom()).optional(),
22
32
  });
23
33
  /**
24
34
  * Agent is the base class for all agents.
@@ -65,11 +75,42 @@ export class Agent {
65
75
  else if (options.memory) {
66
76
  this.memories.push(options.memory);
67
77
  }
78
+ this.hooks = options.hooks ?? {};
79
+ this.guideRails = options.guideRails;
68
80
  }
69
81
  /**
70
82
  * List of memories this agent can use
71
83
  */
72
84
  memories = [];
85
+ /**
86
+ * Lifecycle hooks for agent processing.
87
+ *
88
+ * Hooks enable tracing, logging, monitoring, and custom behavior
89
+ * without modifying the core agent implementation
90
+ *
91
+ * @example
92
+ * Here's an example of using hooks:
93
+ * {@includeCode ../../test/agents/agent.test.ts#example-agent-hooks}
94
+ */
95
+ hooks;
96
+ /**
97
+ * List of GuideRail agents applied to this agent
98
+ *
99
+ * GuideRail agents validate, transform, or control the message flow by:
100
+ * - Enforcing rules and safety policies
101
+ * - Validating inputs/outputs against specific criteria
102
+ * - Implementing business logic validations
103
+ * - Monitoring and auditing agent behavior
104
+ *
105
+ * Each GuideRail agent can examine both input and expected output,
106
+ * and has the ability to abort the process with an explanation
107
+ *
108
+ * @example
109
+ * Here's an example of using GuideRail agents:
110
+ *
111
+ * {@includeCode ../../test/agents/agent.test.ts#example-agent-guide-rails}
112
+ */
113
+ guideRails;
73
114
  /**
74
115
  * Name of the agent, used for identification and logging
75
116
  *
@@ -209,61 +250,71 @@ export class Agent {
209
250
  /**
210
251
  * Check context status to ensure it hasn't timed out
211
252
  *
212
- * @param context The context to check
253
+ * @param options Invocation options containing context
213
254
  * @throws Error if the context has timed out
214
255
  */
215
- checkContextStatus(context) {
216
- if (context) {
217
- const { status } = context;
218
- if (status === "timeout") {
219
- throw new Error(`AIGNE for agent ${this.name} has timed out`);
220
- }
256
+ checkContextStatus(options) {
257
+ const { status } = options.context;
258
+ if (status === "timeout") {
259
+ throw new Error(`AIGNE for agent ${this.name} has timed out`);
221
260
  }
222
261
  }
223
262
  async newDefaultContext() {
224
263
  return import("../aigne/context.js").then((m) => new m.AIGNEContext());
225
264
  }
226
- async invoke(input, context, options) {
227
- const ctx = context ?? (await this.newDefaultContext());
265
+ async invoke(input, options = {}) {
266
+ const opts = {
267
+ ...options,
268
+ context: options.context ?? (await this.newDefaultContext()),
269
+ };
228
270
  const message = typeof input === "string" ? createMessage(input) : input;
229
- logger.core("Invoke agent %s started with input: %O", this.name, input);
271
+ logger.debug("Invoke agent %s started with input: %O", this.name, input);
230
272
  if (!this.disableEvents)
231
- ctx.emit("agentStarted", { agent: this, input: message });
273
+ opts.context.emit("agentStarted", { agent: this, input: message });
232
274
  try {
275
+ await this.hooks.onStart?.({ context: opts.context, input: message });
233
276
  const parsedInput = checkArguments(`Agent ${this.name} input`, this.inputSchema, message);
234
- this.preprocess(parsedInput, ctx);
235
- this.checkContextStatus(ctx);
236
- let response = await this.process(parsedInput, ctx);
277
+ await this.preprocess(parsedInput, opts);
278
+ this.checkContextStatus(opts);
279
+ let response = await this.process(parsedInput, opts);
237
280
  if (response instanceof Agent) {
238
281
  response = transferToAgentOutput(response);
239
282
  }
240
- if (options?.streaming) {
283
+ if (opts.streaming) {
241
284
  const stream = response instanceof ReadableStream
242
285
  ? response
243
286
  : isAsyncGenerator(response)
244
287
  ? asyncGeneratorToReadableStream(response)
245
288
  : objectToAgentResponseStream(response);
246
- return onAgentResponseStreamEnd(stream, async (result) => {
247
- return await this.processAgentOutput(parsedInput, result, ctx);
289
+ return this.checkResponseByGuideRails(message, onAgentResponseStreamEnd(stream, async (result) => {
290
+ return await this.processAgentOutput(parsedInput, result, opts);
248
291
  }, {
249
- errorCallback: (error) => {
250
- try {
251
- this.processAgentError(error, ctx);
252
- }
253
- catch (error) {
254
- return error;
255
- }
292
+ errorCallback: async (error) => {
293
+ return await this.processAgentError(message, error, opts);
256
294
  },
257
- });
295
+ }), opts);
258
296
  }
259
- return await this.processAgentOutput(parsedInput, response instanceof ReadableStream
297
+ return await this.checkResponseByGuideRails(message, this.processAgentOutput(parsedInput, response instanceof ReadableStream
260
298
  ? await agentResponseStreamToObject(response)
261
299
  : isAsyncGenerator(response)
262
300
  ? await agentResponseStreamToObject(response)
263
- : response, ctx);
301
+ : response, opts), opts);
264
302
  }
265
303
  catch (error) {
266
- this.processAgentError(error, ctx);
304
+ throw await this.processAgentError(message, error, opts);
305
+ }
306
+ }
307
+ async invokeSkill(skill, input, options) {
308
+ const { context } = options;
309
+ await this.hooks.onSkillStart?.({ context, skill, input });
310
+ try {
311
+ const output = await context.invoke(skill, input);
312
+ await this.hooks.onSkillEnd?.({ context, skill, input, output });
313
+ return output;
314
+ }
315
+ catch (error) {
316
+ await this.hooks.onSkillEnd?.({ context, skill, input, error });
317
+ throw error;
267
318
  }
268
319
  }
269
320
  /**
@@ -273,16 +324,18 @@ export class Agent {
273
324
  *
274
325
  * @param input Original input message
275
326
  * @param output Raw output produced by the agent
276
- * @param context Execution context
327
+ * @param options Invocation options
277
328
  * @returns Final processed output
278
329
  */
279
- async processAgentOutput(input, output, context) {
330
+ async processAgentOutput(input, output, options) {
331
+ const { context } = options;
280
332
  const parsedOutput = checkArguments(`Agent ${this.name} output`, this.outputSchema, output);
281
333
  const finalOutput = this.includeInputInOutput ? { ...input, ...parsedOutput } : parsedOutput;
282
- this.postprocess(input, finalOutput, context);
283
- logger.core("Invoke agent %s succeed with output: %O", this.name, finalOutput);
334
+ await this.postprocess(input, finalOutput, options);
335
+ logger.debug("Invoke agent %s succeed with output: %O", this.name, finalOutput);
284
336
  if (!this.disableEvents)
285
337
  context.emit("agentSucceed", { agent: this, output: finalOutput });
338
+ await this.hooks.onEnd?.({ context, input, output: finalOutput });
286
339
  return finalOutput;
287
340
  }
288
341
  /**
@@ -291,14 +344,15 @@ export class Agent {
291
344
  * Logs error information, triggers failure events, and re-throws the error
292
345
  *
293
346
  * @param error Caught error
294
- * @param context Execution context
295
- * @throws Always throws the received error
347
+ * @param options Invocation options
296
348
  */
297
- processAgentError(error, context) {
298
- logger.core("Invoke agent %s failed with error: %O", this.name, error);
349
+ async processAgentError(input, error, options) {
350
+ logger.error("Invoke agent %s failed with error: %O", this.name, error);
299
351
  if (!this.disableEvents)
300
- context.emit("agentFailed", { agent: this, error });
301
- throw error;
352
+ options.context.emit("agentFailed", { agent: this, error });
353
+ const { context } = options;
354
+ await this.hooks.onEnd?.({ context, input, error });
355
+ return error;
302
356
  }
303
357
  /**
304
358
  * Check agent invocation usage to prevent exceeding limits
@@ -306,11 +360,11 @@ export class Agent {
306
360
  * If the context has a maximum invocation limit set, checks if the limit
307
361
  * has been exceeded and increments the invocation counter
308
362
  *
309
- * @param context Execution context
363
+ * @param options Invocation options containing context and limits
310
364
  * @throws Error if maximum invocation limit is exceeded
311
365
  */
312
- checkAgentInvokesUsage(context) {
313
- const { limits, usage } = context;
366
+ checkAgentInvokesUsage(options) {
367
+ const { limits, usage } = options.context;
314
368
  if (limits?.maxAgentInvokes && usage.agentCalls >= limits.maxAgentInvokes) {
315
369
  throw new Error(`Exceeded max agent invokes ${usage.agentCalls}/${limits.maxAgentInvokes}`);
316
370
  }
@@ -324,11 +378,53 @@ export class Agent {
324
378
  * - Verifying invocation limits
325
379
  *
326
380
  * @param _ Input message (unused)
327
- * @param context Execution context
381
+ * @param options Options for agent invocation
382
+ */
383
+ async preprocess(_, options) {
384
+ this.checkContextStatus(options);
385
+ this.checkAgentInvokesUsage(options);
386
+ }
387
+ async checkResponseByGuideRails(input, output, options) {
388
+ if (!this.guideRails?.length)
389
+ return output;
390
+ const result = await output;
391
+ if (result instanceof ReadableStream) {
392
+ return onAgentResponseStreamEnd(result, async (result) => {
393
+ const error = await this.runGuideRails(input, result, options);
394
+ if (error) {
395
+ return {
396
+ ...(await this.onGuideRailError(error)),
397
+ $status: "GuideRailError",
398
+ };
399
+ }
400
+ });
401
+ }
402
+ const error = await this.runGuideRails(input, result, options);
403
+ if (!error)
404
+ return output;
405
+ return { ...(await this.onGuideRailError(error)), $status: "GuideRailError" };
406
+ }
407
+ async runGuideRails(input, output, options) {
408
+ const result = await Promise.all((this.guideRails ?? []).map((i) => options.context.invoke(i, { input, output })));
409
+ return result.find((i) => !!i.abort);
410
+ }
411
+ /**
412
+ * Handle errors detected by GuideRail agents
413
+ *
414
+ * This method is called when a GuideRail agent aborts the process, providing
415
+ * a way for agents to customize error handling behavior. By default, it simply
416
+ * returns the original error, but subclasses can override this method to:
417
+ * - Transform the error into a more specific response
418
+ * - Apply recovery strategies
419
+ * - Log or report the error in a custom format
420
+ * - Return a fallback output instead of an error
421
+ *
422
+ * @param error The GuideRail agent output containing abort=true and a reason
423
+ * @returns Either the original/modified error or a substitute output object
424
+ * which will be tagged with $status: "GuideRailError"
328
425
  */
329
- preprocess(_, context) {
330
- this.checkContextStatus(context);
331
- this.checkAgentInvokesUsage(context);
426
+ async onGuideRailError(error) {
427
+ return error;
332
428
  }
333
429
  /**
334
430
  * Post-processing operations after handling output
@@ -339,26 +435,26 @@ export class Agent {
339
435
  *
340
436
  * @param input Input message
341
437
  * @param output Output message
342
- * @param context Execution context
438
+ * @param options Options for agent invocation
343
439
  */
344
- postprocess(input, output, context) {
345
- this.checkContextStatus(context);
346
- this.publishToTopics(output, context);
440
+ async postprocess(input, output, options) {
441
+ this.checkContextStatus(options);
442
+ this.publishToTopics(output, options);
347
443
  for (const memory of this.memories) {
348
444
  if (memory.autoUpdate) {
349
- memory.record({
445
+ await memory.record({
350
446
  content: [
351
447
  { role: "user", content: input },
352
448
  { role: "agent", content: replaceTransferAgentToName(output), source: this.name },
353
449
  ],
354
- }, context);
450
+ }, options.context);
355
451
  }
356
452
  }
357
453
  }
358
- async publishToTopics(output, context) {
454
+ async publishToTopics(output, options) {
359
455
  const publishTopics = typeof this.publishTopic === "function" ? await this.publishTopic(output) : this.publishTopic;
360
456
  if (publishTopics?.length) {
361
- context.publish(publishTopics, {
457
+ options.context.publish(publishTopics, {
362
458
  role: this.constructor.name === "UserAgent" ? "user" : "agent",
363
459
  source: this.name,
364
460
  message: output,
@@ -510,11 +606,11 @@ export class FunctionAgent extends Agent {
510
606
  * Process input implementation, calls the configured processing function
511
607
  *
512
608
  * @param input Input message
513
- * @param context Execution context
609
+ * @param options Invocation options
514
610
  * @returns Processing result
515
611
  */
516
- process(input, context) {
517
- return this._process(input, context);
612
+ process(input, options) {
613
+ return this._process(input, options);
518
614
  }
519
615
  }
520
616
  function functionToAgent(agent) {
@@ -1,10 +1,9 @@
1
1
  import { type ZodObject, type ZodType, z } from "zod";
2
- import type { Context } from "../aigne/context.js";
3
- import { type DefaultMemoryOptions } from "../memory/default-memory.js";
4
- import { ChatModel } from "../models/chat-model.js";
5
- import type { ChatModelInput } from "../models/chat-model.js";
2
+ import { type DefaultMemoryOptions } from "../memory/default-memory/index.js";
6
3
  import { PromptBuilder } from "../prompt/prompt-builder.js";
7
- import { Agent, type AgentOptions, type AgentProcessAsyncGenerator, type Message } from "./agent.js";
4
+ import { Agent, type AgentInvokeOptions, type AgentOptions, type AgentProcessAsyncGenerator, type Message } from "./agent.js";
5
+ import { ChatModel, type ChatModelInput } from "./chat-model.js";
6
+ import type { GuideRailAgentOutput } from "./guide-rail-agent.js";
8
7
  /**
9
8
  * Configuration options for an AI Agent
10
9
  *
@@ -215,7 +214,8 @@ export declare class AIAgent<I extends Message = Message, O extends Message = Me
215
214
  *
216
215
  * @protected
217
216
  */
218
- process(input: I, context: Context): AgentProcessAsyncGenerator<O>;
217
+ process(input: I, options: AgentInvokeOptions): AgentProcessAsyncGenerator<O>;
218
+ protected onGuideRailError(error: GuideRailAgentOutput): Promise<O | GuideRailAgentOutput>;
219
219
  /**
220
220
  * Process router mode requests
221
221
  *
@@ -224,5 +224,5 @@ export declare class AIAgent<I extends Message = Message, O extends Message = Me
224
224
  *
225
225
  * @protected
226
226
  */
227
- _processRouter(input: I, model: ChatModel, modelInput: ChatModelInput, context: Context, toolsMap: Map<string, Agent>): AgentProcessAsyncGenerator<O>;
227
+ _processRouter(input: I, model: ChatModel, modelInput: ChatModelInput, options: AgentInvokeOptions, toolsMap: Map<string, Agent>): AgentProcessAsyncGenerator<O>;
228
228
  }
@@ -1,11 +1,11 @@
1
1
  import { z } from "zod";
2
- import { DefaultMemory } from "../memory/default-memory.js";
2
+ import { DefaultMemory } from "../memory/default-memory/index.js";
3
3
  import { MemoryAgent } from "../memory/memory.js";
4
- import { ChatModel } from "../models/chat-model.js";
5
4
  import { MESSAGE_KEY, PromptBuilder } from "../prompt/prompt-builder.js";
6
5
  import { AgentMessageTemplate, ToolMessageTemplate } from "../prompt/template.js";
7
6
  import { checkArguments, isEmpty } from "../utils/type-utils.js";
8
7
  import { Agent, agentOptionsSchema, } from "./agent.js";
8
+ import { ChatModel, } from "./chat-model.js";
9
9
  import { isTransferAgentOutput } from "./types.js";
10
10
  /**
11
11
  * Tool choice options for AI agents
@@ -185,26 +185,26 @@ export class AIAgent extends Agent {
185
185
  *
186
186
  * @protected
187
187
  */
188
- async *process(input, context) {
189
- const model = this.model ?? context.model;
188
+ async *process(input, options) {
189
+ const model = this.model ?? options.context.model;
190
190
  if (!model)
191
191
  throw new Error("model is required to run AIAgent");
192
192
  const { toolAgents, ...modelInput } = await this.instructions.build({
193
193
  agent: this,
194
194
  input,
195
195
  model,
196
- context,
196
+ context: options.context,
197
197
  });
198
198
  const toolsMap = new Map(toolAgents?.map((i) => [i.name, i]));
199
199
  if (this.toolChoice === "router") {
200
- yield* this._processRouter(input, model, modelInput, context, toolsMap);
200
+ yield* this._processRouter(input, model, modelInput, options, toolsMap);
201
201
  return;
202
202
  }
203
203
  const toolCallMessages = [];
204
204
  const outputKey = this.outputKey || MESSAGE_KEY;
205
205
  for (;;) {
206
206
  const modelOutput = {};
207
- const stream = await context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
207
+ const stream = await options.context.invoke(model, { ...modelInput, messages: modelInput.messages.concat(toolCallMessages) }, { streaming: true });
208
208
  for await (const value of stream) {
209
209
  if (value.delta.text?.text) {
210
210
  yield { delta: { text: { [outputKey]: value.delta.text.text } } };
@@ -222,9 +222,7 @@ export class AIAgent extends Agent {
222
222
  if (!tool)
223
223
  throw new Error(`Tool not found: ${call.function.name}`);
224
224
  // NOTE: should pass both arguments (model generated) and input (user provided) to the tool
225
- const output = await context
226
- .invoke(tool, { ...input, ...call.function.arguments }, { disableTransfer: true })
227
- .catch((error) => {
225
+ const output = await this.invokeSkill(tool, { ...input, ...call.function.arguments }, options).catch((error) => {
228
226
  if (!this.catchToolsError) {
229
227
  return Promise.reject(error);
230
228
  }
@@ -248,7 +246,7 @@ export class AIAgent extends Agent {
248
246
  }
249
247
  }
250
248
  const result = {};
251
- if (modelInput.responseFormat?.type === "json_schema") {
249
+ if (json) {
252
250
  Object.assign(result, json);
253
251
  }
254
252
  else if (text) {
@@ -260,6 +258,12 @@ export class AIAgent extends Agent {
260
258
  return;
261
259
  }
262
260
  }
261
+ async onGuideRailError(error) {
262
+ const outputKey = this.outputKey || MESSAGE_KEY;
263
+ return {
264
+ [outputKey]: error.reason,
265
+ };
266
+ }
263
267
  /**
264
268
  * Process router mode requests
265
269
  *
@@ -268,15 +272,15 @@ export class AIAgent extends Agent {
268
272
  *
269
273
  * @protected
270
274
  */
271
- async *_processRouter(input, model, modelInput, context, toolsMap) {
272
- const { toolCalls: [call] = [], } = await context.invoke(model, modelInput);
275
+ async *_processRouter(input, model, modelInput, options, toolsMap) {
276
+ const { toolCalls: [call] = [], } = await options.context.invoke(model, modelInput);
273
277
  if (!call) {
274
278
  throw new Error("Router toolChoice requires exactly one tool to be executed");
275
279
  }
276
280
  const tool = toolsMap.get(call.function.name);
277
281
  if (!tool)
278
282
  throw new Error(`Tool not found: ${call.function.name}`);
279
- const stream = await context.invoke(tool, { ...call.function.arguments, ...input }, { streaming: true });
283
+ const stream = await options.context.invoke(tool, { ...call.function.arguments, ...input }, { streaming: true, sourceAgent: this });
280
284
  yield* stream;
281
285
  }
282
286
  }
@@ -1,6 +1,5 @@
1
- import { Agent, type AgentProcessResult, type Message } from "../agents/agent.js";
2
- import type { Context } from "../aigne/context.js";
3
1
  import type { PromiseOrValue } from "../utils/type-utils.js";
2
+ import { Agent, type AgentInvokeOptions, type AgentProcessResult, type Message } from "./agent.js";
4
3
  /**
5
4
  * ChatModel is an abstract base class for interacting with Large Language Models (LLMs).
6
5
  *
@@ -10,19 +9,19 @@ import type { PromiseOrValue } from "../utils/type-utils.js";
10
9
  *
11
10
  * @example
12
11
  * Here's how to implement a custom ChatModel:
13
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model}
12
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model}
14
13
  *
15
14
  * @example
16
15
  * Here's an example showing streaming response with readable stream:
17
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-streaming}
16
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-streaming}
18
17
  *
19
18
  * @example
20
19
  * Here's an example showing streaming response with async generator:
21
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-streaming-async-generator}
20
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-streaming-async-generator}
22
21
  *
23
22
  * @example
24
23
  * Here's an example with tool calls:
25
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
24
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
26
25
  */
27
26
  export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelOutput> {
28
27
  constructor();
@@ -44,16 +43,27 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
44
43
  supportsParallelToolCalls: boolean;
45
44
  };
46
45
  private validateToolNames;
46
+ /**
47
+ * Normalizes tool names to ensure compatibility with language models
48
+ *
49
+ * This method converts tool names to a format that complies with model requirements
50
+ * by replacing hyphens and whitespace characters with underscores. The normalized
51
+ * names are used for tool calls while preserving the original names for reference.
52
+ *
53
+ * @param name - The original tool name to normalize
54
+ * @returns A promise that resolves to the normalized tool name
55
+ */
56
+ protected normalizeToolName(name: string): Promise<string>;
47
57
  /**
48
58
  * Performs preprocessing operations before handling input
49
59
  *
50
60
  * Primarily checks if token usage exceeds limits, throwing an exception if limits are exceeded
51
61
  *
52
62
  * @param input Input message
53
- * @param context Execution context
63
+ * @param options Options for invoking the agent
54
64
  * @throws Error if token usage exceeds maximum limit
55
65
  */
56
- protected preprocess(input: ChatModelInput, context: Context): void;
66
+ protected preprocess(input: ChatModelInput, options: AgentInvokeOptions): Promise<void>;
57
67
  /**
58
68
  * Performs postprocessing operations after handling output
59
69
  *
@@ -61,9 +71,9 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
61
71
  *
62
72
  * @param input Input message
63
73
  * @param output Output message
64
- * @param context Execution context
74
+ * @param options Options for invoking the agent
65
75
  */
66
- protected postprocess(input: ChatModelInput, output: ChatModelOutput, context: Context): void;
76
+ protected postprocess(input: ChatModelInput, output: ChatModelOutput, options: AgentInvokeOptions): Promise<void>;
67
77
  /**
68
78
  * Processes input messages and generates model responses
69
79
  *
@@ -81,10 +91,10 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
81
91
  * - Tool call processing if applicable
82
92
  *
83
93
  * @param input - The standardized input containing messages and model options
84
- * @param context - The execution context with settings and state
94
+ * @param options - The options for invoking the agent, including context and limits
85
95
  * @returns A promise or direct value containing the model's response
86
96
  */
87
- abstract process(input: ChatModelInput, context: Context): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
97
+ abstract process(input: ChatModelInput, options: AgentInvokeOptions): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
88
98
  }
89
99
  /**
90
100
  * Input message format for ChatModel
@@ -94,11 +104,11 @@ export declare abstract class ChatModel extends Agent<ChatModelInput, ChatModelO
94
104
  *
95
105
  * @example
96
106
  * Here's a basic ChatModel input example:
97
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model}
107
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model}
98
108
  *
99
109
  * @example
100
110
  * Here's an example with tool calling:
101
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
111
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
102
112
  */
103
113
  export interface ChatModelInput extends Message {
104
114
  /**
@@ -213,7 +223,7 @@ export type ChatModelInputResponseFormat = {
213
223
  *
214
224
  * @example
215
225
  * Here's an example showing how to use tools:
216
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
226
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
217
227
  */
218
228
  export interface ChatModelInputTool {
219
229
  /**
@@ -249,7 +259,7 @@ export interface ChatModelInputTool {
249
259
  *
250
260
  * @example
251
261
  * Here's an example showing how to use tools:
252
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
262
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
253
263
  */
254
264
  export type ChatModelInputToolChoice = "auto" | "none" | "required" | {
255
265
  type: "function";
@@ -296,11 +306,11 @@ export interface ChatModelOptions {
296
306
  *
297
307
  * @example
298
308
  * Here's a basic output example:
299
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model}
309
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model}
300
310
  *
301
311
  * @example
302
312
  * Here's an example with tool calls:
303
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
313
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
304
314
  */
305
315
  export interface ChatModelOutput extends Message {
306
316
  /**
@@ -331,7 +341,7 @@ export interface ChatModelOutput extends Message {
331
341
  *
332
342
  * @example
333
343
  * Here's an example with tool calls:
334
- * {@includeCode ../../test/models/chat-model.test.ts#example-chat-model-tools}
344
+ * {@includeCode ../../test/agents/chat-model.test.ts#example-chat-model-tools}
335
345
  */
336
346
  export interface ChatModelOutputToolCall {
337
347
  /**