@n8n/agents 0.7.1 → 0.8.1

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 (73) hide show
  1. package/dist/build.tsbuildinfo +1 -1
  2. package/dist/index.d.ts +10 -7
  3. package/dist/index.js +30 -10
  4. package/dist/index.js.map +1 -1
  5. package/dist/runtime/agent-runtime.d.ts +24 -12
  6. package/dist/runtime/agent-runtime.js +241 -91
  7. package/dist/runtime/agent-runtime.js.map +1 -1
  8. package/dist/runtime/background-task-tracker.d.ts +6 -0
  9. package/dist/runtime/background-task-tracker.js +26 -0
  10. package/dist/runtime/background-task-tracker.js.map +1 -0
  11. package/dist/runtime/deferred-tool-manager.d.ts +28 -0
  12. package/dist/runtime/deferred-tool-manager.js +205 -0
  13. package/dist/runtime/deferred-tool-manager.js.map +1 -0
  14. package/dist/runtime/memory-store.d.ts +21 -36
  15. package/dist/runtime/memory-store.js +118 -51
  16. package/dist/runtime/memory-store.js.map +1 -1
  17. package/dist/runtime/message-list.d.ts +1 -7
  18. package/dist/runtime/message-list.js +3 -6
  19. package/dist/runtime/message-list.js.map +1 -1
  20. package/dist/runtime/observation-log-defaults.d.ts +20 -0
  21. package/dist/runtime/observation-log-defaults.js +523 -0
  22. package/dist/runtime/observation-log-defaults.js.map +1 -0
  23. package/dist/runtime/observation-log-observer.d.ts +64 -0
  24. package/dist/runtime/observation-log-observer.js +235 -0
  25. package/dist/runtime/observation-log-observer.js.map +1 -0
  26. package/dist/runtime/observation-log-reflector.d.ts +36 -0
  27. package/dist/runtime/observation-log-reflector.js +292 -0
  28. package/dist/runtime/observation-log-reflector.js.map +1 -0
  29. package/dist/runtime/observation-log-renderer.d.ts +6 -0
  30. package/dist/runtime/observation-log-renderer.js +73 -0
  31. package/dist/runtime/observation-log-renderer.js.map +1 -0
  32. package/dist/runtime/observation-log-store.d.ts +3 -0
  33. package/dist/runtime/observation-log-store.js +26 -0
  34. package/dist/runtime/observation-log-store.js.map +1 -0
  35. package/dist/runtime/scoped-memory-task-runner.d.ts +79 -0
  36. package/dist/runtime/scoped-memory-task-runner.js +134 -0
  37. package/dist/runtime/scoped-memory-task-runner.js.map +1 -0
  38. package/dist/sdk/agent.d.ts +13 -1
  39. package/dist/sdk/agent.js +58 -9
  40. package/dist/sdk/agent.js.map +1 -1
  41. package/dist/sdk/catalog.d.ts +1 -0
  42. package/dist/sdk/catalog.js +1 -0
  43. package/dist/sdk/catalog.js.map +1 -1
  44. package/dist/sdk/memory.d.ts +12 -12
  45. package/dist/sdk/memory.js +71 -51
  46. package/dist/sdk/memory.js.map +1 -1
  47. package/dist/storage/base-memory.d.ts +0 -10
  48. package/dist/storage/base-memory.js +0 -6
  49. package/dist/storage/base-memory.js.map +1 -1
  50. package/dist/types/index.d.ts +5 -4
  51. package/dist/types/index.js +7 -3
  52. package/dist/types/index.js.map +1 -1
  53. package/dist/types/runtime/event.d.ts +1 -0
  54. package/dist/types/sdk/agent-builder.d.ts +5 -0
  55. package/dist/types/sdk/agent.d.ts +6 -0
  56. package/dist/types/sdk/memory.d.ts +16 -24
  57. package/dist/types/sdk/observation-log.d.ts +99 -0
  58. package/dist/types/sdk/observation-log.js +17 -0
  59. package/dist/types/sdk/observation-log.js.map +1 -0
  60. package/dist/types/sdk/observation.d.ts +3 -94
  61. package/dist/types/sdk/observation.js +0 -2
  62. package/dist/types/sdk/observation.js.map +1 -1
  63. package/dist/types/sdk/provider.d.ts +5 -2
  64. package/package.json +3 -7
  65. package/dist/runtime/working-memory.d.ts +0 -14
  66. package/dist/runtime/working-memory.js +0 -69
  67. package/dist/runtime/working-memory.js.map +0 -1
  68. package/dist/storage/postgres-memory.d.ts +0 -96
  69. package/dist/storage/postgres-memory.js +0 -431
  70. package/dist/storage/postgres-memory.js.map +0 -1
  71. package/dist/storage/sqlite-memory.d.ts +0 -70
  72. package/dist/storage/sqlite-memory.js +0 -354
  73. package/dist/storage/sqlite-memory.js.map +0 -1
