@memberjunction/ai-agents 6.2.0-edge.0 → 6.2.0-edge.2

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 (214) hide show
  1. package/README.md +43 -0
  2. package/dist/AgentDataPreloader.d.ts +4 -0
  3. package/dist/AgentDataPreloader.d.ts.map +1 -1
  4. package/dist/AgentDataPreloader.js +10 -2
  5. package/dist/AgentDataPreloader.js.map +1 -1
  6. package/dist/AgentDecisionService.d.ts +83 -0
  7. package/dist/AgentDecisionService.d.ts.map +1 -0
  8. package/dist/AgentDecisionService.js +155 -0
  9. package/dist/AgentDecisionService.js.map +1 -0
  10. package/dist/AgentRunner.d.ts +16 -4
  11. package/dist/AgentRunner.d.ts.map +1 -1
  12. package/dist/AgentRunner.js +55 -32
  13. package/dist/AgentRunner.js.map +1 -1
  14. package/dist/ArtifactToolManager.d.ts +4 -4
  15. package/dist/ArtifactToolManager.js +10 -10
  16. package/dist/ConversationToolManager.d.ts +16 -3
  17. package/dist/ConversationToolManager.d.ts.map +1 -1
  18. package/dist/ConversationToolManager.js +28 -5
  19. package/dist/ConversationToolManager.js.map +1 -1
  20. package/dist/KnowledgeAgent.d.ts.map +1 -1
  21. package/dist/KnowledgeAgent.js +6 -6
  22. package/dist/KnowledgeAgent.js.map +1 -1
  23. package/dist/PayloadChangeAnalyzer.d.ts +4 -0
  24. package/dist/PayloadChangeAnalyzer.d.ts.map +1 -1
  25. package/dist/PayloadChangeAnalyzer.js +10 -2
  26. package/dist/PayloadChangeAnalyzer.js.map +1 -1
  27. package/dist/PayloadFeedbackManager.d.ts +120 -13
  28. package/dist/PayloadFeedbackManager.d.ts.map +1 -1
  29. package/dist/PayloadFeedbackManager.js +244 -88
  30. package/dist/PayloadFeedbackManager.js.map +1 -1
  31. package/dist/PayloadManager.d.ts +27 -0
  32. package/dist/PayloadManager.d.ts.map +1 -1
  33. package/dist/PayloadManager.js +47 -15
  34. package/dist/PayloadManager.js.map +1 -1
  35. package/dist/agent-context-injector.d.ts +47 -3
  36. package/dist/agent-context-injector.d.ts.map +1 -1
  37. package/dist/agent-context-injector.js +77 -10
  38. package/dist/agent-context-injector.js.map +1 -1
  39. package/dist/agent-memory-context-builder.d.ts +13 -0
  40. package/dist/agent-memory-context-builder.d.ts.map +1 -1
  41. package/dist/agent-memory-context-builder.js +24 -5
  42. package/dist/agent-memory-context-builder.js.map +1 -1
  43. package/dist/agent-types/base-agent-type.d.ts +16 -0
  44. package/dist/agent-types/base-agent-type.d.ts.map +1 -1
  45. package/dist/agent-types/base-agent-type.js +20 -1
  46. package/dist/agent-types/base-agent-type.js.map +1 -1
  47. package/dist/agent-types/flow-agent-type.d.ts +106 -0
  48. package/dist/agent-types/flow-agent-type.d.ts.map +1 -1
  49. package/dist/agent-types/flow-agent-type.js +299 -29
  50. package/dist/agent-types/flow-agent-type.js.map +1 -1
  51. package/dist/agent-types/flow-graph-executor.d.ts +12 -1
  52. package/dist/agent-types/flow-graph-executor.d.ts.map +1 -1
  53. package/dist/agent-types/flow-graph-executor.js +25 -1
  54. package/dist/agent-types/flow-graph-executor.js.map +1 -1
  55. package/dist/agent-types/loop-agent-prompt-params.d.ts +258 -11
  56. package/dist/agent-types/loop-agent-prompt-params.d.ts.map +1 -1
  57. package/dist/agent-types/loop-agent-prompt-params.js +49 -2
  58. package/dist/agent-types/loop-agent-prompt-params.js.map +1 -1
  59. package/dist/agent-types/loop-agent-response-type.d.ts +12 -1
  60. package/dist/agent-types/loop-agent-response-type.d.ts.map +1 -1
  61. package/dist/agent-types/loop-agent-response-type.js.map +1 -1
  62. package/dist/agent-types/loop-agent-type.d.ts +6 -0
  63. package/dist/agent-types/loop-agent-type.d.ts.map +1 -1
  64. package/dist/agent-types/loop-agent-type.js +42 -3
  65. package/dist/agent-types/loop-agent-type.js.map +1 -1
  66. package/dist/artifact-target-plan.d.ts +2 -0
  67. package/dist/artifact-target-plan.d.ts.map +1 -1
  68. package/dist/artifact-target-plan.js +5 -1
  69. package/dist/artifact-target-plan.js.map +1 -1
  70. package/dist/base-agent.d.ts +886 -5
  71. package/dist/base-agent.d.ts.map +1 -1
  72. package/dist/base-agent.js +2567 -164
  73. package/dist/base-agent.js.map +1 -1
  74. package/dist/catalog-narrowing.d.ts +136 -0
  75. package/dist/catalog-narrowing.d.ts.map +1 -0
  76. package/dist/catalog-narrowing.js +212 -0
  77. package/dist/catalog-narrowing.js.map +1 -0
  78. package/dist/constants.d.ts +57 -0
  79. package/dist/constants.d.ts.map +1 -0
  80. package/dist/constants.js +70 -0
  81. package/dist/constants.js.map +1 -0
  82. package/dist/decision-discovery.d.ts +401 -0
  83. package/dist/decision-discovery.d.ts.map +1 -0
  84. package/dist/decision-discovery.js +511 -0
  85. package/dist/decision-discovery.js.map +1 -0
  86. package/dist/finish-if-mode-warnings.d.ts +39 -0
  87. package/dist/finish-if-mode-warnings.d.ts.map +1 -0
  88. package/dist/finish-if-mode-warnings.js +78 -0
  89. package/dist/finish-if-mode-warnings.js.map +1 -0
  90. package/dist/finish-if-state.d.ts +72 -0
  91. package/dist/finish-if-state.d.ts.map +1 -0
  92. package/dist/finish-if-state.js +109 -0
  93. package/dist/finish-if-state.js.map +1 -0
  94. package/dist/index.d.ts +9 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +10 -0
  97. package/dist/index.js.map +1 -1
  98. package/dist/memory-manager-agent.d.ts +119 -13
  99. package/dist/memory-manager-agent.d.ts.map +1 -1
  100. package/dist/memory-manager-agent.js +237 -74
  101. package/dist/memory-manager-agent.js.map +1 -1
  102. package/dist/memory-note-gate.d.ts +208 -0
  103. package/dist/memory-note-gate.d.ts.map +1 -0
  104. package/dist/memory-note-gate.js +294 -0
  105. package/dist/memory-note-gate.js.map +1 -0
  106. package/dist/native-tools/action-tool-builder.d.ts +8 -0
  107. package/dist/native-tools/action-tool-builder.d.ts.map +1 -1
  108. package/dist/native-tools/action-tool-builder.js +22 -6
  109. package/dist/native-tools/action-tool-builder.js.map +1 -1
  110. package/dist/native-tools/control-tools.d.ts +8 -0
  111. package/dist/native-tools/control-tools.d.ts.map +1 -1
  112. package/dist/native-tools/control-tools.js +25 -9
  113. package/dist/native-tools/control-tools.js.map +1 -1
  114. package/dist/native-tools/dual-channel.d.ts +2 -0
  115. package/dist/native-tools/dual-channel.d.ts.map +1 -1
  116. package/dist/native-tools/dual-channel.js +5 -1
  117. package/dist/native-tools/dual-channel.js.map +1 -1
  118. package/dist/native-tools/tool-result-turns.d.ts +9 -0
  119. package/dist/native-tools/tool-result-turns.d.ts.map +1 -1
  120. package/dist/native-tools/tool-result-turns.js +15 -3
  121. package/dist/native-tools/tool-result-turns.js.map +1 -1
  122. package/dist/pipeline/coerce.d.ts +14 -0
  123. package/dist/pipeline/coerce.d.ts.map +1 -1
  124. package/dist/pipeline/coerce.js +37 -9
  125. package/dist/pipeline/coerce.js.map +1 -1
  126. package/dist/pipeline/jsonpath-eval.d.ts +4 -0
  127. package/dist/pipeline/jsonpath-eval.d.ts.map +1 -1
  128. package/dist/pipeline/jsonpath-eval.js +10 -2
  129. package/dist/pipeline/jsonpath-eval.js.map +1 -1
  130. package/dist/pipeline/operators.js +16 -16
  131. package/dist/pipeline/path.d.ts +6 -0
  132. package/dist/pipeline/path.d.ts.map +1 -1
  133. package/dist/pipeline/path.js +17 -5
  134. package/dist/pipeline/path.js.map +1 -1
  135. package/dist/pipeline/pipeline-executor.js +10 -10
  136. package/dist/pipeline/predicate.d.ts +4 -0
  137. package/dist/pipeline/predicate.d.ts.map +1 -1
  138. package/dist/pipeline/predicate.js +15 -7
  139. package/dist/pipeline/predicate.js.map +1 -1
  140. package/dist/pipeline/providers/action-provider.js +2 -2
  141. package/dist/pipeline/providers/artifact-tool-provider.js +2 -2
  142. package/dist/pipeline/providers/serialize.d.ts +4 -0
  143. package/dist/pipeline/providers/serialize.d.ts.map +1 -1
  144. package/dist/pipeline/providers/serialize.js +10 -2
  145. package/dist/pipeline/providers/serialize.js.map +1 -1
  146. package/dist/pipeline/template.d.ts +4 -0
  147. package/dist/pipeline/template.d.ts.map +1 -1
  148. package/dist/pipeline/template.js +15 -7
  149. package/dist/pipeline/template.js.map +1 -1
  150. package/dist/realtime/agent-media-library.d.ts +10 -0
  151. package/dist/realtime/agent-media-library.d.ts.map +1 -1
  152. package/dist/realtime/agent-media-library.js +29 -9
  153. package/dist/realtime/agent-media-library.js.map +1 -1
  154. package/dist/realtime/bridge-realtime-session-factory.d.ts +5 -2
  155. package/dist/realtime/bridge-realtime-session-factory.d.ts.map +1 -1
  156. package/dist/realtime/bridge-realtime-session-factory.js +7 -4
  157. package/dist/realtime/bridge-realtime-session-factory.js.map +1 -1
  158. package/dist/realtime/bridge-room-transcript-sink.d.ts.map +1 -1
  159. package/dist/realtime/bridge-room-transcript-sink.js +15 -9
  160. package/dist/realtime/bridge-room-transcript-sink.js.map +1 -1
  161. package/dist/realtime/media-channel-server.js +2 -2
  162. package/dist/realtime/meeting-controls-state.d.ts +2 -0
  163. package/dist/realtime/meeting-controls-state.d.ts.map +1 -1
  164. package/dist/realtime/meeting-controls-state.js +6 -2
  165. package/dist/realtime/meeting-controls-state.js.map +1 -1
  166. package/dist/realtime/realtime-channel-server-data-context.d.ts +2 -0
  167. package/dist/realtime/realtime-channel-server-data-context.d.ts.map +1 -1
  168. package/dist/realtime/realtime-channel-server-data-context.js +5 -1
  169. package/dist/realtime/realtime-channel-server-data-context.js.map +1 -1
  170. package/dist/realtime/realtime-channel-server-host.js +2 -2
  171. package/dist/realtime/realtime-client-session-service.d.ts +58 -12
  172. package/dist/realtime/realtime-client-session-service.d.ts.map +1 -1
  173. package/dist/realtime/realtime-client-session-service.js +91 -31
  174. package/dist/realtime/realtime-client-session-service.js.map +1 -1
  175. package/dist/realtime/realtime-coagent-config.d.ts +2 -0
  176. package/dist/realtime/realtime-coagent-config.d.ts.map +1 -1
  177. package/dist/realtime/realtime-coagent-config.js +6 -2
  178. package/dist/realtime/realtime-coagent-config.js.map +1 -1
  179. package/dist/realtime/realtime-recording-store.d.ts +15 -0
  180. package/dist/realtime/realtime-recording-store.d.ts.map +1 -1
  181. package/dist/realtime/realtime-recording-store.js +31 -7
  182. package/dist/realtime/realtime-recording-store.js.map +1 -1
  183. package/dist/realtime/realtime-session-runner.d.ts +4 -4
  184. package/dist/realtime/realtime-session-runner.js +9 -9
  185. package/dist/realtime/realtime-session-runner.js.map +1 -1
  186. package/dist/realtime/realtime-vendor-resolution.d.ts +8 -3
  187. package/dist/realtime/realtime-vendor-resolution.d.ts.map +1 -1
  188. package/dist/realtime/realtime-vendor-resolution.js +3 -3
  189. package/dist/realtime/realtime-vendor-resolution.js.map +1 -1
  190. package/dist/rubric-evaluation-agent-runner.d.ts +2 -0
  191. package/dist/rubric-evaluation-agent-runner.d.ts.map +1 -0
  192. package/dist/rubric-evaluation-agent-runner.js +38 -0
  193. package/dist/rubric-evaluation-agent-runner.js.map +1 -0
  194. package/dist/runtime-state-fragment.d.ts +101 -0
  195. package/dist/runtime-state-fragment.d.ts.map +1 -0
  196. package/dist/runtime-state-fragment.js +173 -0
  197. package/dist/runtime-state-fragment.js.map +1 -0
  198. package/dist/self-check.d.ts +98 -0
  199. package/dist/self-check.d.ts.map +1 -0
  200. package/dist/self-check.js +74 -0
  201. package/dist/self-check.js.map +1 -0
  202. package/dist/types/payload-operations.d.ts +8 -0
  203. package/dist/types/payload-operations.d.ts.map +1 -1
  204. package/dist/types/payload-operations.js +21 -5
  205. package/dist/types/payload-operations.js.map +1 -1
  206. package/dist/utils/ConversationMessageResolver.d.ts +4 -0
  207. package/dist/utils/ConversationMessageResolver.d.ts.map +1 -1
  208. package/dist/utils/ConversationMessageResolver.js +10 -2
  209. package/dist/utils/ConversationMessageResolver.js.map +1 -1
  210. package/dist/volatile-child-prompt.d.ts +33 -0
  211. package/dist/volatile-child-prompt.d.ts.map +1 -0
  212. package/dist/volatile-child-prompt.js +76 -0
  213. package/dist/volatile-child-prompt.js.map +1 -0
  214. package/package.json +21 -18
