@cognipeer/agent-sdk 0.5.3 → 0.6.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.
package/README.md CHANGED
@@ -136,7 +136,12 @@ const agent = createSmartAgent({
136
136
  memory: { provider: "inMemory", scope: "session", writePolicy: "auto_important" },
137
137
  summarization: { summaryTriggerTokens: 8000, summaryMode: "incremental" },
138
138
  context: { policy: "hybrid", lastTurnsToKeep: 8 },
139
- toolResponses: { maxToolResponseChars: 4000, maxToolResponseTokens: 1200 },
139
+ toolResponses: {
140
+ defaultPolicy: "summarize_archive",
141
+ toolResponseRetentionByTool: { read_skills: "keep_full" },
142
+ maxToolResponseChars: 4000,
143
+ maxToolResponseTokens: 1200,
144
+ },
140
145
  limits: { maxToolCalls: 5, maxContextTokens: 12000 },
141
146
  tracing: { enabled: true },
142
147
  });
@@ -149,6 +154,14 @@ const result = await agent.invoke({
149
154
  console.log(result.content);
150
155
  ```
151
156
 
157
+ Tool-response retention is lazy and summarizer-driven:
158
+
159
+ - Tool outputs are stored at full fidelity in `state.toolHistory` and are never reduced at tool-call time.
160
+ - When the summarizer runs (context limits reached), old tool messages are rewritten in place according to `defaultPolicy` (default: `summarize_archive`). The full payload is still recoverable via `get_tool_response` using the execution id embedded in the placeholder.
161
+ - `toolResponseRetentionByTool` lets you opt specific tools out of reduction (e.g. `read_skills: "keep_full"`).
162
+ - `criticalTools` are never reduced. The built-in list covers `response`, `manage_todo_list`, and `get_tool_response`.
163
+ - `maxToolResponseChars` / `maxToolResponseTokens` only drive an eager hard-cap truncation when a single tool output is big enough to blow up the very next model call. The truncated head always points at `get_tool_response` for recovery.
164
+
152
165
  The smart wrapper now supports runtime presets (`fast`, `balanced`, `deep`, `research`), custom profiles layered on top of a base preset, structured summarization, hybrid context compaction, configurable tool-response retention, in-memory fact storage, delegation limits, and an eval harness via `runSmartAgentEvalHarness(...)`.
153
166
 
154
167
  You can also define a custom profile by extending a built-in preset and overriding only the knobs you need:
@@ -201,6 +214,7 @@ console.log(res.content);
201
214
  - **Native provider layer** – call OpenAI, Anthropic, Azure, Bedrock, Vertex, and any OpenAI-compatible API directly. No LangChain required. Unified `ChatCompletionRequest` / `ChatCompletionResponse` schema with per-provider wire format conversion.
202
215
  - **Full token tracking** – every response surfaces `inputTokens`, `outputTokens`, `cachedInputTokens`, `cachedWriteTokens`, and `reasoningTokens` for all six providers.
203
216
  - **Summarization pipeline** – automatic chunking keeps tool call history within `contextTokenLimit` / `summaryTokenLimit`, archiving originals so `get_tool_response` can fetch them later.
217
+ - **Retention controls** – tool outputs can be kept full, reduced to structured previews, archived, or dropped based on size tiers, critical-tool fallback, per-tool overrides, and recent-response pinning.
204
218
  - **Planning discipline** – when planning is enabled the system prompt distinguishes full plan writes from incremental plan updates and emits `plan` events as todos change.
205
219
  - **Structured output** – supply `outputSchema` and the framework adds a hidden `response` finalize tool; parsed JSON is returned as `result.output`.
206
220
  - **Multi-agent orchestration** – reuse agents via `agent.asTool({ toolName })` or perform handoffs that swap runtimes mid-execution.
package/dist/index.cjs CHANGED
@@ -2136,15 +2136,13 @@ var BASE_DEFAULTS = {
2136
2136
  requireJsonOutputContract: true
2137
2137
  },
2138
2138
  toolResponses: {
2139
- maxToolResponseChars: 3600,
2140
- maxToolResponseTokens: 1200,
2141
- defaultPolicy: "keep_structured",
2142
- largeResponsePolicy: "summarize_archive",
2139
+ maxToolResponseChars: 12e3,
2140
+ maxToolResponseTokens: 3e3,
2141
+ defaultPolicy: "summarize_archive",
2143
2142
  toolResponseRetentionByTool: {},
2144
2143
  criticalTools: [...DEFAULT_CRITICAL_TOOLS],
2145
2144
  schemaValidation: "strict",
2146
- retryOnSchemaError: true,
2147
- fallbackPolicy: "keep_structured"
2145
+ retryOnSchemaError: true
2148
2146
  }
2149
2147
  };
2150
2148
  function buildProfile(overrides) {
@@ -2183,7 +2181,7 @@ var DEFAULT_PROFILE_CONFIGS = {
2183
2181
  },
2184
2182
  memory: { readPolicy: "recent_only" },
2185
2183
  delegation: { mode: "off", maxDelegationDepth: 1, maxChildCalls: 2, maxParallelChild: 1, childContextPolicy: "minimal" },
2186
- toolResponses: { maxToolResponseChars: 2400, maxToolResponseTokens: 800 }
2184
+ toolResponses: { maxToolResponseChars: 8e3, maxToolResponseTokens: 2e3 }
2187
2185
  }),
2188
2186
  balanced: buildProfile({}),
2189
2187
  deep: buildProfile({
@@ -2200,7 +2198,7 @@ var DEFAULT_PROFILE_CONFIGS = {
2200
2198
  },
2201
2199
  memory: { scope: "workspace" },
2202
2200
  delegation: { maxDelegationDepth: 3, maxChildCalls: 6 },
2203
- toolResponses: { maxToolResponseChars: 5400, maxToolResponseTokens: 1800 }
2201
+ toolResponses: { maxToolResponseChars: 16e3, maxToolResponseTokens: 4e3 }
2204
2202
  }),
2205
2203
  research: buildProfile({
2206
2204
  limits: { maxToolCalls: 20, maxParallelTools: 4, maxContextTokens: 56e3 },
@@ -2216,7 +2214,7 @@ var DEFAULT_PROFILE_CONFIGS = {
2216
2214
  },
2217
2215
  memory: { scope: "workspace" },
2218
2216
  delegation: { mode: "automatic", maxDelegationDepth: 4, maxChildCalls: 8, maxParallelChild: 3, childContextPolicy: "full" },
2219
- toolResponses: { maxToolResponseChars: 7200, maxToolResponseTokens: 2200 }
2217
+ toolResponses: { maxToolResponseChars: 24e3, maxToolResponseTokens: 6e3 }
2220
2218
  })
2221
2219
  };
2222
2220
  function mergeLimits(base, override) {
@@ -2423,57 +2421,65 @@ function summarizeObject(value) {
2423
2421
  return safeStringify(value);
2424
2422
  }
2425
2423
  function classifyToolResponse(toolName, output, config) {
2426
- const serialized = safeStringify(output);
2427
- const tokenCount = countApproxTokens(serialized);
2428
2424
  const criticalTools = new Set(config.toolResponses.criticalTools);
2429
2425
  if (criticalTools.has(toolName)) return "critical";
2426
+ const serialized = safeStringify(output);
2427
+ const tokenCount = countApproxTokens(serialized);
2430
2428
  if (tokenCount >= config.toolResponses.maxToolResponseTokens || serialized.length >= config.toolResponses.maxToolResponseChars) {
2431
2429
  return "verbose";
2432
2430
  }
2433
- if (serialized === "ok" || serialized === "true" || serialized === "null") {
2434
- return "redundant";
2435
- }
2436
2431
  return "informative";
2437
2432
  }
2438
- function resolveToolResponsePolicy(toolName, output, config) {
2433
+ function applyToolResponseHardCap(toolName, output, executionId, config) {
2439
2434
  const serialized = safeStringify(output);
2440
2435
  const tokenCount = countApproxTokens(serialized);
2441
2436
  const classification = classifyToolResponse(toolName, output, config);
2442
- const byTool = config.toolResponses.toolResponseRetentionByTool[toolName];
2443
- let retentionPolicy = byTool || config.toolResponses.defaultPolicy;
2444
- if (classification === "critical") {
2445
- retentionPolicy = byTool || config.toolResponses.fallbackPolicy;
2446
- } else if (classification === "verbose") {
2447
- retentionPolicy = byTool || config.toolResponses.largeResponsePolicy;
2448
- } else if (classification === "redundant") {
2449
- retentionPolicy = byTool || "drop";
2450
- }
2451
- const summary = summarizeObject(output);
2452
- if (retentionPolicy === "keep_full") {
2453
- return { classification, retentionPolicy, content: serialized, rawOutput: output, summary, tokenCount };
2454
- }
2455
- if (retentionPolicy === "keep_structured") {
2456
- return { classification, retentionPolicy, content: summary, rawOutput: output, summary, tokenCount };
2457
- }
2458
- if (retentionPolicy === "summarize_archive") {
2459
- return {
2460
- classification,
2461
- retentionPolicy,
2462
- content: `ARCHIVED_TOOL_RESPONSE: ${summary}`,
2463
- rawOutput: output,
2464
- summary,
2465
- tokenCount
2466
- };
2437
+ if (classification !== "verbose") {
2438
+ return { classification, content: serialized, rawOutput: output, tokenCount, truncated: false };
2467
2439
  }
2440
+ const cap = config.toolResponses.maxToolResponseChars;
2441
+ const head = serialized.slice(0, cap);
2442
+ const note = `
2443
+ ... [TRUNCATED ${serialized.length - cap} chars by hard cap. Use get_tool_response with executionId="${executionId}" to fetch the full payload.]`;
2468
2444
  return {
2469
2445
  classification,
2470
- retentionPolicy,
2471
- content: `DROPPED_TOOL_RESPONSE: ${summary}`,
2446
+ content: head + note,
2472
2447
  rawOutput: output,
2473
- summary,
2474
- tokenCount
2448
+ tokenCount,
2449
+ truncated: true
2475
2450
  };
2476
2451
  }
2452
+ function resolveSummarizationRetention(toolName, config) {
2453
+ const criticalTools = new Set(config.toolResponses.criticalTools);
2454
+ if (criticalTools.has(toolName)) return "keep_full";
2455
+ const byTool = config.toolResponses.toolResponseRetentionByTool[toolName];
2456
+ return byTool || config.toolResponses.defaultPolicy;
2457
+ }
2458
+ function renderRetainedToolMessage(args) {
2459
+ const { policy, rawOutput, toolName, toolCallId, executionId, prebuiltSummary } = args;
2460
+ if (policy === "keep_full") {
2461
+ return typeof rawOutput === "string" ? rawOutput : safeStringify(rawOutput);
2462
+ }
2463
+ const summary = prebuiltSummary || summarizeObject(rawOutput);
2464
+ const refs = [
2465
+ `toolName=${toolName}`,
2466
+ toolCallId ? `toolCallId=${toolCallId}` : null,
2467
+ executionId ? `executionId=${executionId}` : null
2468
+ ].filter(Boolean).join("; ");
2469
+ const refId = executionId || toolCallId || "";
2470
+ if (policy === "keep_structured") {
2471
+ return `STRUCTURED_TOOL_RESPONSE [${refs}]
2472
+ Preview: ${summary}
2473
+ Use get_tool_response with executionId "${refId}" to fetch the full payload when a specific field is needed.`;
2474
+ }
2475
+ if (policy === "summarize_archive") {
2476
+ return `ARCHIVED_TOOL_RESPONSE [${refs}]
2477
+ Summary: ${summary}
2478
+ Use get_tool_response with executionId "${refId}" to fetch the full payload.`;
2479
+ }
2480
+ return `DROPPED_TOOL_RESPONSE [${refs}]
2481
+ Use get_tool_response with executionId "${refId}" only if you must recover the original payload.`;
2482
+ }
2477
2483
  function validateToolArgs(tool, args) {
2478
2484
  const schema = tool.schema;
2479
2485
  if (!schema || typeof schema.parse !== "function") {
@@ -2752,52 +2758,25 @@ function createToolsNode(initialTools, opts) {
2752
2758
  state.ctx.__structuredOutputParsed = output.data;
2753
2759
  state.ctx.__finalizedDueToStructuredOutput = true;
2754
2760
  }
2755
- const responsePolicy = resolveToolResponsePolicy(toolName, output, resolved);
2761
+ const responsePolicy = applyToolResponseHardCap(toolName, output, executionId, resolved);
2756
2762
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2757
- const storedOutput = responsePolicy.retentionPolicy === "keep_full" ? output : responsePolicy.summary;
2758
2763
  toolHistory.push({
2759
2764
  executionId,
2760
2765
  toolName,
2761
2766
  args,
2762
- output: storedOutput,
2767
+ output,
2763
2768
  rawOutput: output,
2764
2769
  timestamp,
2765
2770
  tool_call_id: tc.id,
2766
- summarized: responsePolicy.retentionPolicy !== "keep_full",
2771
+ summarized: false,
2767
2772
  originalTokenCount: responsePolicy.tokenCount,
2768
2773
  classification: responsePolicy.classification,
2769
- retentionPolicy: responsePolicy.retentionPolicy,
2770
- summary: responsePolicy.summary,
2771
- archiveId: responsePolicy.retentionPolicy === "summarize_archive" || responsePolicy.retentionPolicy === "drop" ? executionId : void 0,
2774
+ retentionPolicy: "keep_full",
2775
+ summary: void 0,
2776
+ archiveId: void 0,
2772
2777
  status: "success"
2773
2778
  });
2774
- if (resolved.context.archiveLargeToolResponses && (responsePolicy.retentionPolicy === "summarize_archive" || responsePolicy.retentionPolicy === "drop")) {
2775
- toolHistoryArchived.push({
2776
- executionId,
2777
- toolName,
2778
- args,
2779
- output,
2780
- rawOutput: output,
2781
- timestamp,
2782
- tool_call_id: tc.id,
2783
- summarized: true,
2784
- originalTokenCount: responsePolicy.tokenCount,
2785
- classification: responsePolicy.classification,
2786
- retentionPolicy: responsePolicy.retentionPolicy,
2787
- summary: responsePolicy.summary,
2788
- archiveId: executionId,
2789
- status: "success"
2790
- });
2791
- }
2792
- let toolMessageContent = responsePolicy.content;
2793
- if (responsePolicy.retentionPolicy === "summarize_archive") {
2794
- toolMessageContent = `ARCHIVED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
2795
- Use get_tool_response with executionId "${executionId}" to retrieve the full output.`;
2796
- } else if (responsePolicy.retentionPolicy === "drop") {
2797
- toolMessageContent = `DROPPED_TOOL_RESPONSE [executionId=${executionId}]: ${responsePolicy.summary}
2798
- Use get_tool_response with executionId "${executionId}" to retrieve the full output.`;
2799
- }
2800
- appended.push({ role: "tool", content: toolMessageContent, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
2779
+ appended.push({ role: "tool", content: responsePolicy.content, tool_call_id: tc.id || `${tc.name}_${appended.length}`, name: tc.name });
2801
2780
  onEvent?.({ type: "tool_call", phase: "success", name: toolName, id: tc.id, args, result: output, durationMs });
2802
2781
  onProgress?.({ stage: "tools", message: `Tool ${tc.name} completed`, detail: { durationMs } });
2803
2782
  if (needsApproval && approvalEntry) {
@@ -2841,8 +2820,9 @@ Use get_tool_response with executionId "${executionId}" to retrieve the full out
2841
2820
  messageList,
2842
2821
  debug: {
2843
2822
  classification: responsePolicy.classification,
2844
- retentionPolicy: responsePolicy.retentionPolicy,
2845
- originalTokenCount: responsePolicy.tokenCount
2823
+ retentionPolicy: "keep_full",
2824
+ originalTokenCount: responsePolicy.tokenCount,
2825
+ truncated: responsePolicy.truncated
2846
2826
  }
2847
2827
  });
2848
2828
  toolCount += 1;
@@ -4203,24 +4183,8 @@ function extractCanonicalFacts(messages) {
4203
4183
  }
4204
4184
  return [...facts.values()];
4205
4185
  }
4206
- function flattenToolMessageContent(message) {
4207
- if (typeof message.content === "string") {
4208
- return message.content;
4209
- }
4210
- if (Array.isArray(message.content)) {
4211
- return message.content.map((part) => typeof part === "string" ? part : part?.text ?? part?.content ?? String(part ?? "")).join(" ");
4212
- }
4213
- return "";
4214
- }
4215
4186
  function isSummarizedToolPlaceholder(content) {
4216
- return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE"));
4217
- }
4218
- function summarizeToolMessagePreview(message) {
4219
- const preview = flattenToolMessageContent(message).trim();
4220
- if (!preview) {
4221
- return "No summary available.";
4222
- }
4223
- return preview.length > 240 ? `${preview.slice(0, 240)}...` : preview;
4187
+ return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE") || content.startsWith("ARCHIVED_TOOL_RESPONSE") || content.startsWith("STRUCTURED_TOOL_RESPONSE") || content.startsWith("DROPPED_TOOL_RESPONSE"));
4224
4188
  }
4225
4189
  function findToolHistoryEntry(state, toolCallId, toolName) {
4226
4190
  const entries = [
@@ -4246,29 +4210,6 @@ function findToolHistoryEntry(state, toolCallId, toolName) {
4246
4210
  }
4247
4211
  return void 0;
4248
4212
  }
4249
- function buildSummarizedToolMessage(message, state) {
4250
- const toolName = message.name || "unknown_tool";
4251
- const toolCallId = message.tool_call_id;
4252
- const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
4253
- const executionId = historyEntry?.executionId;
4254
- const summary = historyEntry?.summary || summarizeToolMessagePreview(message);
4255
- const references = [
4256
- `toolName=${toolName}`,
4257
- toolCallId ? `toolCallId=${toolCallId}` : null,
4258
- executionId ? `executionId=${executionId}` : null
4259
- ].filter(Boolean).join("; ");
4260
- let retrievalHint = "Use get_tool_response if exact details are still needed.";
4261
- if (executionId && toolCallId) {
4262
- retrievalHint = `Use get_tool_response with executionId "${executionId}" or tool call id "${toolCallId}" if exact details are still needed.`;
4263
- } else if (executionId || toolCallId) {
4264
- retrievalHint = `Use get_tool_response with executionId "${executionId || toolCallId}" if exact details are still needed.`;
4265
- }
4266
- return [
4267
- `SUMMARIZED_TOOL_RESPONSE [${references}]`,
4268
- `Summary: ${summary}`,
4269
- retrievalHint
4270
- ].join("\n");
4271
- }
4272
4213
  function mergeStableFacts(summary, additionalFacts) {
4273
4214
  if (additionalFacts.length === 0) return summary;
4274
4215
  const merged = new Map(summary.stable_facts.map((fact) => [fact.key, fact]));
@@ -4326,18 +4267,13 @@ function createContextSummarizeNode(opts) {
4326
4267
  const messages = state.messages || [];
4327
4268
  const onEvent = state.ctx?.__onEvent;
4328
4269
  const traceSession = state.ctx?.__traceSession;
4329
- const toolResponsesConfigEarly = resolved.toolResponses;
4330
4270
  const compressableMessages = messages.filter(
4331
4271
  (m) => {
4332
4272
  if (m.role !== "tool") return false;
4333
4273
  if (isSummarizedToolPlaceholder(m.content)) return false;
4334
4274
  if (isSyntheticSummaryMessage(m)) return false;
4335
- const histEntry = findToolHistoryEntry(state, m.tool_call_id, m.name);
4336
- if (histEntry?.retentionPolicy === "keep_full") return false;
4337
- if (!histEntry?.retentionPolicy) {
4338
- const byTool = toolResponsesConfigEarly.toolResponseRetentionByTool?.[m.name || ""];
4339
- if ((byTool || toolResponsesConfigEarly.defaultPolicy) === "keep_full") return false;
4340
- }
4275
+ const policy = resolveSummarizationRetention(m.name || "", resolved);
4276
+ if (policy === "keep_full") return false;
4341
4277
  return true;
4342
4278
  }
4343
4279
  );
@@ -4517,7 +4453,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4517
4453
  break;
4518
4454
  }
4519
4455
  }
4520
- const toolResponsesConfig = resolved.toolResponses;
4456
+ const archivedExecutions = [...state.toolHistoryArchived || []];
4457
+ const archivedIds = new Set(archivedExecutions.map((entry) => entry?.executionId).filter(Boolean));
4521
4458
  const newMessages = messages.map((m) => {
4522
4459
  if (m.role === "tool") {
4523
4460
  if (isSyntheticSummaryMessage(m)) {
@@ -4530,23 +4467,38 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4530
4467
  if (isSummarizedToolPlaceholder(m.content)) return m;
4531
4468
  if (toolCallId && protectedToolCallIds.has(toolCallId)) return m;
4532
4469
  const toolName = m.name || "";
4470
+ const policy = resolveSummarizationRetention(toolName, resolved);
4471
+ if (policy === "keep_full") return m;
4533
4472
  const historyEntry = findToolHistoryEntry(state, toolCallId, toolName);
4534
- const entryRetention = historyEntry?.retentionPolicy;
4535
- if (entryRetention === "keep_full") return m;
4536
- if (!entryRetention) {
4537
- const byTool = toolResponsesConfig.toolResponseRetentionByTool?.[toolName];
4538
- const configPolicy = byTool || toolResponsesConfig.defaultPolicy;
4539
- if (configPolicy === "keep_full") return m;
4473
+ const rawOutput = historyEntry?.rawOutput ?? historyEntry?.output ?? m.content;
4474
+ const executionId = historyEntry?.executionId;
4475
+ const prebuiltSummary = historyEntry?.summary || summarizeObject(rawOutput);
4476
+ if ((policy === "summarize_archive" || policy === "drop") && historyEntry && executionId && !archivedIds.has(executionId)) {
4477
+ archivedExecutions.push({
4478
+ ...historyEntry,
4479
+ summarized: true,
4480
+ retentionPolicy: policy,
4481
+ archiveId: executionId,
4482
+ summary: prebuiltSummary
4483
+ });
4484
+ archivedIds.add(executionId);
4540
4485
  }
4541
4486
  return {
4542
4487
  ...m,
4543
- content: buildSummarizedToolMessage(m, state)
4488
+ content: renderRetainedToolMessage({
4489
+ policy,
4490
+ rawOutput,
4491
+ toolName,
4492
+ toolCallId,
4493
+ executionId,
4494
+ prebuiltSummary
4495
+ })
4544
4496
  };
4545
4497
  }
4546
4498
  return m;
4547
4499
  }).filter((m) => m !== null);
4548
4500
  const actuallyCompressed = newMessages.filter(
4549
- (m) => m.role === "tool" && typeof m.content === "string" && m.content.startsWith("SUMMARIZED_TOOL_RESPONSE") && !messages.some((orig) => orig.tool_call_id === m.tool_call_id && isSummarizedToolPlaceholder(orig.content))
4501
+ (m) => m.role === "tool" && isSummarizedToolPlaceholder(m.content) && !messages.some((orig) => orig.tool_call_id === m.tool_call_id && isSummarizedToolPlaceholder(orig.content))
4550
4502
  );
4551
4503
  if (actuallyCompressed.length === 0) {
4552
4504
  return {};
@@ -4625,7 +4577,8 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
4625
4577
  return {
4626
4578
  messages: finalMessages,
4627
4579
  summaries,
4628
- summaryRecords
4580
+ summaryRecords,
4581
+ toolHistoryArchived: archivedExecutions
4629
4582
  };
4630
4583
  };
4631
4584
  }
@@ -4867,8 +4820,9 @@ function createContextTools(stateRef, opts) {
4867
4820
  }
4868
4821
  const getTool = createTool({
4869
4822
  name: "get_tool_response",
4870
- description: "RETRIEVE the full output of a tool execution whose response was archived, dropped, or later compacted in conversation history. When a tool response appears as 'ARCHIVED_TOOL_RESPONSE [executionId=xxx]', 'DROPPED_TOOL_RESPONSE [executionId=xxx]', or 'SUMMARIZED_TOOL_RESPONSE [...]', pass the referenced executionId to this tool to get the complete data. You can also pass the original tool_call_id from the tool call.",
4823
+ description: "RETRIEVE the full output of a tool execution whose response was archived, dropped, or later compacted in conversation history. Use this only when the preview or summary is missing a specific field, identifier, snippet, or exact payload you still need to finish the task. Do not call it reflexively for every archived response. When a tool response appears as 'ARCHIVED_TOOL_RESPONSE [executionId=xxx]', 'DROPPED_TOOL_RESPONSE [executionId=xxx]', or 'SUMMARIZED_TOOL_RESPONSE [...]', pass the referenced executionId to this tool to get the complete data. You can also pass the original tool_call_id from the tool call.",
4871
4824
  schema: zod.z.object({ executionId: zod.z.string().describe("Tool execution id or original tool_call_id") }),
4825
+ maxExecutionsPerRun: 8,
4872
4826
  func: async ({ executionId }) => {
4873
4827
  const matchesExecution = (t) => t?.executionId === executionId || t?.tool_call_id === executionId;
4874
4828
  let execution = stateRef.toolHistory?.find((t) => matchesExecution(t));