@@ -38,19 +38,27 @@ const ai_1 = require("ai");
38
38
  const zod_to_json_schema_1 = require("zod-to-json-schema");
39
39
  const catalog_1 = require("../sdk/catalog");
40
40
  const message_1 = require("../sdk/message");
41
+ const background_task_tracker_1 = require("./background-task-tracker");
42
+ const deferred_tool_manager_1 = require("./deferred-tool-manager");
41
43
  const event_bus_1 = require("./event-bus");
42
44
  const json_value_1 = require("./json-value");
45
+ const logger_1 = require("./logger");
43
46
  const memory_store_1 = require("./memory-store");
44
47
  const message_list_1 = require("./message-list");
45
48
  const messages_1 = require("./messages");
46
49
  const model_factory_1 = require("./model-factory");
50
+ const observation_log_observer_1 = require("./observation-log-observer");
51
+ const observation_log_reflector_1 = require("./observation-log-reflector");
52
+ const observation_log_renderer_1 = require("./observation-log-renderer");
53
+ const observation_log_store_1 = require("./observation-log-store");
47
54
  const run_state_1 = require("./run-state");
48
55
  const runtime_helpers_1 = require("./runtime-helpers");
56
+ const scoped_memory_task_runner_1 = require("./scoped-memory-task-runner");
49
57
  const stream_1 = require("./stream");
50
58
  const strip_orphaned_tool_messages_1 = require("./strip-orphaned-tool-messages");
51
59
  const title_generation_1 = require("./title-generation");
52
60
  const tool_adapter_1 = require("./tool-adapter");
53
- const working_memory_1 = require("./working-memory");
61
+ const observation_log_1 = require("../types/sdk/observation-log");
54
62
  const parse_1 = require("../utils/parse");
55
63
  const zod_1 = require("../utils/zod");
56
64
  function isActiveSpanTracer(value) {
@@ -112,15 +120,29 @@ function buildAgentRootInputAttributes(config) {
112
120
  };
113
121
  }
114
122
  const MAX_LOOP_ITERATIONS = 20;
123
+ const logger = (0, logger_1.createFilteredLogger)();
115
124
  const EMPTY_MESSAGE_LIST = {
116
125
  messages: [],
117
126
  historyIds: [],
118
127
  inputIds: [],
119
128
  responseIds: [],
120
129
  };