@@ -10,24 +10,28 @@
10
10
  * @author MemberJunction.com
11
11
  * @since 2.49.0
12
12
  */
13
- import { MJAIAgentTypeEntity, MJTemplateParamEntity, MJAIAgentRelationshipEntity, MJAIAgentNoteEntity, MJAIAgentExampleEntity, MJAISkillEntity } from '@memberjunction/core-entities';
13
+ import { MJAIAgentTypeEntity, MJTemplateParamEntity, MJAIAgentRelationshipEntity, MJAIAgentNoteEntity, MJAIAgentExampleEntity, MJAISkillEntity, MJAIVendorEntity } from '@memberjunction/core-entities';
14
14
  import { type NativeToolBinding } from './native-tools/control-tools.js';
15
- import { MJAIAgentRunEntityExtended, MJAIAgentRunStepEntityExtended, MJAIPromptEntityExtended, MJAIAgentEntityExtended, MJAIPromptRunEntityExtended } from "@memberjunction/ai-core-plus";
15
+ import { MJAIAgentRunEntityExtended, MJAIAgentRunStepEntityExtended, MJAIPromptEntityExtended, MJAIAgentEntityExtended, MJAIModelEntityExtended, MJAIPromptRunEntityExtended } from "@memberjunction/ai-core-plus";
16
16
  import { UserInfo, IMetadataProvider } from '@memberjunction/core';
17
- import { ChatMessage, ChatMessageContent, BaseRealtimeModel, IRealtimeSession, ChatToolChoice } from '@memberjunction/ai';
17
+ import { AIDecisionRunResult } from '@memberjunction/ai-prompts';
18
+ import { ChatMessage, ChatMessageContent, BaseRealtimeModel, IRealtimeSession, ChatToolChoice, DecisionAnswer } from '@memberjunction/ai';
18
19
  import { BaseAgentType } from './agent-types/base-agent-type.js';
19
20
  import { type CodeLang } from '@memberjunction/context-crush/code';
20
21
  import { RealtimeSessionRunnerDeps } from './realtime/realtime-session-runner.js';
21
22
  import { RealtimeCoAgentConfig } from './realtime/realtime-coagent-config.js';
22
23
  import { AIEngine } from '@memberjunction/aiengine';
24
+ import { AgentMemoryObservability } from './agent-memory-context-builder.js';
23
25
  import { CompactionOutcome, EffectiveContextBudget } from './ConversationCompactionManager.js';
24
26
  import { ConversationToolCall, ConversationToolExecutionResult, ConversationToolSummaryHost } from './ConversationToolManager.js';
25
27
  import { CarryForwardStepRecord } from './tool-result-format.js';
26
28
  import { AgentPreExecutionRAGResult } from './agent-pre-execution-rag.js';
27
- import { AIPromptParams, AIPromptRunResult, ExecuteAgentParams, AgentConfiguration, ExecuteAgentResult, AgentAction, AgentSubAgentRequest, BaseAgentNextStep, MessageLifecycleEvent, AgentChatMessage, AgentChatMessageMetadata, AIModelSelectionInfo, ActionChange, ActionChangeScope, SubAgentChange, MediaOutput, FileOutputRef, SecondaryScopeConfig, SecondaryScopeValue, AgentResponseForm, AgentPipelineRequest, AgentSkillActivationRequest, AgentSkillInvocation, SkillAvailabilityPurpose } from '@memberjunction/ai-core-plus';
29
+ import { AIPromptParams, AIPromptRunResult, ExecuteAgentParams, AgentConfiguration, ExecuteAgentResult, AgentAction, AgentSubAgentRequest, BaseAgentNextStep, MessageLifecycleEvent, AgentChatMessage, AgentChatMessageMetadata, AIModelSelectionInfo, ActionChange, ActionChangeScope, SubAgentChange, MediaOutput, FileOutputRef, SecondaryScopeConfig, SecondaryScopeValue, AgentResponseForm, AgentPipelineRequest, AgentSkillActivationRequest, AgentSkillInvocation, SkillAvailabilityPurpose, AgentDecisionRequest, AgentDecisionResult, AgentDecisionAnswerSummary } from '@memberjunction/ai-core-plus';
28
30
  import { MJActionEntityExtended, ActionResult, ActionParam, AIDirective } from '@memberjunction/actions-base';
31
+ import { RuntimeStateDateTime, RuntimeStateScratchpad } from './runtime-state-fragment.js';
29
32
  import { ArtifactToolCall, StoredToolResult } from './ArtifactToolManager.js';
30
33
  import { MemoryWriteRequest, MemoryWriteResult } from './MemoryWriteManager.js';
34
+ import { AgentDecisionService } from './AgentDecisionService.js';
31
35
  import { PipelineToolRegistry, PipelineExecutionResult } from './pipeline/index.js';
32
36
  /**
33
37
  * Compact representation of a single action's execution result, used for
@@ -40,6 +44,8 @@ interface ActionResultSummary {
40
44
  resultCode: string;
41
45
  message: string;
42
46
  aiDirectives?: AIDirective[];
47
+ /** Set when the circuit breaker blocked the call without dispatching it. */
48
+ breakerReason?: ActionCircuitBreakerReason;
43
49
  }
44
50
  /**
45
51
  * Resolved per-run configuration for structurally compressing inline action-result
@@ -58,6 +64,47 @@ export interface ActionResultCrushConfig {
58
64
  */
59
65
  codeLang: CodeLang | undefined;
60
66
  }
67
+ /**
68
+ * Options for {@link BaseAgent.ExecuteSingleAction}.
69
+ */
70
+ export interface ExecuteSingleActionOptions {
71
+ /**
72
+ * When true, the run-scoped action circuit breaker is bypassed for this call: none of the
73
+ * pre-execution checks (fatal lockout, identical-arguments rule, consecutive-attempt budget)
74
+ * apply, and the outcome neither increments nor resets the failure history.
75
+ *
76
+ * Set by the pipeline registry and by the ForEach / While iteration paths. Those callers do
77
+ * their own per-element failure accounting and expect elements to be independent, and there
78
+ * is no model in the loop to act on the breaker's guidance, so counting those calls would let
79
+ * a run of bad elements block the rest of the batch and then block the model's next direct
80
+ * call too.
81
+ */
82
+ skipCircuitBreaker?: boolean;
83
+ }
84
+ /**
85
+ * Which circuit-breaker rule blocked an action call without dispatching it.
86
+ *
87
+ * - `'fatal'` — the action failed earlier in the run with a configuration or credential error and is
88
+ * locked out for the rest of the run.
89
+ * - `'identical-arguments'` — the action already failed {@link IDENTICAL_FAILURE_THRESHOLD} times
90
+ * with these exact arguments.
91
+ * - `'attempts-exhausted'` — the action has failed {@link ACTION_FAILURE_BUDGET} consecutive times
92
+ * across any arguments.
93
+ */
94
+ export type ActionCircuitBreakerReason = 'fatal' | 'identical-arguments' | 'attempts-exhausted';
95
+ /** Identical-arguments rule: this many failures with the same arguments block further identical calls. */
96
+ export declare const IDENTICAL_FAILURE_THRESHOLD = 2;
97
+ /** Attempt budget: this many consecutive failures, across any arguments, disable the action for the run. */
98
+ export declare const ACTION_FAILURE_BUDGET = 5;
99
+ /**
100
+ * The {@link ActionResult} returned when the run-scoped circuit breaker blocks a call before it
101
+ * reaches the action engine. Carries the rule that fired so the failure directive can name it
102
+ * directly instead of re-deriving it from the failure history, which a blocked call never updates.
103
+ */
104
+ export declare class CircuitBreakerActionResult extends ActionResult {
105
+ readonly Reason: ActionCircuitBreakerReason;
106
+ constructor(Reason: ActionCircuitBreakerReason);
107
+ }
61
108
  /**
62
109
  * The agent-invariant "base" catalog cached (process-wide) on AIEngine and reused across runs/steps.
63
110
  * Holds the resolved sub-agents + actions and their formatted markdown, plus the base merged
@@ -79,6 +126,12 @@ interface AgentBaseCatalog {
79
126
  /** Agent-type prompt params merged from schema defaults + agent config (NO runtime overrides). */