130
+ function hasFunctionProperty(value, property) {
131
+ return property in value && typeof Reflect.get(value, property) === 'function';
132
+ }
133
+ function hasObservationLogObserverMemory(memory) {
134
+ return ((0, observation_log_store_1.hasObservationLogStore)(memory) &&
135
+ hasFunctionProperty(memory, 'getMessagesForScope') &&
136
+ hasFunctionProperty(memory, 'getCursor') &&
137
+ hasFunctionProperty(memory, 'setCursor'));
138
+ }
121
139
  class AgentRuntime {
122
140
  constructor(config) {
141
+ this.backgroundTasks = new background_task_tracker_1.BackgroundTaskTracker();
123
142
  this.config = config;
143
+ if (config.deferredTools && config.deferredTools.length > 0) {
144
+ this.deferredToolManager = new deferred_tool_manager_1.DeferredToolManager(config.deferredTools, config.toolSearch);
145
+ }
124
146
  this.runState = new run_state_1.RunStateManager(config.checkpointStorage);
125
147
  this.eventBus = config.eventBus ?? new event_bus_1.AgentEventBus();
126
148
  this.currentState = {
@@ -130,6 +152,9 @@ class AgentRuntime {
130
152
  pendingToolCalls: {},
131
153
  };
132
154
  }
155
+ async dispose() {
156
+ await this.backgroundTasks.flush();
157
+ }
133
158
  getState() {
134
159
  return { ...this.currentState };
135
160
  }
@@ -178,7 +203,9 @@ class AgentRuntime {
178
203
  const toolCall = state.pendingToolCalls[options.toolCallId];
179
204
  if (!toolCall)
180
205
  throw new Error(`No tool call found for toolCallId: ${options.toolCallId}`);
181
- const tool = this.config.tools?.find((t) => t.name === toolCall.toolName);
206
+ const list = message_list_1.AgentMessageList.deserialize(state.messageList);
207
+ this.hydrateDeferredToolsFromList(list);
208
+ const tool = this.getCurrentTools().find((t) => t.name === toolCall.toolName);
182
209
  if (!tool)
183
210
  throw new Error(`Tool ${toolCall.toolName} not found`);
184
211
  let resumeData = data;
@@ -190,7 +217,6 @@ class AgentRuntime {
190
217
  resumeData = parseResult.data;
191
218
  }
192
219
  try {
193
- const list = message_list_1.AgentMessageList.deserialize(state.messageList);
194
220
  const { runId: _rid, toolCallId: _tcid, ...callerExecOptions } = options;
195
221
  const persisted = state.executionOptions ?? {};
196
222
  const mergedExecOptions = {
@@ -209,7 +235,7 @@ class AgentRuntime {
209
235
  messages: state.messageList.messages,
210
236
  };
211
237
  await this.ensureModelCost();
212
- await this.setListWorkingMemoryConfig(list, state.persistence);
238
+ await this.setListObservationLogMemory(list, state.persistence);
213
239
  if (method === 'generate') {
214
240
  const rawResult = await this.withTelemetryRootSpan('generate', resumeOptions, options.runId, async () => await this.runGenerateLoop({
215
241
  list,
@@ -254,6 +280,7 @@ class AgentRuntime {
254
280
  if (this.config.memory && options?.persistence?.threadId) {
255
281
  const memMessages = await this.config.memory.getMessages(options.persistence.threadId, {
256
282
  limit: this.config.lastMessages ?? 10,
283
+ resourceId: options.persistence.resourceId,
257
284
  });
258
285
  if (memMessages.length > 0) {
259
286
  list.addHistory((0, strip_orphaned_tool_messages_1.stripOrphanedToolMessages)(memMessages));
@@ -262,7 +289,7 @@ class AgentRuntime {
262
289
  if (this.config.semanticRecall && options?.persistence?.threadId) {
263
290
  await this.performSemanticRecall(list, input, options.persistence.threadId, options.persistence.resourceId);
264
291
  }
265
- await this.setListWorkingMemoryConfig(list, options?.persistence);
292
+ await this.setListObservationLogMemory(list, options?.persistence);
266
293
  list.addInput(input);
267
294
  return list;
268
295
  }
@@ -353,6 +380,7 @@ class AgentRuntime {
353
380
  this.eventBus.emit({ type: "agent_start" });
354
381
  await this.ensureModelCost();
355
382
  const normalizedInput = (0, runtime_helpers_1.normalizeInput)(input);
383
+ this.incrementMessageCount(options?.executionCounter);
356
384
  return await this.buildMessageList(normalizedInput, options);
357
385
  }
358
386
  finalizeGenerate(result, list, runId) {
@@ -423,6 +451,31 @@ class AgentRuntime {
423
451
  ...this.buildTelemetryMetadataAttributes(t, 'ai.telemetry.metadata'),
424
452
  };
425
453
  }
454
+ recordExecutionCounter(fn) {
455
+ try {
456
+ fn();
457
+ }
458
+ catch {
459
+ }
460
+ }
461
+ incrementMessageCount(counter) {
462
+ if (!counter)
463
+ return;
464
+ this.recordExecutionCounter(() => counter.incrementMessageCount());
465
+ }
466
+ incrementToolCallCount(counter) {
467
+ if (!counter)
468
+ return;
469
+ this.recordExecutionCounter(() => counter.incrementToolCallCount());
470
+ }
471
+ incrementTokenCount(counter, usage) {
472
+ if (!counter || !usage)
473
+ return;
474
+ const tokenCount = usage.totalTokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0);
475
+ if (tokenCount <= 0)
476
+ return;
477
+ this.recordExecutionCounter(() => counter.incrementTokenCount(tokenCount));
478
+ }
426
479
  async withTelemetryRootSpan(operation, options, runId, fn) {
427
480
  const t = this.resolveTelemetry(options);
428
481
  if (!t?.enabled || t.runtimeRootSpanEnabled === false || !isActiveSpanTracer(t.tracer)) {
@@ -478,16 +531,30 @@ class AgentRuntime {
478
531
  }
479
532
  async runGenerateLoop(ctx) {
480
533
  const { list, options, runId, pendingResume } = ctx;
481
- const { model, toolMap, aiTools, providerOptions, hasTools, outputSpec, effectiveInstructions, } = this.buildLoopContext({ ...options, persistence: options?.persistence });
534
+ this.hydrateDeferredToolsFromList(list);
482
535
  let totalUsage;
483
536
  let lastFinishReason = 'stop';
484
537
  let structuredOutput;
485
538
  const toolCallSummary = [];
486
539
  const collectedSubAgentUsage = [];
487
540
  const runTelemetry = this.resolveTelemetry(options);
488
- const toolCtx = { toolMap, list, runId, telemetry: runTelemetry };
541
+ const staticLoopContext = this.buildStaticLoopContext({
542
+ ...options,
543
+ persistence: options?.persistence,
544
+ });
545
+ const pendingLoopContext = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
546
+ const pendingToolCtx = {
547
+ toolMap: pendingLoopContext.toolMap,
548
+ list,
549
+ runId,
550
+ telemetry: runTelemetry,
551
+ executionCounter: options?.executionCounter,
552
+ };
489
553
  if (pendingResume) {
490
- const batch = await this.iteratePendingToolCallsConcurrent({ ...toolCtx, pendingResume });
554
+ const batch = await this.iteratePendingToolCallsConcurrent({
555
+ ...pendingToolCtx,
556
+ pendingResume,
557
+ });
491
558
  for (const r of batch.results) {
492
559
  toolCallSummary.push(r.toolEntry);
493
560
  if (r.subAgentUsage)
@@ -518,32 +585,38 @@ class AgentRuntime {
518
585
  throw new Error('Agent run was aborted');
519
586
  }
520
587
  this.eventBus.emit({ type: "turn_start" });
588
+ const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
521
589
  const result = await (0, ai_1.generateText)({
522
- model,
590
+ model: staticLoopContext.model,
523
591
  messages: list.forLlm(effectiveInstructions, this.config.instructionProviderOptions),
524
592
  abortSignal: this.eventBus.signal,
525
593
  ...(hasTools ? { tools: aiTools } : {}),
526
- ...(providerOptions
527
- ? { providerOptions: providerOptions }
594
+ ...(staticLoopContext.providerOptions
595
+ ? { providerOptions: staticLoopContext.providerOptions }
528
596
  : {}),
529
- ...(outputSpec ? { output: outputSpec } : {}),
597
+ ...(staticLoopContext.outputSpec ? { output: staticLoopContext.outputSpec } : {}),
530
598
  ...this.buildTelemetryOptions(options),
531
599
  });
532
600
  const aiFinishReason = result.finishReason;
533
601
  lastFinishReason = (0, messages_1.fromAiFinishReason)(aiFinishReason);
534
602
  totalUsage = (0, runtime_helpers_1.accumulateUsage)(totalUsage, result.usage);
603
+ this.incrementTokenCount(options?.executionCounter, result.usage);
535
604
  const responseMessages = result.response.messages;
536
605
  const newMessages = (0, messages_1.fromAiMessages)(responseMessages);
537
606
  list.addResponse(newMessages);
538
607
  if (aiFinishReason !== 'tool-calls') {
539
- if (outputSpec) {
608
+ if (staticLoopContext.outputSpec) {
540
609
  structuredOutput = result.output;
541
610
  }
542
611
  this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractSettledToolCalls)(newMessages));
543
612
  break;
544
613
  }
545
614
  const batch = await this.iterateToolCallsConcurrent({
546
- ...toolCtx,
615
+ toolMap,
616
+ list,
617
+ runId,
618
+ telemetry: runTelemetry,
619
+ executionCounter: options?.executionCounter,
547
620
  toolCalls: result.toolCalls,
548
621
  });
549
622
  for (const r of batch.results) {
@@ -584,6 +657,7 @@ class AgentRuntime {
584
657
  agentModel: this.config.model,
585
658
  turnDelta: list.turnDelta(),
586
659
  });
660
+ this.backgroundTasks.track(titlePromise);
587
661
  if (this.config.titleGeneration.sync) {
588
662
  await titlePromise;
589
663
  }
@@ -634,7 +708,7 @@ class AgentRuntime {
634
708
  }
635
709
  async runStreamLoop(ctx) {
636
710
  const { list, options, runId, pendingResume, writer } = ctx;
637
- const { model, toolMap, aiTools, providerOptions, hasTools, outputSpec, effectiveInstructions, } = this.buildLoopContext({ ...options, persistence: options?.persistence });
711
+ this.hydrateDeferredToolsFromList(list);
638
712
  const writeChunk = async (chunk) => {
639
713
  await writer.write(chunk);
640
714
  };
@@ -657,11 +731,22 @@ class AgentRuntime {
657
731
  return true;
658
732
  };
659
733
  const runTelemetry = this.resolveTelemetry(options);
660
- const toolCtx = { toolMap, list, runId, telemetry: runTelemetry };
734
+ const staticLoopContext = this.buildStaticLoopContext({
735
+ ...options,
736
+ persistence: options?.persistence,
737
+ });
738
+ const pendingLoopContext = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
739
+ const pendingToolCtx = {
740
+ toolMap: pendingLoopContext.toolMap,
741
+ list,
742
+ runId,
743
+ telemetry: runTelemetry,
744
+ executionCounter: options?.executionCounter,
745
+ };
661
746
  if (pendingResume) {
662
747
  try {
663
748
  const batch = await this.iteratePendingToolCallsConcurrent({
664
- ...toolCtx,
749
+ ...pendingToolCtx,
665
750
  pendingResume,
666
751
  });
667
752
  for (const r of batch.results) {
@@ -714,16 +799,17 @@ class AgentRuntime {
714
799
  if (await handleAbort())
715
800
  return;
716
801
  this.eventBus.emit({ type: "turn_start" });
802
+ const { toolMap, aiTools, hasTools, effectiveInstructions } = this.buildToolLoopContext(staticLoopContext.aiProviderTools);
717
803
  const messages = list.forLlm(effectiveInstructions, this.config.instructionProviderOptions);
718
804
  const result = (0, ai_1.streamText)({
719
- model,
805
+ model: staticLoopContext.model,
720
806
  messages,
721
807
  abortSignal: this.eventBus.signal,
722
808
  ...(hasTools ? { tools: aiTools } : {}),
723
- ...(providerOptions
724
- ? { providerOptions: providerOptions }
809
+ ...(staticLoopContext.providerOptions
810
+ ? { providerOptions: staticLoopContext.providerOptions }
725
811
  : {}),
726
- ...(outputSpec ? { output: outputSpec } : {}),
812
+ ...(staticLoopContext.outputSpec ? { output: staticLoopContext.outputSpec } : {}),
727
813
  ...this.buildTelemetryOptions(options),
728
814
  });
729
815
  try {
@@ -753,11 +839,12 @@ class AgentRuntime {
753
839
  const response = await result.response;
754
840
  lastFinishReason = (0, messages_1.fromAiFinishReason)(aiFinishReason);
755
841
  totalUsage = (0, runtime_helpers_1.accumulateUsage)(totalUsage, usage);
842
+ this.incrementTokenCount(options?.executionCounter, usage);
756
843
  const responseMessages = response.messages;
757
844
  const newMessages = (0, messages_1.fromAiMessages)(responseMessages);
758
845
  list.addResponse(newMessages);
759
846
  if (aiFinishReason !== 'tool-calls') {
760
- if (outputSpec) {
847
+ if (staticLoopContext.outputSpec) {
761
848
  structuredOutput = await result.output;
762
849
  }
763
850
  this.emitTurnEnd(newMessages, (0, runtime_helpers_1.extractSettledToolCalls)(newMessages));
@@ -765,7 +852,14 @@ class AgentRuntime {
765
852
  }
766
853
  const toolCalls = await result.toolCalls;
767
854
  try {
768
- const batch = await this.iterateToolCallsConcurrent({ ...toolCtx, toolCalls });
855
+ const batch = await this.iterateToolCallsConcurrent({
856
+ toolMap,
857
+ list,
858
+ runId,
859
+ telemetry: runTelemetry,
860
+ executionCounter: options?.executionCounter,
861
+ toolCalls,
862
+ });
769
863
  if (await handleAbort())
770
864
  return;
771
865
  for (const r of batch.results) {
@@ -840,6 +934,7 @@ class AgentRuntime {
840
934
  agentModel: this.config.model,
841
935
  turnDelta: list.turnDelta(),
842
936
  });
937
+ this.backgroundTasks.track(titlePromise);
843
938
  if (this.config.titleGeneration.sync) {
844
939
  await titlePromise;
845
940
  }
@@ -863,6 +958,67 @@ class AgentRuntime {
863
958
  if (this.config.semanticRecall?.embedder && this.config.memory.saveEmbeddings) {
864
959
  await this.saveEmbeddingsForMessages(options.persistence.threadId, options.persistence.resourceId, delta);
865
960
  }
961
+ this.scheduleObservationLogJobs(options.persistence);
962
+ }
963
+ scheduleObservationLogJobs(persistence) {
964
+ const { memory, observationalMemory } = this.config;
965
+ if (!memory || !observationalMemory || !(0, observation_log_store_1.hasObservationLogStore)(memory))
966
+ return;
967
+ const scope = this.getObservationLogScope(persistence);
968
+ const runner = this.getMemoryTaskRunner(memory, observationalMemory);
969
+ const observe = observationalMemory.observe;
970
+ const observerThresholdTokens = observationalMemory.observerThresholdTokens;
971
+ if (observe &&
972
+ observerThresholdTokens !== undefined &&
973
+ hasObservationLogObserverMemory(memory)) {
974
+ runner.schedule({ ...scope, taskKind: 'observer' }, async () => await (0, observation_log_observer_1.runObservationLogObserver)({
975
+ memory,
976
+ ...scope,
977
+ observerThresholdTokens,
978
+ observationLogTailLimit: observationalMemory.observationLogTailLimit ?? 0,
979
+ observe,
980
+ messageSource: {
981
+ threadId: persistence.threadId,
982
+ resourceId: persistence.resourceId,
983
+ },
984
+ }));
985
+ }
986
+ const reflect = observationalMemory.reflect;
987
+ const reflectorThresholdTokens = observationalMemory.reflectorThresholdTokens;
988
+ if (reflect && reflectorThresholdTokens !== undefined) {
989
+ runner.schedule({ ...scope, taskKind: 'reflector' }, async () => await (0, observation_log_reflector_1.runObservationLogReflector)({
990
+ memory,
991
+ ...scope,
992
+ reflectorThresholdTokens,
993
+ reflect,
994
+ }));
995
+ }
996
+ }
997
+ getMemoryTaskRunner(memory, observationalMemory) {
998
+ this.memoryTasks ??= new scoped_memory_task_runner_1.ScopedMemoryTaskRunner({
999
+ tracker: this.backgroundTasks,
1000
+ lockStore: (0, observation_log_store_1.hasObservationLogTaskLockStore)(memory) ? memory : undefined,
1001
+ lockTtlMs: observationalMemory.lockTtlMs,
1002
+ onEvent: (event) => {
1003
+ if (event.type !== 'failed')
1004
+ return;
1005
+ const source = event.task.taskKind;
1006
+ const message = `Observation log ${source} task failed`;
1007
+ logger.warn(message, {
1008
+ error: event.error,
1009
+ scopeKind: event.task.scopeKind,
1010
+ scopeId: event.task.scopeId,
1011
+ });
1012
+ this.eventBus.emit({ type: "error", message, error: event.error, source });
1013
+ },
1014
+ });
1015
+ return this.memoryTasks;
1016
+ }
1017
+ getObservationLogScope(persistence) {
1018
+ return {
1019
+ scopeKind: 'thread',
1020
+ scopeId: (0, observation_log_1.createObservationLogThreadScopeId)(persistence.threadId, persistence.resourceId),
1021
+ };
866
1022
  }
867
1023
  async saveEmbeddingsForMessages(threadId, resourceId, messages) {
868
1024
  const embeddable = [];
@@ -908,12 +1064,12 @@ class AgentRuntime {
908
1064
  switch (provider) {
909
1065
  case 'anthropic': {
910
1066
  const cfg = thinking;
1067
+ if (cfg.mode === 'adaptive') {
1068
+ return { anthropic: { thinking: { type: 'adaptive' } } };
1069
+ }
911
1070
  return {
912
1071
  anthropic: {
913
- thinking: {
914
- type: 'enabled',
915
- budgetTokens: cfg.budgetTokens ?? 10000,
916
- },
1072
+ thinking: { type: 'enabled', budgetTokens: cfg.budgetTokens ?? 10000 },
917
1073
  },
918
1074
  };
919
1075
  }
@@ -960,8 +1116,12 @@ class AgentRuntime {
960
1116
  return merged;
961
1117
  }
962
1118
  async iterateToolCallsConcurrent(ctx) {
963
- const { toolCalls, toolMap, list, runId, telemetry: resolvedTelemetry } = ctx;
1119
+ const { toolCalls, toolMap, list, runId, telemetry: resolvedTelemetry, executionCounter } = ctx;
964
1120
  const executableCalls = toolCalls.filter((tc) => !tc.providerExecuted);
1121
+ const providerExecutedCount = toolCalls.length - executableCalls.length;
1122
+ for (let i = 0; i < providerExecutedCount; i++) {
1123
+ this.incrementToolCallCount(executionCounter);
1124
+ }
965
1125
  const executableCallsById = new Map(executableCalls.map((tc) => [tc.toolCallId, tc]));
966
1126
  const unexecutedIds = new Set(executableCalls.map((tc) => tc.toolCallId));
967
1127
  const batchSize = this.concurrency;
@@ -975,7 +1135,7 @@ class AgentRuntime {
975
1135
  throw new Error('Agent run was aborted');
976
1136
  }
977
1137
  const batch = executableCalls.slice(batchStart, batchStart + batchSize);
978
- const settledResults = await Promise.allSettled(batch.map(async (tc) => await this.processToolCall(tc.toolCallId, tc.toolName, tc.input, toolMap, list, undefined, resolvedTelemetry)));
1138
+ const settledResults = await Promise.allSettled(batch.map(async (tc) => await this.processToolCall(tc.toolCallId, tc.toolName, tc.input, toolMap, list, undefined, resolvedTelemetry, executionCounter, true)));
979
1139
  for (const tc of batch) {
980
1140
  unexecutedIds.delete(tc.toolCallId);
981
1141
  }
@@ -1050,7 +1210,7 @@ class AgentRuntime {
1050
1210
  return { results, suspensions, errors, pending };
1051
1211
  }
1052
1212
  async iteratePendingToolCallsConcurrent(ctx) {
1053
- const { pendingResume, toolMap, list, runId, telemetry: resolvedTelemetry } = ctx;
1213
+ const { pendingResume, toolMap, list, runId, telemetry: resolvedTelemetry, executionCounter, } = ctx;
1054
1214
  const resumedId = pendingResume.resumeToolCallId;
1055
1215
  const resumedEntry = pendingResume.pendingToolCalls[resumedId];
1056
1216
  if (!resumedEntry) {
@@ -1061,7 +1221,7 @@ class AgentRuntime {
1061
1221
  const suspensions = [];
1062
1222
  const errors = [];
1063
1223
  const pending = {};
1064
- const processResult = await this.processToolCall(resumedEntry.toolCallId, resumedToolName, resumedEntry.input, toolMap, list, pendingResume.resumeData, resolvedTelemetry);
1224
+ const processResult = await this.processToolCall(resumedEntry.toolCallId, resumedToolName, resumedEntry.input, toolMap, list, pendingResume.resumeData, resolvedTelemetry, executionCounter, false);
1065
1225
  if (processResult.outcome === 'suspended') {
1066
1226
  pending[resumedId] = {
1067
1227
  ...resumedEntry,
@@ -1129,6 +1289,7 @@ class AgentRuntime {
1129
1289
  list,
1130
1290
  runId,
1131
1291
  telemetry: resolvedTelemetry,
1292
+ executionCounter,
1132
1293
  });
1133
1294
  results.push(...batch.results);
1134
1295
  suspensions.push(...batch.suspensions);
@@ -1137,7 +1298,7 @@ class AgentRuntime {
1137
1298
  }
1138
1299
  return { results, suspensions, errors, pending };
1139
1300
  }
1140
- async processToolCall(toolCallId, toolName, toolInput, toolMap, list, resumeData, resolvedTelemetry) {
1301
+ async processToolCall(toolCallId, toolName, toolInput, toolMap, list, resumeData, resolvedTelemetry, executionCounter, countToolCall = true) {
1141
1302
  const builtTool = toolMap.get(toolName);
1142
1303
  this.eventBus.emit({
1143
1304
  type: "tool_execution_start",
@@ -1180,6 +1341,9 @@ class AgentRuntime {
1180
1341
  });
1181
1342
  return { outcome: 'noop' };
1182
1343
  }
1344
+ if (countToolCall) {
1345
+ this.incrementToolCallCount(executionCounter);
1346
+ }
1183
1347
  if (builtTool.inputSchema) {
1184
1348
  const result = await (0, parse_1.parseWithSchema)(builtTool.inputSchema, toolInput);
1185
1349
  if (!result.success) {
@@ -1252,27 +1416,47 @@ class AgentRuntime {
1252
1416
  customMessage,
1253
1417
  };
1254
1418
  }
1255
- buildLoopContext(execOptions) {
1256
- const wmTool = this.buildWorkingMemoryToolForRun(execOptions?.persistence);
1257
- const allUserTools = wmTool
1258
- ? [...(this.config.tools ?? []), wmTool]
1259
- : (this.config.tools ?? []);
1260
- const aiTools = (0, tool_adapter_1.toAiSdkTools)(allUserTools);
1419
+ buildStaticLoopContext(execOptions) {
1261
1420
  const aiProviderTools = (0, tool_adapter_1.toAiSdkProviderTools)(this.config.providerTools);
1262
- const allTools = { ...aiTools, ...aiProviderTools };
1263
1421
  const model = (0, model_factory_1.createModel)(this.config.model);
1264
1422
  return {
1265
1423
  model,
1266
- toolMap: (0, tool_adapter_1.buildToolMap)(allUserTools),
1267
- aiTools: allTools,
1424
+ aiProviderTools,
1268
1425
  providerOptions: this.buildCallProviderOptions(execOptions?.providerOptions),
1269
- hasTools: Object.keys(allTools).length > 0,
1270
1426
  outputSpec: this.config.structuredOutput
1271
1427
  ? ai_1.Output.object({ schema: this.config.structuredOutput })
1272
1428
  : undefined,
1273
- effectiveInstructions: this.composeEffectiveInstructions(allUserTools),
1274
1429
  };
1275
1430
  }
1431
+ buildToolLoopContext(aiProviderTools) {
1432
+ const allUserTools = this.getCurrentTools();
1433
+ const aiTools = (0, tool_adapter_1.toAiSdkTools)(allUserTools);
1434
+ const allTools = { ...aiTools, ...aiProviderTools };
1435
+ const aiToolCount = Object.keys(allTools).length;
1436
+ const toolMap = (0, tool_adapter_1.buildToolMap)(allUserTools);
1437
+ const effectiveInstructions = this.composeEffectiveInstructions(allUserTools);
1438
+ return {
1439
+ toolMap,
1440
+ aiTools: allTools,
1441
+ hasTools: aiToolCount > 0,
1442
+ effectiveInstructions,
1443
+ };
1444
+ }
1445
+ getCurrentTools() {
1446
+ const baseTools = this.config.tools ?? [];
1447
+ if (!this.deferredToolManager?.hasTools)
1448
+ return baseTools;
1449
+ return [
1450
+ ...baseTools,
1451
+ ...this.deferredToolManager.getControllerTools(),
1452
+ ...this.deferredToolManager.getLoadedTools(),
1453
+ ];
1454
+ }
1455
+ hydrateDeferredToolsFromList(list) {
1456
+ if (!this.deferredToolManager?.hasTools)
1457
+ return;
1458
+ this.deferredToolManager.hydrateLoadedToolsFromMessages(list.serialize().messages);
1459
+ }
1276
1460
  composeEffectiveInstructions(tools) {
1277
1461
  const fragments = tools
1278
1462
  .map((t) => t.systemInstruction)
@@ -1283,16 +1467,6 @@ class AgentRuntime {
1283
1467
  const block = `<built_in_rules>\n${fragments.map((f) => `- ${f}`).join('\n')}\n</built_in_rules>`;
1284
1468
  return userInstructions ? `${block}\n\n${userInstructions}` : block;
1285
1469
  }
1286
- buildWorkingMemoryToolForRun(persistence) {
1287
- const wmParams = this.resolveWorkingMemoryParams(persistence);
1288
- if (!wmParams)
1289
- return undefined;
1290
- return (0, working_memory_1.buildWorkingMemoryTool)({
1291
- structured: wmParams.structured,
1292
- schema: wmParams.schema,
1293
- persist: wmParams.persistFn,
1294
- });
1295
- }
1296
1470
  async persistSuspension(pendingToolCalls, options, list, totalUsage, existingRunId) {
1297
1471
  const runId = existingRunId ?? (0, run_state_1.generateRunId)();
1298
1472
  const executionOptions = options?.maxIterations !== undefined ? { maxIterations: options.maxIterations } : undefined;
@@ -1352,46 +1526,22 @@ class AgentRuntime {
1352
1526
  return usage;
1353
1527
  return { ...usage, cost: (0, catalog_1.computeCost)(usage, this.modelCost) };
1354
1528
  }
1355
- async setListWorkingMemoryConfig(list, options) {
1356
- const wmParams = this.resolveWorkingMemoryParams(options);
1357
- if (!wmParams || !this.config.memory?.getWorkingMemory)
1529
+ async setListObservationLogMemory(list, options) {
1530
+ const memory = this.config.memory;
1531
+ if (!memory || !options?.threadId || !(0, observation_log_store_1.hasObservationLogStore)(memory))
1358
1532
  return;
1359
- const wmState = await this.config.memory.getWorkingMemory(wmParams.memoryParams);
1360
- list.workingMemory = {
1361
- template: wmParams.template,
1362
- structured: wmParams.structured,
1363
- state: wmState,
1364
- ...(wmParams.instruction !== undefined && { instruction: wmParams.instruction }),
1365
- };
1533
+ const scope = this.getObservationLogScope(options);
1534
+ const observations = await memory.getActiveObservationLog({
1535
+ ...scope,
1536
+ order: 'asc',
1537
+ });
1538
+ list.observationLogMemory =
1539
+ (0, observation_log_renderer_1.renderObservationLog)(observations, {
1540
+ renderTokenBudget: this.config.observationLog?.renderTokenBudget,
1541
+ }) ?? undefined;
1366
1542
  }
1367
- resolveWorkingMemoryParams(options) {
1368
- if (!options)
1369
- return null;
1370
- if (!this.config.workingMemory)
1371
- return null;
1372
- const scope = this.config.workingMemory?.scope ?? 'resource';
1373
- if (scope === 'resource' && !options.resourceId) {
1374
- throw new Error('Working memory scope is "resource" but no resourceId was provided. ' +
1375
- 'Pass a resourceId in RunOptions or change the scope to "thread".');
1376
- }
1377
- if (!options)
1378
- return null;
1379
- const memoryParams = { ...options, scope };
1380
- const persistFn = this.config.workingMemory && this.config.memory?.saveWorkingMemory && options
1381
- ? async (content) => {
1382
- await this.config.memory.saveWorkingMemory(memoryParams, content);
1383
- }
1384
- : undefined;
1385
- if (!persistFn)
1386
- return null;
1387
- return {
1388
- persistFn,
1389
- memoryParams,
1390
- template: this.config.workingMemory.template,
1391
- structured: this.config.workingMemory.structured,
1392
- schema: this.config.workingMemory.schema,
1393
- instruction: this.config.workingMemory.instruction,
1394
- };
1543
+ getConfiguredTelemetry() {
1544
+ return this.config.telemetry;
1395
1545
  }
1396
1546
  }
1397
1547
  exports.AgentRuntime = AgentRuntime;