80
127
  baseAgentTypePromptParams: Record<string, unknown>;
81
128
  }
129
+ /**
130
+ * Turns one decision call's typed answers into what its reader gets. A loop turn's model reads
131
+ * `AgentDecisionService.SummarizeAnswers`; an agent type that routes on the answers reads
132
+ * `SummarizeDecisionAnswers`, which keeps each distribution.
133
+ */
134
+ type DecisionAnswerSummarizer = (answers: Record<string, DecisionAnswer>) => Record<string, AgentDecisionAnswerSummary>;
82
135
  export declare class BaseAgent {
83
136
  /**
84
137
  * Maximum allowed validation retries before forcing failure.
@@ -148,6 +201,138 @@ export declare class BaseAgent {
148
201
  * @private
149
202
  */
150
203
  private _lastModelSelectionInfo;
204
+ /**
205
+ * The volatile runtime state message generated for the most recent prompt execution.
206
+ * When append-only trailing state mode is used (e.g. OpenAI prompt caching), this fragment
207
+ * is retained in conversation history across turns to preserve a byte-exact prompt prefix.
208
+ * @private
209
+ */
210
+ private _lastVolatileStateMessage;
211
+ /**
212
+ * The trailing-state retention mode once it has been decided for this run, frozen at the first
213
+ * model selection so the layout never flips again mid-run. Undefined until then (turn 1 only).
214
+ * @private
215
+ */
216
+ private _resolvedTrailingStateMode;
217
+ /**
218
+ * Index in conversationMessages where this agent run began, used to accurately restore
219
+ * turn 1's trailing state message in append-only mode without corrupting prior chat turns.
220
+ * @private
221
+ */
222
+ private _turn1InsertionIndex;
223
+ /**
224
+ * Actions that have failed fatally (e.g., missing API key, unauthorized, or repeated unrecoverable errors)
225
+ * during the current agent run. Subsequent attempts to execute these actions are short-circuited in 0ms.
226
+ * @private
227
+ */
228
+ private _fatalActionFailures;
229
+ /**
230
+ * Parameter-aware failure tracking per action name for the current agent run.
231
+ * Differentiates identical retries (which trip quickly) from parameter modifications (which allow self-correction).
232
+ * @private
233
+ */
234
+ private _actionFailureHistory;
235
+ /**
236
+ * The identity of one action call's arguments, for the circuit breaker's identical-arguments
237
+ * rule: two calls with the same normalized string are "the same call", whatever order the model
238
+ * wrote the keys in.
239
+ *
240
+ * Algorithm, top to bottom:
241
+ * 1. Null, undefined or a non-object yields `''` (a call with no arguments).
242
+ * 2. The top-level keys are sorted, and each `(key, value)` pair passes through
243
+ * {@link normalizeActionParamEntry}, which may rename it, rewrite its value, or drop it.
244
+ * 3. Every value passes through {@link normalizeActionParamValue}: plain objects are rebuilt with
245
+ * sorted keys at EVERY depth, arrays keep their order but normalize each element, and
246
+ * anything else (strings, numbers, booleans, null, Dates, entity instances) is kept as is.
247
+ * 4. The result is serialized with `JSON.stringify`. Should that throw (a circular reference,
248
+ * a BigInt), the fallback is a sorted list of the top-level keys — still deterministic, still
249
+ * distinguishes differently-shaped calls, and never throws.
250
+ *
251
+ * Three protected layers so a subclass can change one part without re-implementing the rest:
252
+ * override {@link normalizeActionParamEntry} to ignore a key (a trace id, a timestamp the model
253
+ * regenerates on every call), or {@link normalizeActionParamValue} to canonicalize values
254
+ * (case-fold a search query, trim whitespace) so near-identical retries count as identical.
255
+ */
256
+ protected normalizeActionParams(params: Record<string, unknown> | null | undefined): string;
257
+ /**
258
+ * Normalizes one top-level `(key, value)` pair of an action's arguments. The default keeps the
259
+ * key and normalizes the value through {@link normalizeActionParamValue}. Return `null` to drop
260
+ * the pair from the call's identity — the seam for ignoring arguments that legitimately differ
261
+ * between otherwise identical retries.
262
+ */
263
+ protected normalizeActionParamEntry(key: string, value: unknown): {
264
+ key: string;
265
+ value: unknown;
266
+ } | null;
267
+ /**
268
+ * Normalizes one value, recursively: a plain object is rebuilt with its keys sorted, an array
269
+ * keeps its order with each element normalized, and any other value is returned unchanged. The
270
+ * seam for canonicalizing values before they are compared.
271
+ *
272
+ * "Plain" here is by prototype (`Object.prototype` or none), not the structural
273
+ * `IsPlainObject` from `@memberjunction/global`: a Date, Map or entity instance must pass through
274
+ * as an opaque leaf and serialize as itself, not be rebuilt as an empty bag of sorted keys.
275
+ */
276
+ protected normalizeActionParamValue(value: unknown): unknown;
277
+ /**
278
+ * Detects whether an action error message represents a fatal configuration or credential
279
+ * problem: the tool cannot work in this environment no matter what arguments it is given,
280
+ * so retrying is pointless and the action is locked out for the rest of the run.
281
+ *
282
+ * Deliberately NOT fatal: HTTP 401/403, "unauthorized" and "forbidden". Those are usually
283
+ * per-resource (one site blocking a fetch, one record the user cannot read) or transient
284
+ * (a search provider using 403 as a rate limit), so they fall through to the parameter-aware
285
+ * failure history where the identical-arguments rule and the consecutive-attempt budget
286
+ * bound them without disabling the tool for every other resource.
287
+ *
288
+ * Also NOT fatal, for the same reason: a failure the model can fix by changing its arguments.
289
+ * A message that names a parameter is treated as an argument problem whatever else it says,
290
+ * and a call that itself carried credential-shaped arguments (password, API key, token) is
291
+ * never fatal even on "authentication failed", because the credential came from the model,
292
+ * not the environment. Demoting a message from fatal costs at most the attempt budget.
293
+ *
294
+ * @param message The action's failure message.
295
+ * @param actionParams The arguments the call was made with, when known.
296
+ */
297
+ protected isFatalActionError(message: string | null | undefined, actionParams?: Record<string, unknown> | null): boolean;
298
+ /**
299
+ * True when any top-level argument name looks like a credential the model supplied itself
300
+ * (password, secret, credential, API key, or an access / auth / bearer / refresh / ID token).
301
+ * `maxTokens`-style names are deliberately not matched.
302
+ */
303
+ protected hasCredentialShapedArguments(actionParams?: Record<string, unknown> | null): boolean;
304
+ /**
305
+ * Records a non-successful outcome for the run-scoped action circuit breaker. A fatal
306
+ * configuration error locks the action out for the rest of the run; any other failure
307
+ * updates the parameter-aware history behind the identical-arguments rule and the
308
+ * consecutive-attempt budget.
309
+ */
310
+ protected recordActionFailure(action: AgentAction, actionEntity: MJActionEntityExtended | undefined, message: string | null | undefined, normalizedParams: string): void;
311
+ /**
312
+ * Clears the parameter-aware failure history for an action after it succeeds, so the
313
+ * identical-arguments rule and the consecutive-attempt budget start over.
314
+ */
315
+ protected clearActionFailureRecord(action: AgentAction, actionEntity: MJActionEntityExtended | undefined): void;
316
+ /**
317
+ * Applies the three circuit-breaker rules to a call that is about to be dispatched. Returns a
318
+ * blocked result, with the rule that fired, when the call must not go to the action engine;
319
+ * null when it may proceed. Rules are checked fatal → identical-arguments → budget.
320
+ */
321
+ protected checkActionCircuitBreaker(params: ExecuteAgentParams, action: AgentAction, actionEntity: MJActionEntityExtended, normalizedParams: string): CircuitBreakerActionResult | null;
322
+ /** The failed {@link ActionResult} a blocked call returns in place of dispatching. */
323
+ protected buildBlockedActionResult(actionEntity: MJActionEntityExtended, reason: ActionCircuitBreakerReason, message: string): CircuitBreakerActionResult;
324
+ /**
325
+ * Names the rule behind a failed action summary so the directive matches what actually
326
+ * happened. A blocked call reports the rule that blocked it. A dispatched failure is fatal if
327
+ * `recordActionFailure` locked the action out (the summary has no access to the call's
328
+ * arguments, so the decision is read back rather than re-derived from the message); otherwise
329
+ * the budget is checked BEFORE the identical-arguments rule, because once the budget is spent
330
+ * the action is blocked whatever the arguments are, and telling the model to change them
331
+ * would send it in circles.
332
+ */
333
+ protected classifyActionFailure(summary: ActionResultSummary): ActionCircuitBreakerReason | 'warning';
334
+ /** The guidance line appended to the history for one failed action. */
335
+ protected formatActionFailureDirective(summary: ActionResultSummary): string;
151
336
  /**
152
337
  * Returns the active metadata provider for this agent run. Subclasses MUST
153
338
  * use this getter (rather than `new Metadata()` or `Metadata.Provider`) so
@@ -300,6 +485,8 @@ export declare class BaseAgent {
300
485
  * }]);
301
486
  * ```
302
487
  */
488
+ PromoteMediaOutputs(mediaOutputs: MediaOutput[]): void;
489
+ /** @deprecated Use {@link PromoteMediaOutputs}. */
303
490
  promoteMediaOutputs(mediaOutputs: MediaOutput[]): void;
304
491
  /**
305
492
  * Gets the currently accumulated media outputs for this agent run.
@@ -471,6 +658,10 @@ export declare class BaseAgent {
471
658
  * Allows agents to explore input artifacts on demand.
472
659
  */
473
660
  private _artifactToolManager;
661
+ /**
662
+ * Service for evaluating agent decisions inline via fast decision models.
663
+ */
664
+ protected _agentDecisionService: AgentDecisionService;
474
665
  /**
475
666
  * Reverse map from sanitized tool name back to Action, for the turn currently being prepared.
476
667
  *
@@ -507,6 +698,41 @@ export declare class BaseAgent {
507
698
  * @private
508
699
  */
509
700
  private _effectiveSubAgents;
701
+ /**
702
+ * The merged agent-type prompt params of the current step. Populated during
703
+ * gatherPromptTemplateData() and read by the finishIf gate, which runs in executeActionsStep()
704
+ * and executeNextStep() after the prompt that requested the step.
705
+ * @private
706
+ */
707
+ private _agentTypePromptParams;
708
+ /**
709
+ * The run's catalog narrowing (plan Task 3.7): what the prompt hides from its action, sub-agent
710
+ * and skill lists. Computed once, on the run's first prompt, and reused by every later step, so
711
+ * the catalog the model sees never changes mid-run. `undefined` until then; hides nothing when
712
+ * narrowing is off or failed open.
713
+ * @private
714
+ */
715
+ private _catalogNarrowing;
716
+ /**
717
+ * The request that opened the run: the last user message when it started, before the framework
718
+ * added anything. Catalog narrowing judges the catalog against it.
719
+ * @private
720
+ */
721
+ private _openingRequest;
722
+ /**
723
+ * Whether the run answers its conversation's opening request ({@link IsOpeningTurn}), read from
724
+ * the messages it started with. Decision discovery asks about no other turn.
725
+ * @private
726
+ */
727
+ private _isOpeningTurn;
728
+ /** The longest the catalog narrowing decision may take before the run shows the full catalog. */
729
+ private static readonly CATALOG_NARROWING_TIMEOUT_MS;
730
+ /**
731
+ * Decision requests held back by the prompt that made them, because the step that carried them
732
+ * can end the run. They run before the next prompt, or are skipped when the run ends first.
733
+ * @private
734
+ */
735
+ private _heldDecisions;
510
736
  /**
511
737
  * IDs of skills already activated during this run. Prevents re-activation from re-appending
512
738
  * the same instructions to context / re-pushing duplicate actionChanges/subAgentChanges entries
@@ -1143,6 +1369,16 @@ export declare class BaseAgent {
1143
1369
  * @returns A human-readable scope label
1144
1370
  */
1145
1371
  private determineNoteScope;
1372
+ /**
1373
+ * The observability context memory injection runs under for an agent run: the run's ID, the next
1374
+ * step number, and a callback that adds each rerank step to the run's steps. A rerank step carries
1375
+ * the rerank's prompt run, whose cost and token rollups include a prompt-backed reranker's own
1376
+ * prompt runs, so the run's totals and its `MaxCostPerRun` / `MaxTokensPerRun` guardrails count
1377
+ * them. Undefined when there is no run.
1378
+ *
1379
+ * @param run - The current agent run, or null before one exists
1380
+ */
1381
+ protected MemoryObservability(run: MJAIAgentRunEntityExtended | null): AgentMemoryObservability | undefined;
1146
1382
  /**
1147
1383
  * Inject notes and examples into agent context memory.
1148
1384
  * Called automatically before agent execution if injection is enabled on the agent.
@@ -1200,6 +1436,98 @@ export declare class BaseAgent {
1200
1436
  * @returns The structured RAG result, or `null` if no scopes produced results.
1201
1437
  */
1202
1438
  protected InjectPreExecutionRAG(lastUserMessage: string, agent: MJAIAgentEntityExtended, contextUser: UserInfo | undefined, conversationMessages: ChatMessage[] | undefined, originalMessages: ChatMessage[] | undefined, primaryScopeEntityId?: string, primaryScopeRecordId?: string, secondaryScopes?: Record<string, SecondaryScopeValue>, payload?: unknown): Promise<AgentPreExecutionRAGResult | null>;
1439
+ /**
1440
+ * Decision discovery (plan Task 3.1): suggests the agent to delegate to before the first prompt.
1441
+ *
1442
+ * Runs in parallel with the rest of Phase 2 of `Execute()`, and only when the merged agent-type
1443
+ * prompt params set `decisionsEnabled: true` (the master switch, {@link DecisionsEnabled}) and
1444
+ * `decisionDiscovery: true`, the run answers its conversation's opening request
1445
+ * ({@link IsOpeningTurn}), and that request @mentions no agent. A follow-up turn is never asked
1446
+ * about: it may be continuing work with an agent already engaged, and a suggestion must not pull
1447
+ * the agent away from it. One decision asks which of the agents the user may run (and the host
1448
+ * allows) should handle the request, and whether a specialist should. When both answers are
1449
+ * confident, a `<suggested_agent>` system message is unshifted onto `conversationMessages`, the
1450
+ * way pre-execution RAG adds `<retrieved_context>`. Each discovery is recorded as one
1451
+ * `Agent discovery` Decision step.
1452
+ *
1453
+ * Fails safe: an error, a timeout, a cancelled run, an unusable answer or an unsure one adds
1454
+ * nothing, so the agent behaves as it would without discovery. So do fewer than
1455
+ * {@link DECISION_DISCOVERY_MIN_OPTIONS} options. Never delays the first prompt by more than
1456
+ * {@link DECISION_DISCOVERY_TIMEOUT_MS}, and never throws.
1457
+ *
1458
+ * The any-applies question does not name the options, so the decision cannot say that none of
1459
+ * them fits: see {@link DECISION_DISCOVERY_APPLIES_INSTRUCTIONS} for why it stays that way for now.
1460
+ *
1461
+ * @param agent - The agent being executed.
1462
+ * @param contextUser - The user whose run permission decides the options.
1463
+ * @param conversationMessages - The mutated message array that flows to the LLM (the suggestion is unshifted here).
1464
+ * @param data - The run's `ExecuteAgentParams.data`. Its `__agentTypePromptParams` overrides the agent's prompt
1465
+ * params, and its `ALL_AVAILABLE_AGENTS`, when an array, is the host's allow-list: no other agent is suggested.
1466
+ */
1467
+ protected InjectDecisionDiscovery(agent: MJAIAgentEntityExtended, contextUser: UserInfo | undefined, conversationMessages: ChatMessage[] | undefined, data: Record<string, unknown> | undefined): Promise<void>;
1468
+ /**
1469
+ * Whether discovery is on for this run: the master switch ({@link DecisionsEnabled}) and
1470
+ * `decisionDiscovery` are both on. Read without rebuilding the merged prompt params, since it is
1471
+ * asked on every run of every agent: each setting from the per-run override when it sets one,
1472
+ * otherwise from the agent's base params, cached on AIEngine with its base catalog. Only a cold
1473
+ * cache builds them.
1474
+ */
1475
+ private isDecisionDiscoveryOnFor;
1476
+ /**
1477
+ * The run's merged agent-type prompt params (schema defaults < agent < per-run overrides), once
1478
+ * discovery is on: the cached base params when there is no override, otherwise built.
1479
+ */
1480
+ private decisionDiscoveryPromptParams;
1481
+ /** The agent's base prompt params (no per-run overrides), from the base catalog AIEngine caches, when it holds one. */
1482
+ private cachedBasePromptParams;
1483
+ /** Builds the merged prompt params, as `gatherPromptTemplateData` does. */
1484
+ private buildDecisionDiscoveryPromptParams;
1485
+ /**
1486
+ * Records one `Agent discovery` step around a bounded discovery, and returns what it found. A
1487
+ * failed discovery is logged as a warning; an unsure one only in verbose logs, except that an
1488
+ * answer from a model with no discovery calibration is warned about once per model, because
1489
+ * then discovery can never suggest anything.
1490
+ */
1491
+ private runDecisionDiscovery;
1492
+ /** The answering models already warned about as having no discovery calibration, so each is warned about once per process. */
1493
+ private static readonly _uncalibratedDiscoveryModelsWarned;
1494
+ /**
1495
+ * Warns, once per model, that discovery answered by a model with no discovery calibration
1496
+ * suggests nothing. That happens when a decision model is added or renamed, when a vendor model
1497
+ * moves to another version (Jev's `APIName`), or when LLM Decision answers through a chat model
1498
+ * other than the one its calibration was fitted on; without the warning the only trace is each
1499
+ * `Agent discovery` step's reason.
1500
+ */
1501
+ private static warnUncalibratedDiscoveryModel;
1502
+ /**
1503
+ * Runs `discover` until it finishes, {@link DECISION_DISCOVERY_TIMEOUT_MS} passes, or the run is
1504
+ * cancelled. A timeout or a cancellation aborts the signal `discover` was given, which aborts the
1505
+ * decision call, and returns a failed discovery at once. What `discover` returns after that
1506
+ * suggests nothing, but the prompt run of its decision call is still linked to `step` once it
1507
+ * settles ({@link linkLateDecisionPromptRun}), so the run counts the call's cost.
1508
+ */
1509
+ private boundDecisionDiscovery;
1510
+ /**
1511
+ * The discovery itself: the options, rebuilt from the permitted catalog, then one decision about
1512
+ * the opening request, and what its answer means. Never throws.
1513
+ */
1514
+ private discoverAgent;
1515
+ /**
1516
+ * The Choice's options, rebuilt on every call and never cached ({@link BuildDecisionDiscoveryOptionSet}):
1517
+ * from AIEngine's current catalog, the agents the user may run, the decision prompt's option cap,
1518
+ * and the semantic search over the opening request when the provider can run it.
1519
+ */
1520
+ private decisionDiscoveryOptionSet;
1521
+ /** Opens the `Agent discovery` Decision step. Without a run there is no step. */
1522
+ private startDecisionDiscoveryStep;
1523
+ /**
1524
+ * Finalizes the `Agent discovery` step: the answer, whether it was injected, the host allow-list,
1525
+ * the agents left out for having no description (at most {@link DECISION_DISCOVERY_MAX_RECORDED_IDS}
1526
+ * IDs), any narrowing, and the call's usage.
1527
+ */
1528
+ private finishDecisionDiscoveryStep;
1529
+ /** Logs that decision discovery failed, so nothing was suggested. */
1530
+ private warnDecisionDiscovery;
1203
1531
  /**
1204
1532
  * Converts UI markup (@{...} syntax) in user messages to plain text.
1205
1533
  * This prevents agents from being confused by UI-specific JSON syntax and reduces token usage.
@@ -1384,6 +1712,151 @@ export declare class BaseAgent {
1384
1712
  */
1385
1713
  protected isFinalPermittedIteration(params: ExecuteAgentParams): boolean;
1386
1714
  protected preparePromptParams<P>(config: AgentConfiguration, payload: P, params: ExecuteAgentParams): Promise<AIPromptParams>;
1715
+ /**
1716
+ * In append-only mode, restores turn 1's volatile state fragment if mode resolution
1717
+ * was deferred until after turn 1 (e.g. dynamic model selection).
1718
+ *
1719
+ * Restores the fragment at the exact message boundary where turn 1 executed, ensuring
1720
+ * earlier turns in multi-turn conversations are not corrupted.
1721
+ *
1722
+ * This is only correct for a replace → append-only flip between turn 1 and turn 2, when
1723
+ * `_lastVolatileStateMessage` still holds turn 1's fragment. `shouldUseAppendOnlyTrailingState`
1724
+ * freezes the mode at the first model selection precisely so that no later flip can occur.
1725
+ */
1726
+ protected restoreTurn1VolatileStateIfNeeded(params: ExecuteAgentParams, isAppendOnly: boolean): void;
1727
+ /**
1728
+ * Whether THIS run has already placed a volatile-state fragment in the history, i.e. at or after
1729
+ * the turn-1 boundary. Fragments before the boundary belong to an earlier run whose history the
1730
+ * caller reused; they must not suppress this run's turn-1 restore.
1731
+ */
1732
+ protected runHasVolatileStateMessage(params: ExecuteAgentParams): boolean;
1733
+ /**
1734
+ * The message array sent for ONE request under `'trailingMessage'` placement: a copy of the history
1735
+ * with every non-system message's fragment tag literals escaped, then the real fragment last.
1736
+ *
1737
+ * Escaping at send time (rather than where text enters the history) covers every source at once —
1738
+ * user turns, action results, sub-agent results, skill activations — without rewriting stored data,
1739
+ * and it is deterministic, so the cached prefix stays byte-stable across iterations. System messages
1740
+ * and framework-authored volatile state messages are left alone.
1741
+ */
1742
+ protected assembleOutgoingMessages(history: ChatMessage[], fragment: AgentChatMessage, isAppendOnly?: boolean): ChatMessage[];
1743
+ /**
1744
+ * Determines whether the current prompt execution should use append-only trailing state retention.
1745
+ *
1746
+ * Why: OpenAI and xAI prompt caching operate on an exact byte prefix match from token 0. Replacing the
1747
+ * trailing runtime-state fragment turn-over-turn breaks the byte prefix after the system prompt,
1748
+ * dropping cache hit rates significantly. In append-only mode, prior runtime state messages are
1749
+ * retained in the message history so each turn is an exact prefix extension of the prior turn,
1750
+ * achieving ~93% cache hit rate. Providers with block-level or sliding caching (Gemini, Cerebras)
1751
+ * use replace-in-place to keep context compact.
1752
+ *
1753
+ * Which providers are which is METADATA, not code: the `PrefixPromptCache` flag in the model
1754
+ * catalog's `ModelConfiguration` cascade (Model Types < Models < Vendors' `Configuration.ModelDefaults`
1755
+ * < Model Vendors), read through {@link resolvePrefixPromptCache}. `true` means append-only;
1756
+ * anything else means replace.
1757
+ *
1758
+ * Decided ONCE per run. An explicit `trailingStateMode` or a runtime model override answers
1759
+ * immediately. Otherwise the answer is frozen at the first model selection and reused for every
1760
+ * later turn, so a failover to another vendor cannot flip the layout mid-run — a flip after turn 2
1761
+ * would leave stale fragments in the history or, worse, restore the wrong turn's fragment. On turn 1,
1762
+ * before any selection is known, the answer is replace-in-place: turn 1's fragment is kept and, if
1763
+ * turn 2 resolves to append-only, spliced back at the turn-1 boundary, which reproduces exactly the
1764
+ * bytes an append-only turn 1 would have sent. Nothing is lost by deferring, so the prompt's bound
1765
+ * models are deliberately NOT consulted — prompts commonly bind several vendors for failover, and
1766
+ * guessing from them mis-pins runs that end up selecting another vendor.
1767
+ */
1768
+ protected shouldUseAppendOnlyTrailingState(promptParams: AIPromptParams): boolean;
1769
+ /**
1770
+ * Whether a model, as served by a vendor, sits behind a byte-prefix prompt cache
1771
+ * (`LLM.PrefixPromptCache`), read from the model catalog's `ModelConfiguration` cascade —
1772
+ * `AIModelType < AIModel < AIVendor.Configuration.ModelDefaults < AIModelVendor` — via
1773
+ * `AIEngine.GetEffectiveModelConfiguration`. The most specific layer is the INFERENCE-PROVIDER
1774
+ * model-vendor row for `vendor`, whose vendor row supplies the host-wide default that beats the
1775
+ * model's own bag; when the vendor is unknown, or has no inference row for this model, the model
1776
+ * and type layers still answer. False when no layer declares it, which callers
1777
+ * treat as a block cache (replace-in-place).
1778
+ *
1779
+ * Extension point: a subclass with out-of-catalog knowledge (an OpenAI-compatible gateway whose
1780
+ * rows carry no flag, say) can override this rather than the mode decision above.
1781
+ */
1782
+ protected resolvePrefixPromptCache(model: MJAIModelEntityExtended | undefined, vendor: MJAIVendorEntity | undefined): boolean;
1783
+ /**
1784
+ * Builds the framework-authored `user` message that carries the loop agent's volatile state as the
1785
+ * final message of the request; returns null only when every block is turned off, or when the
1786
+ * system prompt template in this database has not yet synced and still embeds the state itself
1787
+ * (see the guard below). The blocks mirror the sections the template used to render (see
1788
+ * {@link RuntimeStateFragmentBuilder}), and each honors the same include flag the template did.
1789
+ *
1790
+ * Why this exists: provider prompt caching is a prefix match over tools → system → messages, so
1791
+ * state that changes every iteration INSIDE the system prompt invalidates the entire history each
1792
+ * call. Measured on Sage: 36% → 83% cached on Gemini 2.5 Flash, 12% → 96% on Claude Opus 5 (with the
1793
+ * Anthropic adapter placing its breakpoint before this message), output quality unchanged.
1794
+ *
1795
+ * The message carries STATE only — never rules. It is marked `metadata.volatileState` so adapters
1796
+ * can recognize it without depending on this package's tag names.
1797
+ */
1798
+ protected buildVolatileStateMessage<P>(params: ExecuteAgentParams, promptParams: AIPromptParams, payload: P, childPrompt: MJAIPromptEntityExtended | undefined, agentType: MJAIAgentTypeEntity, systemPrompt?: MJAIPromptEntityExtended): Promise<AgentChatMessage | null>;
1799
+ /**
1800
+ * Decides whether this run's specialization (child prompt) rides in the trailing message, and if so
1801
+ * pre-renders it and flags the template to render a stub in its place. Decided from the child
1802
+ * template's UNRENDERED text via {@link ResolveSpecializationPlacement}, so the answer is the same on
1803
+ * every iteration and the layout never flips mid-run. Returns the rendered specialization, or null
1804
+ * when it stays in the system prompt.
1805
+ */
1806
+ protected resolveRelocatedSpecialization(promptParams: AIPromptParams, childPrompt: MJAIPromptEntityExtended | undefined, agentType: MJAIAgentTypeEntity, contextUser: UserInfo): Promise<string | null>;
1807
+ /**
1808
+ * Decides, from the system prompt's UNRENDERED template text, whether the trailing runtime-state
1809
+ * fragment belongs on this request:
1810
+ *
1811
+ * - `'trailing'` — the template carries the `<mj-runtime-state>` pointer, so the model is told where
1812
+ * the state lives. The Loop agent system prompt.
1813
+ * - `'embedded'` — the template still renders the state blocks itself (an environment whose
1814
+ * TemplateContent has not synced the new Loop template, or the Flow template, which embeds the
1815
+ * payload). Emitting the fragment would deliver the same state twice.
1816
+ * - `'unsupported'` — the template has neither. The Harness system prompt, or a custom prompt run
1817
+ * without the Loop system prompt. The model would receive an unexplained block.
1818
+ * - `'unknown'` — no template text to inspect (no TemplateID, or the lookup failed). The caller
1819
+ * fails OPEN here: a Loop agent losing its payload from the model's view is far worse than a
1820
+ * non-Loop agent receiving an unexplained fragment, and in practice every agent type's system
1821
+ * prompt has a template, so this arises only from a lookup failure.
1822
+ */
1823
+ protected resolveRuntimeStateDelivery(systemPrompt: MJAIPromptEntityExtended | undefined, contextUser: UserInfo): Promise<'trailing' | 'embedded' | 'unsupported' | 'unknown'>;
1824
+ /**
1825
+ * The strings whose presence in a system prompt's unrendered template text means the template
1826
+ * still renders the volatile state itself, so the trailing fragment must be suppressed. Defaults
1827
+ * to {@link VOLATILE_TEMPLATE_MARKERS}: the three block headings plus the date and payload
1828
+ * placeholders. Extension point — an agent type whose template lays the state out under other
1829
+ * headings overrides this to return its own markers.
1830
+ */
1831
+ protected get volatileTemplateMarkers(): readonly string[];
1832
+ /**
1833
+ * True when unrendered template text contains any of {@link volatileTemplateMarkers} — the legacy
1834
+ * Loop layout, or any template that embeds the payload.
1835
+ */
1836
+ protected templateTextEmbedsVolatileState(templateText: string): boolean;
1837
+ /**
1838
+ * Raw template text (placeholders intact) for an AI prompt from the cached template engine.
1839
+ * Null when the prompt has no template or the lookup fails.
1840
+ */
1841
+ protected loadPromptTemplateText(prompt: MJAIPromptEntityExtended | undefined, contextUser: UserInfo): Promise<string | null>;
1842
+ /**
1843
+ * The child prompt's raw template text (placeholders intact), from the cached template engine.
1844
+ * Null when the prompt has no template or the lookup fails — which fails CLOSED: with no text to
1845
+ * inspect, {@link ResolveSpecializationPlacement} keeps the specialization in the system prompt.
1846
+ */
1847
+ protected loadChildPromptTemplateText(childPrompt: MJAIPromptEntityExtended, contextUser: UserInfo): Promise<string | null>;
1848
+ /**
1849
+ * The date/time strings exactly as the system placeholders would render them into the template.
1850
+ * Resolves only the three temporal placeholders (by name, through the same registry the template
1851
+ * uses, so a registered override applies here too) rather than every system placeholder — this runs
1852
+ * on every loop iteration.
1853
+ */
1854
+ protected resolveFragmentDateTime(promptParams: AIPromptParams): Promise<RuntimeStateDateTime | null>;
1855
+ /**
1856
+ * The scratchpad strings already placed in the template data by the prep step (so the fragment shows
1857
+ * exactly what the template would have). Null when the scratchpad is disabled or absent.
1858
+ */
1859
+ protected readScratchpadFromTemplateData(data: Record<string, unknown>): RuntimeStateScratchpad | null;
1387
1860
  /**
1388
1861
  * Executes the configured prompt. Always uses the attemptJSONRepair option to try to fix LLM
1389
1862
  * JSON syntax issues if they arise.
@@ -1538,6 +2011,11 @@ export declare class BaseAgent {
1538
2011
  * @returns Modified next step if guardrails exceeded, or original next step
1539
2012
  * @protected
1540
2013
  */
2014
+ private _selfCheckAttemptsByRun;
2015
+ private _selfCheckLinkByAgent;
2016
+ private applySelfCheck;
2017
+ /** Runs the self-check when a success exit did not pass through the guardrail hook. */
2018
+ private selfCheckSuccess;
1541
2019
  protected checkExecutionGuardrails<P>(params: ExecuteAgentParams, nextStep: BaseAgentNextStep<P>, currentPayload: P, agentRun: MJAIAgentRunEntityExtended, currentStep: MJAIAgentRunStepEntityExtended): Promise<BaseAgentNextStep<P>>;
1542
2020
  /**
1543
2021
  * Checks if any agent run guardrails have been exceeded.
@@ -1624,6 +2102,32 @@ export declare class BaseAgent {
1624
2102
  * @protected
1625
2103
  */
1626
2104
  protected serializePayloadAtEnd(payload: any): string | null;
2105
+ /**
2106
+ * Recovery Strategy 0: drop stale runtime-state fragments.
2107
+ *
2108
+ * Under append-only trailing-state retention (prefix-cache providers: OpenAI, xAI) every
2109
+ * iteration leaves its `<mj-runtime-state>` message in the history so the next request is an
2110
+ * exact prefix extension of the last. Those copies are cached tokens on the wire, but they are
2111
+ * context all the same, and they carry nothing the model needs: the CURRENT state always rides
2112
+ * as the fresh fragment appended to the outgoing request. So when the context overflows they
2113
+ * are the first thing to go, oldest first, all but the most recent. Keeping the newest one
2114
+ * matters for two reasons: it is the history's only fragment after this pass, so
2115
+ * {@link restoreTurn1VolatileStateIfNeeded} does not splice a turn-1 copy back in, and it
2116
+ * keeps the prefix intact from that point forward. The cost is one cache miss on the next call;
2117
+ * the alternative was a failed run.
2118
+ *
2119
+ * A no-op under replace-in-place retention, where the history never holds a fragment.
2120
+ *
2121
+ * @param params - Agent execution parameters
2122
+ * @param tokensToSave - Target number of tokens to free
2123
+ * @param currentStepCount - Current turn number, for the lifecycle event
2124
+ * @returns Result with tokens saved and strategy description
2125
+ * @protected
2126
+ */
2127
+ protected recoveryStrategy_DropStaleVolatileState(params: ExecuteAgentParams, tokensToSave: number, currentStepCount: number): {
2128
+ tokensSaved: number;
2129
+ strategyName: string;
2130
+ };
1627
2131
  /**
1628
2132
  * Recovery Strategy 1: Remove oldest tool-result messages.
1629
2133
  * Targets messages older than minAge turns for removal.
@@ -1728,6 +2232,8 @@ export declare class BaseAgent {
1728
2232
  * its direct predecessor's results, so context never compounds.
1729
2233
  *
1730
2234
  * Gated on conversationId + root depth — programmatic runs and sub-agents skip it.
2235
+ * Skipped under a history floor (`ConversationHistoryFrom`): the previous run's tool
2236
+ * results can quote messages from before the floor.
1731
2237
  * @protected
1732
2238
  */
1733
2239
  protected injectPriorTurnToolResults(params: ExecuteAgentParams): Promise<void>;
@@ -1952,6 +2458,171 @@ export declare class BaseAgent {
1952
2458
  * @protected
1953
2459
  */
1954
2460
  protected injectPipelineResultMessage(params: ExecuteAgentParams, result: PipelineExecutionResult): void;
2461
+ /** At most this many decision calls run at once for one agent turn. */
2462
+ private static readonly DECISION_CONCURRENCY;
2463
+ /**
2464
+ * Runs `fn` over `items` with at most `limit` calls in flight, keeping results in input order.
2465
+ * One call's failure never rejects the others: a call that throws is settled with `onError`'s
2466
+ * result in its place.
2467
+ */
2468
+ private runWithConcurrencyLimit;
2469
+ /**
2470
+ * Answers the decision requests from one agent turn, each logged as an `AIAgentRunStep`
2471
+ * (StepType 'Decision'), with bounded concurrency. A failed request never fails the run: it
2472
+ * becomes that request's `success: false`, which the agent reads on its next turn.
2473
+ *
2474
+ * Two limits bound the turn. At most `decisionsMaxRequests` requests run (default
2475
+ * {@link MAX_DECISION_REQUESTS_PER_TURN}); each request over that cap is not run and records no
2476
+ * step, and its result says why. And the requests make at most `decisionsMaxCallsPerTurn`
2477
+ * decision calls in total, counting every `forEachItemIn` item (default
2478
+ * {@link MAX_DECISION_CALLS_PER_TURN}). That budget is handed out in request order before any
2479
+ * call is made, so which calls run never depends on timing. A `forEachItemIn` request it cuts
2480
+ * short asks its first items and reports the rest in `skippedCount`. A request it leaves no calls
2481
+ * for is not run, records no step, and its result says why.
2482
+ *
2483
+ * @since 2.132.0
2484
+ */
2485
+ protected executeDecisionRequestsAsSteps(requests: AgentDecisionRequest[], finalPayload: unknown, agentTypePromptParams: Record<string, unknown> | undefined, params: ExecuteAgentParams): Promise<AgentDecisionResult[]>;
2486
+ /** The most decision requests one turn may run: `decisionsMaxRequests`, or {@link MAX_DECISION_REQUESTS_PER_TURN}. */
2487
+ private decisionRequestCap;
2488
+ /**
2489
+ * The most decision calls one turn's requests make in total, `forEachItemIn` items included:
2490
+ * `decisionsMaxCallsPerTurn`, or {@link MAX_DECISION_CALLS_PER_TURN}.
2491
+ */
2492
+ private decisionCallBudget;
2493
+ /** The most items one `forEachItemIn` request asks about: `decisionsMaxItems`, or its default. */
2494
+ private decisionMaxItems;
2495
+ /** A decision limit from the prompt params when it is a non-negative integer, or `fallback` when it is absent or anything else. */
2496
+ private decisionLimit;
2497
+ /**
2498
+ * Hands out the turn's decision-call budget to its requests in order, before any of them runs.
2499
+ * Each request gets the calls it wants while the budget lasts. The first one the budget cannot
2500
+ * cover gets what is left, and the ones after it get none.
2501
+ */
2502
+ private allotDecisionCalls;
2503
+ /**
2504
+ * The decision calls a request makes with no budget: one, or one per `forEachItemIn` item up to
2505
+ * `decisionsMaxItems`. A request that cannot make any, because it is not an object or its
2506
+ * `forEachItemIn` is not an array, wants none. A request that fails before it asks, such as one
2507
+ * with no valid question, still holds what its shape wants: the budget can then go unused, but
2508
+ * it is never exceeded.
2509
+ */
2510
+ private decisionCallsWanted;
2511
+ /**
2512
+ * The result of a request the turn's decision-call budget left no calls for. It was not run.
2513
+ * A budget of 0 turns decision calls off for the agent, so then asking again on a later turn
2514
+ * cannot help, and the result does not invite it.
2515
+ */
2516
+ private overBudgetDecisionResult;
2517
+ /** A request's id for its result, or its position when the model sent no usable id. */
2518
+ private decisionRequestId;
2519
+ /**
2520
+ * Runs a `'Decision'` next step: an agent type's decision requests, answered with no LLM turn.
2521
+ *
2522
+ * Each request goes through the same path a loop turn's decisions take
2523
+ * ({@link executeSingleDecisionRequestAsStep}), so it gets the same prompt default, state
2524
+ * resolution and error handling, and is logged as a `Decision` run step. Where a loop turn's
2525
+ * results go into the conversation, these come back to the agent type on the returned `'Retry'`
2526
+ * (`decisionResults`), because it routes on them. So each answer keeps its whole distribution
2527
+ * (`SummarizeDecisionAnswers`), which a path condition may read. A failed request is a result
2528
+ * with `success: false`, never a failed run: what a failure means is the agent type's call.
2529
+ *
2530
+ * @since 6.2.0
2531
+ */
2532
+ protected executeDecisionStep<P>(params: ExecuteAgentParams, decision: BaseAgentNextStep<P>): Promise<BaseAgentNextStep<P>>;
2533
+ /**
2534
+ * Answers one decision request, either once against its `state` or once per item of its
2535
+ * `forEachItemIn` array, and records it as a Decision step. The request is unchecked model
2536
+ * output, so any error finishes the step as failed rather than escaping: this never throws
2537
+ * once the step exists.
2538
+ *
2539
+ * @param callAllowance The most decision calls the request may make, from the turn's
2540
+ * `decisionsMaxCallsPerTurn` budget. It caps a `forEachItemIn` request's items below
2541
+ * `decisionsMaxItems`. A single-state request makes one call, and
2542
+ * {@link executeDecisionRequestsAsSteps} never starts one the budget left without it.
2543
+ * Unbounded by default.
2544
+ * @param summarize how the typed answers are summarised for whoever reads them next; defaults
2545
+ * to the loop turn's model-facing summary
2546
+ * @since 2.132.0
2547
+ */
2548
+ protected executeSingleDecisionRequestAsStep(request: AgentDecisionRequest, finalPayload: unknown, agentTypePromptParams: Record<string, unknown> | undefined, params: ExecuteAgentParams, callAllowance?: number, summarize?: DecisionAnswerSummarizer): Promise<AgentDecisionResult>;
2549
+ /** Asks the request's questions about one state, with the configured decision prompt. */
2550
+ private decisionAsker;
2551
+ /** Asks the questions once, against the request's state. */
2552
+ private askOnce;
2553
+ /**
2554
+ * Asks the same questions of each item of a payload array, up to `decisionsMaxItems` and the
2555
+ * request's share of the turn's call budget. Each item's call is its own child Decision step of
2556
+ * the request's step, carrying that call's prompt run, as each iteration of a ForEach is a child
2557
+ * step of its loop step.
2558
+ */
2559
+ private askForEachItem;
2560
+ /** Asks about one item of a `forEachItemIn` request, recorded as a child step of the request's step. */
2561
+ private askItemAsStep;
2562
+ /**
2563
+ * Links a decision call's prompt run to its step, as the Prompt step links its own, so the run's
2564
+ * cost and token totals and its `MaxCostPerRun` / `MaxTokensPerRun` checks count the call.
2565
+ */
2566
+ protected attachDecisionPromptRun(step: MJAIAgentRunStepEntityExtended, result: AIDecisionRunResult): void;
2567
+ /**
2568
+ * Links the prompt run of a decision call the run stopped waiting for (a timeout or a cancellation)
2569
+ * to its step, once the call settles. `AIDecisionRunner` writes the prompt run before it calls the
2570
+ * model, so a stopped call still has one. The link keeps that row on the run's trace, and counts its
2571
+ * usage in the run's cost and token totals when it settles before the run ends, as
2572
+ * {@link attachDecisionPromptRun} does on time. The step may already be finalized, so the link is
2573
+ * saved on its own. Never throws, and a call that never settles links nothing.
2574
+ */
2575
+ private linkLateDecisionPromptRun;
2576
+ /**
2577
+ * A literal state, or a value read from the payload: the whole payload for `payload`, one value
2578
+ * for a `payload.` path.
2579
+ */
2580
+ private resolveDecisionState;
2581
+ /** Reads a `payload.`-prefixed dotted path (or `payload` itself) from the payload. */
2582
+ private resolvePayloadPath;
2583
+ /** Strings pass through; anything else becomes indented JSON. */
2584
+ private decisionStateText;
2585
+ /** Finalizes the Decision step and builds the result the agent reads next turn. */
2586
+ private finishDecisionStep;
2587
+ /**
2588
+ * Answers the decision requests a prompt returned, or holds them when the step that carries
2589
+ * them can end the run, because then no turn would read their answers. Held requests run before
2590
+ * the next prompt ({@link runHeldDecisions}), or are skipped if the run ends first
2591
+ * ({@link skipHeldDecisions}). Skips them all, unasked, while the master switch is off
2592
+ * ({@link DecisionsEnabled}) or the agent's `decisions` response field is.
2593
+ */
2594
+ private processTurnDecisions;
2595
+ /**
2596
+ * Why the decisions sent with this step would be paid for and never read, or `undefined` when
2597
+ * the next turn reads them. Three ways a step's own outcome ends the run: a passing finishIf gate
2598
+ * (only an Actions step or a single sub-agent is gated), a sub-agent's `terminateAfter`, and
2599
+ * client tools sent with `taskComplete`, which end the run once the tools return. Every other
2600
+ * step, including client tools without `taskComplete`, goes on to a prompt that reads them.
2601
+ */
2602
+ private decisionsHoldReason;
2603
+ /**
2604
+ * Runs the decision requests a prompt held back, now that the step that carried them has run
2605
+ * without ending the run, so the prompt about to run reads their answers.
2606
+ */
2607
+ private runHeldDecisions;
2608
+ /**
2609
+ * Skips the decision requests a prompt held back, because the run ended before they could be
2610
+ * asked: the step that carried them ended it, or it was cancelled, or an error was thrown out of
2611
+ * the step loop. Called from the loop's terminate branch and from `Execute()`'s `finally`, so
2612
+ * every way out logs them. The held state is cleared before the log line, so the second call on
2613
+ * the terminate path logs nothing and each held request is logged exactly once.
2614
+ *
2615
+ * @param runEnd How the run ended, as a clause for the log line.
2616
+ */
2617
+ private skipHeldDecisions;
2618
+ /** How the run ended, as a clause for held decision requests that a cancellation or an error left unasked. */
2619
+ private runEndForHeldDecisions;
2620
+ /**
2621
+ * Injects decision results into the conversation as one tool-result message for the next turn.
2622
+ *
2623
+ * @since 2.132.0
2624
+ */
2625
+ protected injectDecisionResultsMessage(params: ExecuteAgentParams, results: AgentDecisionResult[]): void;
1955
2626
  /**
1956
2627
  * Creates a chat message containing sub-agent execution results.
1957
2628
  *
@@ -1981,6 +2652,52 @@ export declare class BaseAgent {
1981
2652
  * @private
1982
2653
  */
1983
2654
  private gatherPromptTemplateData;
2655
+ /**
2656
+ * Narrows the catalog once per run, on its first prompt (plan Task 3.7), and caches the result for
2657
+ * every later step. With narrowing off, or the master switch ({@link DecisionsEnabled}) off, it
2658
+ * asks nothing and records nothing, so the prompt describes the whole catalog. Never throws: any
2659
+ * failure leaves the full catalog in place. It narrows the prose catalog only:
2660
+ * {@link applyNativeTools} still declares every action and sub-agent.
2661
+ */
2662
+ private ensureCatalogNarrowing;
2663
+ /**
2664
+ * The run's limits, with actions left whole when the agent lacks Find Candidate Actions: a hidden
2665
+ * action would then be unreachable. That case is logged as a warning when it keeps a long action
2666
+ * list whole, since the agent asked for narrowing and did not get it.
2667
+ */
2668
+ private reachableCatalogNarrowingLimits;
2669
+ /**
2670
+ * Every item of the three lists as a narrowing candidate. An action or sub-agent with
2671
+ * `MinExecutionsPerRun` set, and the Find Candidate tools, are pinned: always shown.
2672
+ */
2673
+ private catalogNarrowingCandidates;
2674
+ /**
2675
+ * Asks the one decision, records it as the `Catalog narrowing` step, and returns what to hide.
2676
+ * Any failure is logged as a warning and hides nothing, so the prompt shows the full catalog.
2677
+ */
2678
+ private narrowCatalog;
2679
+ /**
2680
+ * The one decision call, against the opening request. Never throws, and never waits longer than
2681
+ * {@link CATALOG_NARROWING_TIMEOUT_MS} or past the run's cancellation: a throw, a timeout and a
2682
+ * cancelled run each come back as a failed result. Stopping also aborts the call, and links the
2683
+ * prompt run it still returns to `step` once it does ({@link linkLateDecisionPromptRun}).
2684
+ */
2685
+ private askCatalogNarrowing;
2686
+ /** Opens the `Catalog narrowing` Decision step with the decision's inputs. Without a run there is no step. */
2687
+ private startCatalogNarrowingStep;
2688
+ /** Finalizes the `Catalog narrowing` step: each narrowed list's counts, kept names and probabilities, or why it failed open. */
2689
+ private finishCatalogNarrowingStep;
2690
+ /** Logs that catalog narrowing failed open. */
2691
+ private warnCatalogNarrowing;
2692
+ /** The items of one list the prompt shows. Returns `items` itself when the run's narrowing hides none of them. */
2693
+ private hideNarrowedOut;
2694
+ /**
2695
+ * One catalog section as the prompt shows it: `full` when the run's narrowing hides none of
2696
+ * `items`, otherwise a {@link CatalogNarrowingNote} saying how many are hidden and how to reach
2697
+ * them, then the items still shown. A hidden item can still be called. Fails OPEN, unlike the
2698
+ * skill policy: an error shows `full` and logs a warning.
2699
+ */
2700
+ private narrowedCatalogSection;
1984
2701
  /**
1985
2702
  * Builds the agent-invariant {@link AgentBaseCatalog} — the resolved sub-agents + actions and
1986
2703
  * their formatted markdown, plus the base agent-type prompt params. Computed once per agent and
@@ -2021,6 +2738,40 @@ export declare class BaseAgent {
2021
2738
  * @since 2.131.0
2022
2739
  */
2023
2740
  protected buildAgentTypePromptParams(agentType: MJAIAgentTypeEntity | undefined, agent: MJAIAgentEntityExtended, runtimeOverrides?: Record<string, unknown>): Record<string, unknown>;
2741
+ /**
2742
+ * The agent and value pairs {@link warnOnceOnUnknownFinishIfMode} has already reported. It is
2743
+ * process-wide because the prompt params are merged again for every run of an agent, and on every
2744
+ * turn that carries runtime overrides. One warning per agent and value is enough. A run request
2745
+ * can set the value, so what this keeps is bounded: see {@link FinishIfModeWarnings}.
2746
+ */
2747
+ private static readonly finishIfModeWarnings;
2748
+ /**
2749
+ * Warns, once per agent and value, when the merged `finishIfMode` is set but is not a
2750
+ * {@link FinishIfMode}. {@link ResolveFinishIfMode} treats such a value as `'off'`, so without
2751
+ * this a typo such as `"On"` or `"true"` would turn the agent's gates off without a word. An
2752
+ * absent value is the default, so it is not reported.
2753
+ */
2754
+ private warnOnceOnUnknownFinishIfMode;
2755
+ /**
2756
+ * The master switch for decision-model use by this agent: `decisionsEnabled` in its merged
2757
+ * agent-type prompt params (type default < agent < the run's `data.__agentTypePromptParams`).
2758
+ * Anything but `true` is off, the default.
2759
+ *
2760
+ * While it is off the agent never asks a decision model on its own. Each automatic use checks it
2761
+ * before it asks, whatever its own setting says: inline `decisions` ({@link processTurnDecisions}),
2762
+ * `finishIf` gates ({@link finishIfSettings}), decision discovery ({@link isDecisionDiscoveryOnFor}),
2763
+ * the payload change check ({@link isPayloadFeedbackCheckOn}), catalog narrowing
2764
+ * ({@link ensureCatalogNarrowing}) and the Memory Manager's note gate. And
2765
+ * {@link applyResponseTypeAutoAlignment} keeps the `decisions` and `finishIf` docs and response
2766
+ * fields out of the prompt. While it is on, each use keeps its own setting, and each is off by default.
2767
+ *
2768
+ * Explicit uses never read it: a Flow agent's Decision step ({@link executeDecisionStep}) runs because
2769
+ * someone placed it, and the task-graph Decision step and the Run Decision action call
2770
+ * {@link AgentDecisionService} directly. That is why the check sits at each automatic use, not in the service.
2771
+ *
2772
+ * @param promptParams - The merged agent-type prompt params.
2773
+ */
2774
+ protected DecisionsEnabled(promptParams: Record<string, unknown> | undefined): boolean;
2024
2775
  /**
2025
2776
  * Applies auto-alignment rules to includeResponseTypeDefinition based on other flags.
2026
2777
  *
@@ -2034,6 +2785,10 @@ export declare class BaseAgent {
2034
2785
  * - includeCommandDocs → includeResponseTypeDefinition.commands
2035
2786
  * - includeForEachDocs → includeResponseTypeDefinition.forEach
2036
2787
  * - includeWhileDocs → includeResponseTypeDefinition.while
2788
+ * - includeDecisionsDocs → includeResponseTypeDefinition.decisions
2789
+ *
2790
+ * While the master switch is off ({@link DecisionsEnabled}), the decisions and finishIf docs and
2791
+ * response fields are off, even when set explicitly.
2037
2792
  *
2038
2793
  * @param params - The merged params object to modify in place
2039
2794
  * @param explicitResponseType - The explicitly set response type config from agent/runtime (not schema defaults)
@@ -2051,6 +2806,90 @@ export declare class BaseAgent {
2051
2806
  * @since 2.131.0
2052
2807
  */
2053
2808
  protected extractSchemaDefaults(schemaJson: string | null | undefined): Record<string, unknown>;
2809
+ /**
2810
+ * The finishIf settings of the current step, from its merged agent-type prompt params. A gate is
2811
+ * evaluated when the master switch is on ({@link DecisionsEnabled}), `finishIfMode` is `shadow` or
2812
+ * `on`, and `includeResponseTypeDefinition.finishIf` is not `false`; it ends the run only in `on`.
2813
+ */
2814
+ private finishIfSettings;
2815
+ /** Whether a passing finishIf gate ends the run: only in `on` mode. */
2816
+ private finishIfActs;
2817
+ /**
2818
+ * Whether an evaluated gate ends the run. In shadow mode a passing gate is only logged: the
2819
+ * outcome is already recorded on its `Finish check` step, and the model takes its next turn.
2820
+ */
2821
+ private gateEndsRun;
2822
+ /**
2823
+ * Runs the finishIf gate after an Actions step, and returns the Success step when it passes.
2824
+ * ForEach and While call executeActionsStep without a conversation message, and are never gated.
2825
+ */
2826
+ private finishAfterActions;
2827
+ /**
2828
+ * Runs the finishIf gate after a Sub-Agent step that succeeded without terminating, and returns
2829
+ * the step with `terminate: true` when it passes, as `terminateAfter` would.
2830
+ */
2831
+ private finishAfterSubAgent;
2832
+ /**
2833
+ * Asks the finishIf questions about the step's results, then checks that the normal Success
2834
+ * validation would allow the run to end. Records the check as a `Finish check` Decision step.
2835
+ * Never throws: any error means the gate did not pass, and the run continues as it would have.
2836
+ */
2837
+ private evaluateFinishIf;
2838
+ /**
2839
+ * Asks each finishIf question as a Likelihood. Every one must reach the threshold. The call's
2840
+ * prompt run is linked to the `Finish check` step, so the run's cost and tokens count it.
2841
+ */
2842
+ private askFinishIf;
2843
+ /**
2844
+ * Returns why the normal Success validation would refuse to end the run, or `undefined` when it
2845
+ * allows it. The check must not count as a validation retry, so the counters are restored:
2846
+ * otherwise a gate that keeps not passing could exhaust the retries and fail the run.
2847
+ */
2848
+ private finishIfValidationRefusal;
2849
+ /** The Success step a passing gate returns after actions, in the shape of the client-tools `terminateAfterExecution` branch. */
2850
+ private finishIfSuccessStep;
2851
+ /** Finalizes the `Finish check` step with the outcome. A failure to save it never affects the run. */
2852
+ private finalizeFinishCheckStep;
2853
+ /**
2854
+ * Whether the merged agent-type prompt params turn the payload change check on. It is off unless
2855
+ * the master switch ({@link DecisionsEnabled}) and `payloadFeedbackCheck` are both `true`.
2856
+ */
2857
+ private isPayloadFeedbackCheckOn;
2858
+ /**
2859
+ * Runs the payload change check ({@link checkPayloadChanges}) on a step's applied payload changes
2860
+ * when it applies: the analyzer flagged a change for feedback, the check is on
2861
+ * ({@link isPayloadFeedbackCheckOn}), and a turn will read the result. A step that ends the run
2862
+ * skips it: no call to pay for, and no message left in the conversation. Never throws.
2863
+ */
2864
+ private checkPayloadChangesWhenOn;
2865
+ /**
2866
+ * Whether the step ends the run, so no turn would read the payload change check's message: it
2867
+ * terminates, or it is a `Success` or `Chat` step, which hand the run back to the caller.
2868
+ */
2869
+ private stepEndsRun;
2870
+ /**
2871
+ * The payload change check. Asks whether each change the analyzer flagged was intended, as one
2872
+ * Likelihood per change in one decision call, and records it as a `Payload change check`
2873
+ * Decision step. The changes judged unintended are listed in a message for the agent's next
2874
+ * turn, which asks it to confirm or restore them.
2875
+ *
2876
+ * It never reverts or blocks a change: the agent decides. When the decision cannot answer,
2877
+ * every change is accepted, as it is with the check off. Never throws.
2878
+ */
2879
+ private checkPayloadChanges;
2880
+ /**
2881
+ * What the payload change check's decision reads: the agent's own reasoning for the step (from its
2882
+ * response, else from the step), its message, and the reasoning it gave with the change. The check
2883
+ * never runs on a `Chat` or `Success` step, so the message comes from the response alone.
2884
+ */
2885
+ private payloadFeedbackContext;
2886
+ /**
2887
+ * Finalizes the `Payload change check` step with each change's probability and outcome. The step
2888
+ * fails when no decision answered, and its error says why. A failure to save it never affects the run.
2889
+ */
2890
+ private finalizePayloadCheckStep;
2891
+ /** Adds the payload change check's message to the conversation, for the agent's next turn. */
2892
+ private injectPayloadCheckMessage;
2054
2893
  /**
2055
2894
  * Whether THIS action may use the run's runtime API key for THIS driver class. The default is
2056
2895
  * yes: the run was started on those keys, and an action that calls a vendor on the user's behalf
@@ -2073,12 +2912,14 @@ export declare class BaseAgent {
2073
2912
  * @param {ExecuteAgentParams} params - Parameters from agent execution for context passing
2074
2913
  * @param {AgentAction} action - Action to execute
2075
2914
  * @param {UserInfo} [contextUser] - Optional user context for permissions
2915
+ * @param {ExecuteSingleActionOptions} [options] - `skipCircuitBreaker` bypasses the run-scoped
2916
+ * circuit breaker for callers that do their own failure accounting (the pipeline executor)
2076
2917
  *
2077
2918
  * @returns {Promise<ActionResult>} ActionResult object from the action execution
2078
2919
  *
2079
2920
  * @throws {Error} If the action fails to execute
2080
2921
  */
2081
- ExecuteSingleAction(params: ExecuteAgentParams, action: AgentAction, actionEntity: MJActionEntityExtended, contextUser?: UserInfo): Promise<ActionResult>;
2922
+ ExecuteSingleAction(params: ExecuteAgentParams, action: AgentAction, actionEntity: MJActionEntityExtended, contextUser?: UserInfo, options?: ExecuteSingleActionOptions): Promise<ActionResult>;
2082
2923
  /**
2083
2924
  * Makes a SLICED conversation window safe to send on its own.
2084
2925
  *
@@ -2109,6 +2950,13 @@ export declare class BaseAgent {
2109
2950
  * **Priority:** AIAgentRelationship.MessageMode takes precedence over AIAgent.MessageMode
2110
2951
  * to allow different parent agents to pass messages differently to the same sub-agent.
2111
2952
  *
2953
+ * **Runtime state never crosses the boundary.** The parent's trailing runtime-state messages
2954
+ * (`metadata.volatileState` — its payload, scratchpad and, when relocated, its specialization;
2955
+ * retained in the history under append-only mode) are dropped BEFORE any mode slices the
2956
+ * history, so a sub-agent never sees the parent's state, never has it counted against
2957
+ * `MaxMessages`, and never receives it unescaped when it builds no fragment of its own. The
2958
+ * sub-agent builds its own fragment at its prompt step.
2959
+ *
2112
2960
  * Subclasses can override this method to implement custom message preparation logic
2113
2961
  * specific to their domain (e.g., Skip agents adding special context).
2114
2962
  *
@@ -2861,6 +3709,13 @@ export declare class BaseAgent {
2861
3709
  * Supports both dot notation (obj.prop) and array indexing (arr[0]).
2862
3710
  *
2863
3711
 
3712
+ /**
3713
+ * The {@link ExecuteSingleActionOptions} the main loop passes for this run's agent type: the
3714
+ * circuit-breaker exemption when the type has opted out (`BaseAgentType.UsesActionCircuitBreaker`
3715
+ * is false — Flow), otherwise none. Kept as a seam so a subclass can widen or narrow the
3716
+ * exemption without touching the loop.
3717
+ */
3718
+ protected actionOptionsForAgentType(): ExecuteSingleActionOptions | undefined;
2864
3719
  /**
2865
3720
  * Executes actions step and tracks it.
2866
3721
  *
@@ -2915,6 +3770,8 @@ export declare class BaseAgent {
2915
3770
  * them calls this after MJ's gates
2916
3771
  * (AcceptsSkills, Status, agent grant, user Run permission, the ActivationMode double gate) and
2917
3772
  * before anything activates. The default is the identity: MJ's gates are the whole policy.
3773
+ * Catalog narrowing (plan Task 3.7) is not part of this policy: it runs after it, at the catalog
3774
+ * site, and only hides skills from the prompt. An override never needs to call `super` for it.
2918
3775
  *
2919
3776
  * Override it to layer a policy MJ has no table for — a tenant licensing model, a per-organization
2920
3777
  * entitlement, a feature flag — and it applies everywhere at once. Without this seam a subclass
@@ -3294,6 +4151,23 @@ export declare class BaseAgent {
3294
4151
  * rather than being deleted after a single prompt turn.
3295
4152
  */
3296
4153
  private injectLoopResultsMessage;
4154
+ /**
4155
+ * Fails a loop that never ran an iteration, and tells the model why.
4156
+ *
4157
+ * A Loop agent answers a Failed step by prompting again (`HandleStepFallback` returns null), and
4158
+ * nothing on that path reads the step's `errorMessage`. Without the injected message the model
4159
+ * gets another turn with no idea its loop failed, and is likely to emit the same loop again.
4160
+ * Flow agents don't inject loop results, so for them this is just the Failed step.
4161
+ */
4162
+ private failLoopBeforeFirstIteration;
4163
+ /**
4164
+ * One loop error as readable text. Joining the error objects directly wrote "[object Object]"
4165
+ * into the step's ErrorMessage. Falls back to JSON when an iteration threw something with no
4166
+ * message (a thrown non-Error).
4167
+ */
4168
+ private describeLoopError;
4169
+ /** All loop errors as text for a step's ErrorMessage. */
4170
+ private formatLoopErrors;
3297
4171
  /**
3298
4172
  * Formats loop iteration results as markdown. Handles two distinct result shapes
3299
4173
  * depending on whether the loop body executed actions or sub-agents:
@@ -3456,6 +4330,8 @@ export declare class BaseAgent {
3456
4330
  * (agent or type ContextWindowMaxTokens) — before the first prompt the model is
3457
4331
  * unknown, and compacting against the conservative default would over-trigger on
3458
4332
  * large-context models. The post-turn hook (real model known) covers those.
4333
+ * Skipped under a history floor (`ConversationHistoryFrom`): a summary folds in the
4334
+ * conversation from its first message, which is what the floor excludes.
3459
4335
  * @protected
3460
4336
  */
3461
4337
  protected checkPreTurnCompaction(params: ExecuteAgentParams, config: AgentConfiguration | undefined): Promise<void>;
@@ -3467,6 +4343,11 @@ export declare class BaseAgent {
3467
4343
  * final step (→ AwaitingFeedback) is the NORMAL ending of a conversational turn;
3468
4344
  * gating on 'Completed' alone silently disabled post-turn compaction for exactly
3469
4345
  * the long-chat scenario this feature targets.
4346
+ *
4347
+ * Skipped under a history floor (`ConversationHistoryFrom`). A run with a floor must not
4348
+ * write the conversation's summary: the summary covers every row below its boundary, and
4349
+ * a run that may not read the rows before the floor can't produce that — nor, once reads
4350
+ * are narrowed to what the asker can see, can it tell which rows it was not shown.
3470
4351
  * @protected
3471
4352
  */
3472
4353
  protected startPostTurnCompaction(): void;