@memberjunction/ai-agents 6.2.0-edge.1 → 6.2.0-edge.3

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 (131) hide show
  1. package/README.md +18 -0
  2. package/dist/AgentDecisionService.d.ts +90 -0
  3. package/dist/AgentDecisionService.d.ts.map +1 -0
  4. package/dist/AgentDecisionService.js +159 -0
  5. package/dist/AgentDecisionService.js.map +1 -0
  6. package/dist/AgentRunner.d.ts +9 -0
  7. package/dist/AgentRunner.d.ts.map +1 -1
  8. package/dist/AgentRunner.js +23 -7
  9. package/dist/AgentRunner.js.map +1 -1
  10. package/dist/ConversationCompactionManager.d.ts +7 -1
  11. package/dist/ConversationCompactionManager.d.ts.map +1 -1
  12. package/dist/ConversationCompactionManager.js +4 -1
  13. package/dist/ConversationCompactionManager.js.map +1 -1
  14. package/dist/KnowledgeAgent.d.ts.map +1 -1
  15. package/dist/KnowledgeAgent.js +6 -6
  16. package/dist/KnowledgeAgent.js.map +1 -1
  17. package/dist/PayloadFeedbackManager.d.ts +116 -14
  18. package/dist/PayloadFeedbackManager.d.ts.map +1 -1
  19. package/dist/PayloadFeedbackManager.js +229 -88
  20. package/dist/PayloadFeedbackManager.js.map +1 -1
  21. package/dist/agent-context-injector.d.ts +47 -3
  22. package/dist/agent-context-injector.d.ts.map +1 -1
  23. package/dist/agent-context-injector.js +77 -10
  24. package/dist/agent-context-injector.js.map +1 -1
  25. package/dist/agent-memory-context-builder.d.ts +13 -0
  26. package/dist/agent-memory-context-builder.d.ts.map +1 -1
  27. package/dist/agent-memory-context-builder.js +24 -5
  28. package/dist/agent-memory-context-builder.js.map +1 -1
  29. package/dist/agent-types/flow-agent-type.d.ts +97 -0
  30. package/dist/agent-types/flow-agent-type.d.ts.map +1 -1
  31. package/dist/agent-types/flow-agent-type.js +281 -24
  32. package/dist/agent-types/flow-agent-type.js.map +1 -1
  33. package/dist/agent-types/flow-graph-executor.d.ts +12 -1
  34. package/dist/agent-types/flow-graph-executor.d.ts.map +1 -1
  35. package/dist/agent-types/flow-graph-executor.js +25 -1
  36. package/dist/agent-types/flow-graph-executor.js.map +1 -1
  37. package/dist/agent-types/loop-agent-prompt-params.d.ts +239 -66
  38. package/dist/agent-types/loop-agent-prompt-params.d.ts.map +1 -1
  39. package/dist/agent-types/loop-agent-prompt-params.js +47 -2
  40. package/dist/agent-types/loop-agent-prompt-params.js.map +1 -1
  41. package/dist/agent-types/loop-agent-response-type.d.ts +12 -1
  42. package/dist/agent-types/loop-agent-response-type.d.ts.map +1 -1
  43. package/dist/agent-types/loop-agent-response-type.js.map +1 -1
  44. package/dist/agent-types/loop-agent-type.d.ts +26 -0
  45. package/dist/agent-types/loop-agent-type.d.ts.map +1 -1
  46. package/dist/agent-types/loop-agent-type.js +115 -5
  47. package/dist/agent-types/loop-agent-type.js.map +1 -1
  48. package/dist/base-agent.d.ts +527 -10
  49. package/dist/base-agent.d.ts.map +1 -1
  50. package/dist/base-agent.js +1779 -110
  51. package/dist/base-agent.js.map +1 -1
  52. package/dist/catalog-narrowing.d.ts +136 -0
  53. package/dist/catalog-narrowing.d.ts.map +1 -0
  54. package/dist/catalog-narrowing.js +212 -0
  55. package/dist/catalog-narrowing.js.map +1 -0
  56. package/dist/decision-discovery.d.ts +401 -0
  57. package/dist/decision-discovery.d.ts.map +1 -0
  58. package/dist/decision-discovery.js +511 -0
  59. package/dist/decision-discovery.js.map +1 -0
  60. package/dist/finish-if-mode-warnings.d.ts +39 -0
  61. package/dist/finish-if-mode-warnings.d.ts.map +1 -0
  62. package/dist/finish-if-mode-warnings.js +78 -0
  63. package/dist/finish-if-mode-warnings.js.map +1 -0
  64. package/dist/finish-if-state.d.ts +72 -0
  65. package/dist/finish-if-state.d.ts.map +1 -0
  66. package/dist/finish-if-state.js +109 -0
  67. package/dist/finish-if-state.js.map +1 -0
  68. package/dist/index.d.ts +10 -0
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +11 -0
  71. package/dist/index.js.map +1 -1
  72. package/dist/memory-manager-agent.d.ts +108 -2
  73. package/dist/memory-manager-agent.d.ts.map +1 -1
  74. package/dist/memory-manager-agent.js +172 -9
  75. package/dist/memory-manager-agent.js.map +1 -1
  76. package/dist/memory-note-gate.d.ts +208 -0
  77. package/dist/memory-note-gate.d.ts.map +1 -0
  78. package/dist/memory-note-gate.js +294 -0
  79. package/dist/memory-note-gate.js.map +1 -0
  80. package/dist/native-tools/action-tool-builder.d.ts +14 -0
  81. package/dist/native-tools/action-tool-builder.d.ts.map +1 -1
  82. package/dist/native-tools/action-tool-builder.js +62 -7
  83. package/dist/native-tools/action-tool-builder.js.map +1 -1
  84. package/dist/native-tools/control-tools.d.ts +17 -1
  85. package/dist/native-tools/control-tools.d.ts.map +1 -1
  86. package/dist/native-tools/control-tools.js +40 -3
  87. package/dist/native-tools/control-tools.js.map +1 -1
  88. package/dist/realtime/bridge-host-params.d.ts +22 -0
  89. package/dist/realtime/bridge-host-params.d.ts.map +1 -0
  90. package/dist/realtime/bridge-host-params.js +53 -0
  91. package/dist/realtime/bridge-host-params.js.map +1 -0
  92. package/dist/realtime/bridge-realtime-session-factory.d.ts +23 -2
  93. package/dist/realtime/bridge-realtime-session-factory.d.ts.map +1 -1
  94. package/dist/realtime/bridge-realtime-session-factory.js +22 -6
  95. package/dist/realtime/bridge-realtime-session-factory.js.map +1 -1
  96. package/dist/realtime/bridge-room-transcript-sink.d.ts.map +1 -1
  97. package/dist/realtime/bridge-room-transcript-sink.js +15 -9
  98. package/dist/realtime/bridge-room-transcript-sink.js.map +1 -1
  99. package/dist/realtime/bridge-session-transcript-sink.d.ts +37 -0
  100. package/dist/realtime/bridge-session-transcript-sink.d.ts.map +1 -0
  101. package/dist/realtime/bridge-session-transcript-sink.js +58 -0
  102. package/dist/realtime/bridge-session-transcript-sink.js.map +1 -0
  103. package/dist/realtime/realtime-client-session-service.d.ts +117 -12
  104. package/dist/realtime/realtime-client-session-service.d.ts.map +1 -1
  105. package/dist/realtime/realtime-client-session-service.js +162 -39
  106. package/dist/realtime/realtime-client-session-service.js.map +1 -1
  107. package/dist/realtime/realtime-coagent-resolution.d.ts +90 -0
  108. package/dist/realtime/realtime-coagent-resolution.d.ts.map +1 -0
  109. package/dist/realtime/realtime-coagent-resolution.js +186 -0
  110. package/dist/realtime/realtime-coagent-resolution.js.map +1 -0
  111. package/dist/realtime/realtime-delegation-narrator.d.ts +97 -0
  112. package/dist/realtime/realtime-delegation-narrator.d.ts.map +1 -0
  113. package/dist/realtime/realtime-delegation-narrator.js +162 -0
  114. package/dist/realtime/realtime-delegation-narrator.js.map +1 -0
  115. package/dist/realtime/realtime-session-runner.d.ts +2 -82
  116. package/dist/realtime/realtime-session-runner.d.ts.map +1 -1
  117. package/dist/realtime/realtime-session-runner.js +12 -187
  118. package/dist/realtime/realtime-session-runner.js.map +1 -1
  119. package/dist/realtime/realtime-vendor-resolution.d.ts +8 -3
  120. package/dist/realtime/realtime-vendor-resolution.d.ts.map +1 -1
  121. package/dist/realtime/realtime-vendor-resolution.js +3 -3
  122. package/dist/realtime/realtime-vendor-resolution.js.map +1 -1
  123. package/dist/rubric-evaluation-agent-runner.d.ts +2 -0
  124. package/dist/rubric-evaluation-agent-runner.d.ts.map +1 -0
  125. package/dist/rubric-evaluation-agent-runner.js +47 -0
  126. package/dist/rubric-evaluation-agent-runner.js.map +1 -0
  127. package/dist/self-check.d.ts +101 -0
  128. package/dist/self-check.d.ts.map +1 -0
  129. package/dist/self-check.js +74 -0
  130. package/dist/self-check.js.map +1 -0
  131. package/package.json +19 -18
@@ -14,21 +14,24 @@ import { MJAIAgentTypeEntity, MJTemplateParamEntity, MJAIAgentRelationshipEntity
14
14
  import { type NativeToolBinding } from './native-tools/control-tools.js';
15
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';
29
31
  import { RuntimeStateDateTime, RuntimeStateScratchpad } from './runtime-state-fragment.js';
30
32
  import { ArtifactToolCall, StoredToolResult } from './ArtifactToolManager.js';
31
33
  import { MemoryWriteRequest, MemoryWriteResult } from './MemoryWriteManager.js';
34
+ import { AgentDecisionService } from './AgentDecisionService.js';
32
35
  import { PipelineToolRegistry, PipelineExecutionResult } from './pipeline/index.js';
33
36
  /**
34
37
  * Compact representation of a single action's execution result, used for
@@ -123,6 +126,12 @@ interface AgentBaseCatalog {
123
126
  /** Agent-type prompt params merged from schema defaults + agent config (NO runtime overrides). */
124
127
  baseAgentTypePromptParams: Record<string, unknown>;
125
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>;
126
135
  export declare class BaseAgent {
127
136
  /**
128
137
  * Maximum allowed validation retries before forcing failure.
@@ -649,6 +658,10 @@ export declare class BaseAgent {
649
658
  * Allows agents to explore input artifacts on demand.
650
659
  */
651
660
  private _artifactToolManager;
661
+ /**
662
+ * Service for evaluating agent decisions inline via fast decision models.
663
+ */
664
+ protected _agentDecisionService: AgentDecisionService;
652
665
  /**
653
666
  * Reverse map from sanitized tool name back to Action, for the turn currently being prepared.
654
667
  *
@@ -685,6 +698,47 @@ export declare class BaseAgent {
685
698
  * @private
686
699
  */
687
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
+ * The run's {@link AIPromptExecutionScope}, recorded when the run starts, for decision calls made
724
+ * from helpers that are not handed the run's params (discovery, catalog narrowing).
725
+ * @private
726
+ */
727
+ private _runExecutionScope;
728
+ /**
729
+ * Whether the run answers its conversation's opening request ({@link IsOpeningTurn}), read from
730
+ * the messages it started with. Decision discovery asks about no other turn.
731
+ * @private
732
+ */
733
+ private _isOpeningTurn;
734
+ /** The longest the catalog narrowing decision may take before the run shows the full catalog. */
735
+ private static readonly CATALOG_NARROWING_TIMEOUT_MS;
736
+ /**
737
+ * Decision requests held back by the prompt that made them, because the step that carried them
738
+ * can end the run. They run before the next prompt, or are skipped when the run ends first.
739
+ * @private
740
+ */
741
+ private _heldDecisions;
688
742
  /**
689
743
  * IDs of skills already activated during this run. Prevents re-activation from re-appending
690
744
  * the same instructions to context / re-pushing duplicate actionChanges/subAgentChanges entries
@@ -1321,6 +1375,16 @@ export declare class BaseAgent {
1321
1375
  * @returns A human-readable scope label
1322
1376
  */
1323
1377
  private determineNoteScope;
1378
+ /**
1379
+ * The observability context memory injection runs under for an agent run: the run's ID, the next
1380
+ * step number, and a callback that adds each rerank step to the run's steps. A rerank step carries
1381
+ * the rerank's prompt run, whose cost and token rollups include a prompt-backed reranker's own
1382
+ * prompt runs, so the run's totals and its `MaxCostPerRun` / `MaxTokensPerRun` guardrails count
1383
+ * them. Undefined when there is no run.
1384
+ *
1385
+ * @param run - The current agent run, or null before one exists
1386
+ */
1387
+ protected MemoryObservability(run: MJAIAgentRunEntityExtended | null): AgentMemoryObservability | undefined;
1324
1388
  /**
1325
1389
  * Inject notes and examples into agent context memory.
1326
1390
  * Called automatically before agent execution if injection is enabled on the agent.
@@ -1378,6 +1442,98 @@ export declare class BaseAgent {
1378
1442
  * @returns The structured RAG result, or `null` if no scopes produced results.
1379
1443
  */
1380
1444
  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>;
1445
+ /**
1446
+ * Decision discovery (plan Task 3.1): suggests the agent to delegate to before the first prompt.
1447
+ *
1448
+ * Runs in parallel with the rest of Phase 2 of `Execute()`, and only when the merged agent-type
1449
+ * prompt params set `decisionsEnabled: true` (the master switch, {@link DecisionsEnabled}) and
1450
+ * `decisionDiscovery: true`, the run answers its conversation's opening request
1451
+ * ({@link IsOpeningTurn}), and that request @mentions no agent. A follow-up turn is never asked
1452
+ * about: it may be continuing work with an agent already engaged, and a suggestion must not pull
1453
+ * the agent away from it. One decision asks which of the agents the user may run (and the host
1454
+ * allows) should handle the request, and whether a specialist should. When both answers are
1455
+ * confident, a `<suggested_agent>` system message is unshifted onto `conversationMessages`, the
1456
+ * way pre-execution RAG adds `<retrieved_context>`. Each discovery is recorded as one
1457
+ * `Agent discovery` Decision step.
1458
+ *
1459
+ * Fails safe: an error, a timeout, a cancelled run, an unusable answer or an unsure one adds
1460
+ * nothing, so the agent behaves as it would without discovery. So do fewer than
1461
+ * {@link DECISION_DISCOVERY_MIN_OPTIONS} options. Never delays the first prompt by more than
1462
+ * {@link DECISION_DISCOVERY_TIMEOUT_MS}, and never throws.
1463
+ *
1464
+ * The any-applies question does not name the options, so the decision cannot say that none of
1465
+ * them fits: see {@link DECISION_DISCOVERY_APPLIES_INSTRUCTIONS} for why it stays that way for now.
1466
+ *
1467
+ * @param agent - The agent being executed.
1468
+ * @param contextUser - The user whose run permission decides the options.
1469
+ * @param conversationMessages - The mutated message array that flows to the LLM (the suggestion is unshifted here).
1470
+ * @param data - The run's `ExecuteAgentParams.data`. Its `__agentTypePromptParams` overrides the agent's prompt
1471
+ * params, and its `ALL_AVAILABLE_AGENTS`, when an array, is the host's allow-list: no other agent is suggested.
1472
+ */
1473
+ protected InjectDecisionDiscovery(agent: MJAIAgentEntityExtended, contextUser: UserInfo | undefined, conversationMessages: ChatMessage[] | undefined, data: Record<string, unknown> | undefined): Promise<void>;
1474
+ /**
1475
+ * Whether discovery is on for this run: the master switch ({@link DecisionsEnabled}) and
1476
+ * `decisionDiscovery` are both on. Read without rebuilding the merged prompt params, since it is
1477
+ * asked on every run of every agent: each setting from the per-run override when it sets one,
1478
+ * otherwise from the agent's base params, cached on AIEngine with its base catalog. Only a cold
1479
+ * cache builds them.
1480
+ */
1481
+ private isDecisionDiscoveryOnFor;
1482
+ /**
1483
+ * The run's merged agent-type prompt params (schema defaults < agent < per-run overrides), once
1484
+ * discovery is on: the cached base params when there is no override, otherwise built.
1485
+ */
1486
+ private decisionDiscoveryPromptParams;
1487
+ /** The agent's base prompt params (no per-run overrides), from the base catalog AIEngine caches, when it holds one. */
1488
+ private cachedBasePromptParams;
1489
+ /** Builds the merged prompt params, as `gatherPromptTemplateData` does. */
1490
+ private buildDecisionDiscoveryPromptParams;
1491
+ /**
1492
+ * Records one `Agent discovery` step around a bounded discovery, and returns what it found. A
1493
+ * failed discovery is logged as a warning; an unsure one only in verbose logs, except that an
1494
+ * answer from a model with no discovery calibration is warned about once per model, because
1495
+ * then discovery can never suggest anything.
1496
+ */
1497
+ private runDecisionDiscovery;
1498
+ /** The answering models already warned about as having no discovery calibration, so each is warned about once per process. */
1499
+ private static readonly _uncalibratedDiscoveryModelsWarned;
1500
+ /**
1501
+ * Warns, once per model, that discovery answered by a model with no discovery calibration
1502
+ * suggests nothing. That happens when a decision model is added or renamed, when a vendor model
1503
+ * moves to another version (Jev's `APIName`), or when LLM Decision answers through a chat model
1504
+ * other than the one its calibration was fitted on; without the warning the only trace is each
1505
+ * `Agent discovery` step's reason.
1506
+ */
1507
+ private static warnUncalibratedDiscoveryModel;
1508
+ /**
1509
+ * Runs `discover` until it finishes, {@link DECISION_DISCOVERY_TIMEOUT_MS} passes, or the run is
1510
+ * cancelled. A timeout or a cancellation aborts the signal `discover` was given, which aborts the
1511
+ * decision call, and returns a failed discovery at once. What `discover` returns after that
1512
+ * suggests nothing, but the prompt run of its decision call is still linked to `step` once it
1513
+ * settles ({@link linkLateDecisionPromptRun}), so the run counts the call's cost.
1514
+ */
1515
+ private boundDecisionDiscovery;
1516
+ /**
1517
+ * The discovery itself: the options, rebuilt from the permitted catalog, then one decision about
1518
+ * the opening request, and what its answer means. Never throws.
1519
+ */
1520
+ private discoverAgent;
1521
+ /**
1522
+ * The Choice's options, rebuilt on every call and never cached ({@link BuildDecisionDiscoveryOptionSet}):
1523
+ * from AIEngine's current catalog, the agents the user may run, the decision prompt's option cap,
1524
+ * and the semantic search over the opening request when the provider can run it.
1525
+ */
1526
+ private decisionDiscoveryOptionSet;
1527
+ /** Opens the `Agent discovery` Decision step. Without a run there is no step. */
1528
+ private startDecisionDiscoveryStep;
1529
+ /**
1530
+ * Finalizes the `Agent discovery` step: the answer, whether it was injected, the host allow-list,
1531
+ * the agents left out for having no description (at most {@link DECISION_DISCOVERY_MAX_RECORDED_IDS}
1532
+ * IDs), any narrowing, and the call's usage.
1533
+ */
1534
+ private finishDecisionDiscoveryStep;
1535
+ /** Logs that decision discovery failed, so nothing was suggested. */
1536
+ private warnDecisionDiscovery;
1381
1537
  /**
1382
1538
  * Converts UI markup (@{...} syntax) in user messages to plain text.
1383
1539
  * This prevents agents from being confused by UI-specific JSON syntax and reduces token usage.
@@ -1518,15 +1674,22 @@ export declare class BaseAgent {
1518
1674
  /**
1519
1675
  * The `tool_choice` for this turn (§8.3).
1520
1676
  *
1521
- * `'auto'` normally, `'none'` on the last turn this run will be allowed.
1677
+ * `'auto'` normally; on the last turn this run will be allowed, a forced `complete_task` call.
1522
1678
  *
1523
1679
  * **Why the final turn is special.** A tool call is a request to continue: the framework runs
1524
1680
  * the action, feeds the result back, and the model decides again. On the last permitted
1525
1681
  * iteration there is no "again" — the limit check fires the moment the turn returns, so the
1526
1682
  * action is executed, paid for, and its result discarded, and the run ends with no answer for
1527
1683
  * the user because the model spent its last turn asking a question instead of answering one.
1528
- * Forcing `'none'` converts that turn into what the framework actually needs from it: a
1529
- * terminal envelope.
1684
+ * The final turn is forced to what the framework actually needs from it: a terminal answer.
1685
+ *
1686
+ * **Why `complete_task` and not `'none'`.** Under implicit control flow, `'none'` forbids the
1687
+ * model's only way to store its result — `payload_change_request` and `complete_task` are tools
1688
+ * too — so a forced `'none'` turn can end the run but never deliver the payload. Naming
1689
+ * `complete_task` forces the one call that does both. A model that is NOT on implicit control
1690
+ * flow never receives `complete_task` (the runner strips control tools), and the runner then
1691
+ * downgrades the named choice to `'none'`: the envelope turn the hybrid needs. Providers also
1692
+ * enforce a named choice more reliably than `'none'`.
1530
1693
  *
1531
1694
  * **What this does NOT fix.** Models call a tool on a measurable share of turns whose right
1532
1695
  * answer was chat, completion or delegation. Those are not predictable
@@ -1534,11 +1697,11 @@ export declare class BaseAgent {
1534
1697
  * address them. That belongs to the prompt, and is why the native-mode Actions section names
1535
1698
  * the cases explicitly.
1536
1699
  *
1537
- * Subclasses may narrow this further; the base contract is that a forced `'none'` must never be
1538
- * relaxed to `'auto'` on a turn the framework has already decided is terminal.
1700
+ * Subclasses may narrow this further; the base contract is that a forced terminal choice must
1701
+ * never be relaxed to `'auto'` on a turn the framework has already decided is terminal.
1539
1702
  *
1540
1703
  * @param params The run parameters, for the per-run iteration override
1541
- * @returns `'none'` on the final permitted iteration, otherwise `'auto'`
1704
+ * @returns `{ name: 'complete_task' }` on the final permitted iteration, otherwise `'auto'`
1542
1705
  */
1543
1706
  protected resolveToolChoiceForTurn(params: ExecuteAgentParams): ChatToolChoice;
1544
1707
  /**
@@ -1861,6 +2024,11 @@ export declare class BaseAgent {
1861
2024
  * @returns Modified next step if guardrails exceeded, or original next step
1862
2025
  * @protected
1863
2026
  */
2027
+ private _selfCheckAttemptsByRun;
2028
+ private _selfCheckLinkByAgent;
2029
+ private applySelfCheck;
2030
+ /** Runs the self-check when a success exit did not pass through the guardrail hook. */
2031
+ private selfCheckSuccess;
1864
2032
  protected checkExecutionGuardrails<P>(params: ExecuteAgentParams, nextStep: BaseAgentNextStep<P>, currentPayload: P, agentRun: MJAIAgentRunEntityExtended, currentStep: MJAIAgentRunStepEntityExtended): Promise<BaseAgentNextStep<P>>;
1865
2033
  /**
1866
2034
  * Checks if any agent run guardrails have been exceeded.
@@ -2053,6 +2221,8 @@ export declare class BaseAgent {
2053
2221
  * @protected
2054
2222
  */
2055
2223
  protected processNextStep<P>(nextStep: BaseAgentNextStep<P>, params: ExecuteAgentParams, agentType: MJAIAgentTypeEntity, promptResult: AIPromptRunResult, currentPayload: P, currentStep: MJAIAgentRunStepEntityExtended): Promise<BaseAgentNextStep<P>>;
2224
+ /** The tool name the model used for a call on this turn — `payload_change_request` when it cannot be found. */
2225
+ private nativeToolNameForCall;
2056
2226
  /**
2057
2227
  * Executes a batch of artifact tool calls, recording each as its own
2058
2228
  * `Tool` AIAgentRunStep (a sibling of the Prompt step that requested them)
@@ -2303,6 +2473,171 @@ export declare class BaseAgent {
2303
2473
  * @protected
2304
2474
  */
2305
2475
  protected injectPipelineResultMessage(params: ExecuteAgentParams, result: PipelineExecutionResult): void;
2476
+ /** At most this many decision calls run at once for one agent turn. */
2477
+ private static readonly DECISION_CONCURRENCY;
2478
+ /**
2479
+ * Runs `fn` over `items` with at most `limit` calls in flight, keeping results in input order.
2480
+ * One call's failure never rejects the others: a call that throws is settled with `onError`'s
2481
+ * result in its place.
2482
+ */
2483
+ private runWithConcurrencyLimit;
2484
+ /**
2485
+ * Answers the decision requests from one agent turn, each logged as an `AIAgentRunStep`
2486
+ * (StepType 'Decision'), with bounded concurrency. A failed request never fails the run: it
2487
+ * becomes that request's `success: false`, which the agent reads on its next turn.
2488
+ *
2489
+ * Two limits bound the turn. At most `decisionsMaxRequests` requests run (default
2490
+ * {@link MAX_DECISION_REQUESTS_PER_TURN}); each request over that cap is not run and records no
2491
+ * step, and its result says why. And the requests make at most `decisionsMaxCallsPerTurn`
2492
+ * decision calls in total, counting every `forEachItemIn` item (default
2493
+ * {@link MAX_DECISION_CALLS_PER_TURN}). That budget is handed out in request order before any
2494
+ * call is made, so which calls run never depends on timing. A `forEachItemIn` request it cuts
2495
+ * short asks its first items and reports the rest in `skippedCount`. A request it leaves no calls
2496
+ * for is not run, records no step, and its result says why.
2497
+ *
2498
+ * @since 2.132.0
2499
+ */
2500
+ protected executeDecisionRequestsAsSteps(requests: AgentDecisionRequest[], finalPayload: unknown, agentTypePromptParams: Record<string, unknown> | undefined, params: ExecuteAgentParams): Promise<AgentDecisionResult[]>;
2501
+ /** The most decision requests one turn may run: `decisionsMaxRequests`, or {@link MAX_DECISION_REQUESTS_PER_TURN}. */
2502
+ private decisionRequestCap;
2503
+ /**
2504
+ * The most decision calls one turn's requests make in total, `forEachItemIn` items included:
2505
+ * `decisionsMaxCallsPerTurn`, or {@link MAX_DECISION_CALLS_PER_TURN}.
2506
+ */
2507
+ private decisionCallBudget;
2508
+ /** The most items one `forEachItemIn` request asks about: `decisionsMaxItems`, or its default. */
2509
+ private decisionMaxItems;
2510
+ /** A decision limit from the prompt params when it is a non-negative integer, or `fallback` when it is absent or anything else. */
2511
+ private decisionLimit;
2512
+ /**
2513
+ * Hands out the turn's decision-call budget to its requests in order, before any of them runs.
2514
+ * Each request gets the calls it wants while the budget lasts. The first one the budget cannot
2515
+ * cover gets what is left, and the ones after it get none.
2516
+ */
2517
+ private allotDecisionCalls;
2518
+ /**
2519
+ * The decision calls a request makes with no budget: one, or one per `forEachItemIn` item up to
2520
+ * `decisionsMaxItems`. A request that cannot make any, because it is not an object or its
2521
+ * `forEachItemIn` is not an array, wants none. A request that fails before it asks, such as one
2522
+ * with no valid question, still holds what its shape wants: the budget can then go unused, but
2523
+ * it is never exceeded.
2524
+ */
2525
+ private decisionCallsWanted;
2526
+ /**
2527
+ * The result of a request the turn's decision-call budget left no calls for. It was not run.
2528
+ * A budget of 0 turns decision calls off for the agent, so then asking again on a later turn
2529
+ * cannot help, and the result does not invite it.
2530
+ */
2531
+ private overBudgetDecisionResult;
2532
+ /** A request's id for its result, or its position when the model sent no usable id. */
2533
+ private decisionRequestId;
2534
+ /**
2535
+ * Runs a `'Decision'` next step: an agent type's decision requests, answered with no LLM turn.
2536
+ *
2537
+ * Each request goes through the same path a loop turn's decisions take
2538
+ * ({@link executeSingleDecisionRequestAsStep}), so it gets the same prompt default, state
2539
+ * resolution and error handling, and is logged as a `Decision` run step. Where a loop turn's
2540
+ * results go into the conversation, these come back to the agent type on the returned `'Retry'`
2541
+ * (`decisionResults`), because it routes on them. So each answer keeps its whole distribution
2542
+ * (`SummarizeDecisionAnswers`), which a path condition may read. A failed request is a result
2543
+ * with `success: false`, never a failed run: what a failure means is the agent type's call.
2544
+ *
2545
+ * @since 6.2.0
2546
+ */
2547
+ protected executeDecisionStep<P>(params: ExecuteAgentParams, decision: BaseAgentNextStep<P>): Promise<BaseAgentNextStep<P>>;
2548
+ /**
2549
+ * Answers one decision request, either once against its `state` or once per item of its
2550
+ * `forEachItemIn` array, and records it as a Decision step. The request is unchecked model
2551
+ * output, so any error finishes the step as failed rather than escaping: this never throws
2552
+ * once the step exists.
2553
+ *
2554
+ * @param callAllowance The most decision calls the request may make, from the turn's
2555
+ * `decisionsMaxCallsPerTurn` budget. It caps a `forEachItemIn` request's items below
2556
+ * `decisionsMaxItems`. A single-state request makes one call, and
2557
+ * {@link executeDecisionRequestsAsSteps} never starts one the budget left without it.
2558
+ * Unbounded by default.
2559
+ * @param summarize how the typed answers are summarised for whoever reads them next; defaults
2560
+ * to the loop turn's model-facing summary
2561
+ * @since 2.132.0
2562
+ */
2563
+ protected executeSingleDecisionRequestAsStep(request: AgentDecisionRequest, finalPayload: unknown, agentTypePromptParams: Record<string, unknown> | undefined, params: ExecuteAgentParams, callAllowance?: number, summarize?: DecisionAnswerSummarizer): Promise<AgentDecisionResult>;
2564
+ /** Asks the request's questions about one state, with the configured decision prompt. */
2565
+ private decisionAsker;
2566
+ /** Asks the questions once, against the request's state. */
2567
+ private askOnce;
2568
+ /**
2569
+ * Asks the same questions of each item of a payload array, up to `decisionsMaxItems` and the
2570
+ * request's share of the turn's call budget. Each item's call is its own child Decision step of
2571
+ * the request's step, carrying that call's prompt run, as each iteration of a ForEach is a child
2572
+ * step of its loop step.
2573
+ */
2574
+ private askForEachItem;
2575
+ /** Asks about one item of a `forEachItemIn` request, recorded as a child step of the request's step. */
2576
+ private askItemAsStep;
2577
+ /**
2578
+ * Links a decision call's prompt run to its step, as the Prompt step links its own, so the run's
2579
+ * cost and token totals and its `MaxCostPerRun` / `MaxTokensPerRun` checks count the call.
2580
+ */
2581
+ protected attachDecisionPromptRun(step: MJAIAgentRunStepEntityExtended, result: AIDecisionRunResult): void;
2582
+ /**
2583
+ * Links the prompt run of a decision call the run stopped waiting for (a timeout or a cancellation)
2584
+ * to its step, once the call settles. `AIDecisionRunner` writes the prompt run before it calls the
2585
+ * model, so a stopped call still has one. The link keeps that row on the run's trace, and counts its
2586
+ * usage in the run's cost and token totals when it settles before the run ends, as
2587
+ * {@link attachDecisionPromptRun} does on time. The step may already be finalized, so the link is
2588
+ * saved on its own. Never throws, and a call that never settles links nothing.
2589
+ */
2590
+ private linkLateDecisionPromptRun;
2591
+ /**
2592
+ * A literal state, or a value read from the payload: the whole payload for `payload`, one value
2593
+ * for a `payload.` path.
2594
+ */
2595
+ private resolveDecisionState;
2596
+ /** Reads a `payload.`-prefixed dotted path (or `payload` itself) from the payload. */
2597
+ private resolvePayloadPath;
2598
+ /** Strings pass through; anything else becomes indented JSON. */
2599
+ private decisionStateText;
2600
+ /** Finalizes the Decision step and builds the result the agent reads next turn. */
2601
+ private finishDecisionStep;
2602
+ /**
2603
+ * Answers the decision requests a prompt returned, or holds them when the step that carries
2604
+ * them can end the run, because then no turn would read their answers. Held requests run before
2605
+ * the next prompt ({@link runHeldDecisions}), or are skipped if the run ends first
2606
+ * ({@link skipHeldDecisions}). Skips them all, unasked, while the master switch is off
2607
+ * ({@link DecisionsEnabled}) or the agent's `decisions` response field is.
2608
+ */
2609
+ private processTurnDecisions;
2610
+ /**
2611
+ * Why the decisions sent with this step would be paid for and never read, or `undefined` when
2612
+ * the next turn reads them. Three ways a step's own outcome ends the run: a passing finishIf gate
2613
+ * (only an Actions step or a single sub-agent is gated), a sub-agent's `terminateAfter`, and
2614
+ * client tools sent with `taskComplete`, which end the run once the tools return. Every other
2615
+ * step, including client tools without `taskComplete`, goes on to a prompt that reads them.
2616
+ */
2617
+ private decisionsHoldReason;
2618
+ /**
2619
+ * Runs the decision requests a prompt held back, now that the step that carried them has run
2620
+ * without ending the run, so the prompt about to run reads their answers.
2621
+ */
2622
+ private runHeldDecisions;
2623
+ /**
2624
+ * Skips the decision requests a prompt held back, because the run ended before they could be
2625
+ * asked: the step that carried them ended it, or it was cancelled, or an error was thrown out of
2626
+ * the step loop. Called from the loop's terminate branch and from `Execute()`'s `finally`, so
2627
+ * every way out logs them. The held state is cleared before the log line, so the second call on
2628
+ * the terminate path logs nothing and each held request is logged exactly once.
2629
+ *
2630
+ * @param runEnd How the run ended, as a clause for the log line.
2631
+ */
2632
+ private skipHeldDecisions;
2633
+ /** How the run ended, as a clause for held decision requests that a cancellation or an error left unasked. */
2634
+ private runEndForHeldDecisions;
2635
+ /**
2636
+ * Injects decision results into the conversation as one tool-result message for the next turn.
2637
+ *
2638
+ * @since 2.132.0
2639
+ */
2640
+ protected injectDecisionResultsMessage(params: ExecuteAgentParams, results: AgentDecisionResult[]): void;
2306
2641
  /**
2307
2642
  * Creates a chat message containing sub-agent execution results.
2308
2643
  *
@@ -2332,6 +2667,52 @@ export declare class BaseAgent {
2332
2667
  * @private
2333
2668
  */
2334
2669
  private gatherPromptTemplateData;
2670
+ /**
2671
+ * Narrows the catalog once per run, on its first prompt (plan Task 3.7), and caches the result for
2672
+ * every later step. With narrowing off, or the master switch ({@link DecisionsEnabled}) off, it
2673
+ * asks nothing and records nothing, so the prompt describes the whole catalog. Never throws: any
2674
+ * failure leaves the full catalog in place. It narrows the prose catalog only:
2675
+ * {@link applyNativeTools} still declares every action and sub-agent.
2676
+ */
2677
+ private ensureCatalogNarrowing;
2678
+ /**
2679
+ * The run's limits, with actions left whole when the agent lacks Find Candidate Actions: a hidden
2680
+ * action would then be unreachable. That case is logged as a warning when it keeps a long action
2681
+ * list whole, since the agent asked for narrowing and did not get it.
2682
+ */
2683
+ private reachableCatalogNarrowingLimits;
2684
+ /**
2685
+ * Every item of the three lists as a narrowing candidate. An action or sub-agent with
2686
+ * `MinExecutionsPerRun` set, and the Find Candidate tools, are pinned: always shown.
2687
+ */
2688
+ private catalogNarrowingCandidates;
2689
+ /**
2690
+ * Asks the one decision, records it as the `Catalog narrowing` step, and returns what to hide.
2691
+ * Any failure is logged as a warning and hides nothing, so the prompt shows the full catalog.
2692
+ */
2693
+ private narrowCatalog;
2694
+ /**
2695
+ * The one decision call, against the opening request. Never throws, and never waits longer than
2696
+ * {@link CATALOG_NARROWING_TIMEOUT_MS} or past the run's cancellation: a throw, a timeout and a
2697
+ * cancelled run each come back as a failed result. Stopping also aborts the call, and links the
2698
+ * prompt run it still returns to `step` once it does ({@link linkLateDecisionPromptRun}).
2699
+ */
2700
+ private askCatalogNarrowing;
2701
+ /** Opens the `Catalog narrowing` Decision step with the decision's inputs. Without a run there is no step. */
2702
+ private startCatalogNarrowingStep;
2703
+ /** Finalizes the `Catalog narrowing` step: each narrowed list's counts, kept names and probabilities, or why it failed open. */
2704
+ private finishCatalogNarrowingStep;
2705
+ /** Logs that catalog narrowing failed open. */
2706
+ private warnCatalogNarrowing;
2707
+ /** The items of one list the prompt shows. Returns `items` itself when the run's narrowing hides none of them. */
2708
+ private hideNarrowedOut;
2709
+ /**
2710
+ * One catalog section as the prompt shows it: `full` when the run's narrowing hides none of
2711
+ * `items`, otherwise a {@link CatalogNarrowingNote} saying how many are hidden and how to reach
2712
+ * them, then the items still shown. A hidden item can still be called. Fails OPEN, unlike the
2713
+ * skill policy: an error shows `full` and logs a warning.
2714
+ */
2715
+ private narrowedCatalogSection;
2335
2716
  /**
2336
2717
  * Builds the agent-invariant {@link AgentBaseCatalog} — the resolved sub-agents + actions and
2337
2718
  * their formatted markdown, plus the base agent-type prompt params. Computed once per agent and
@@ -2372,6 +2753,40 @@ export declare class BaseAgent {
2372
2753
  * @since 2.131.0
2373
2754
  */
2374
2755
  protected buildAgentTypePromptParams(agentType: MJAIAgentTypeEntity | undefined, agent: MJAIAgentEntityExtended, runtimeOverrides?: Record<string, unknown>): Record<string, unknown>;
2756
+ /**
2757
+ * The agent and value pairs {@link warnOnceOnUnknownFinishIfMode} has already reported. It is
2758
+ * process-wide because the prompt params are merged again for every run of an agent, and on every
2759
+ * turn that carries runtime overrides. One warning per agent and value is enough. A run request
2760
+ * can set the value, so what this keeps is bounded: see {@link FinishIfModeWarnings}.
2761
+ */
2762
+ private static readonly finishIfModeWarnings;
2763
+ /**
2764
+ * Warns, once per agent and value, when the merged `finishIfMode` is set but is not a
2765
+ * {@link FinishIfMode}. {@link ResolveFinishIfMode} treats such a value as `'off'`, so without
2766
+ * this a typo such as `"On"` or `"true"` would turn the agent's gates off without a word. An
2767
+ * absent value is the default, so it is not reported.
2768
+ */
2769
+ private warnOnceOnUnknownFinishIfMode;
2770
+ /**
2771
+ * The master switch for decision-model use by this agent: `decisionsEnabled` in its merged
2772
+ * agent-type prompt params (type default < agent < the run's `data.__agentTypePromptParams`).
2773
+ * Anything but `true` is off, the default.
2774
+ *
2775
+ * While it is off the agent never asks a decision model on its own. Each automatic use checks it
2776
+ * before it asks, whatever its own setting says: inline `decisions` ({@link processTurnDecisions}),
2777
+ * `finishIf` gates ({@link finishIfSettings}), decision discovery ({@link isDecisionDiscoveryOnFor}),
2778
+ * the payload change check ({@link isPayloadFeedbackCheckOn}), catalog narrowing
2779
+ * ({@link ensureCatalogNarrowing}) and the Memory Manager's note gate. And
2780
+ * {@link applyResponseTypeAutoAlignment} keeps the `decisions` and `finishIf` docs and response
2781
+ * fields out of the prompt. While it is on, each use keeps its own setting, and each is off by default.
2782
+ *
2783
+ * Explicit uses never read it: a Flow agent's Decision step ({@link executeDecisionStep}) runs because
2784
+ * someone placed it, and the task-graph Decision step and the Run Decision action call
2785
+ * {@link AgentDecisionService} directly. That is why the check sits at each automatic use, not in the service.
2786
+ *
2787
+ * @param promptParams - The merged agent-type prompt params.
2788
+ */
2789
+ protected DecisionsEnabled(promptParams: Record<string, unknown> | undefined): boolean;
2375
2790
  /**
2376
2791
  * Applies auto-alignment rules to includeResponseTypeDefinition based on other flags.
2377
2792
  *
@@ -2385,6 +2800,10 @@ export declare class BaseAgent {
2385
2800
  * - includeCommandDocs → includeResponseTypeDefinition.commands
2386
2801
  * - includeForEachDocs → includeResponseTypeDefinition.forEach
2387
2802
  * - includeWhileDocs → includeResponseTypeDefinition.while
2803
+ * - includeDecisionsDocs → includeResponseTypeDefinition.decisions
2804
+ *
2805
+ * While the master switch is off ({@link DecisionsEnabled}), the decisions and finishIf docs and
2806
+ * response fields are off, even when set explicitly.
2388
2807
  *
2389
2808
  * @param params - The merged params object to modify in place
2390
2809
  * @param explicitResponseType - The explicitly set response type config from agent/runtime (not schema defaults)
@@ -2402,12 +2821,106 @@ export declare class BaseAgent {
2402
2821
  * @since 2.131.0
2403
2822
  */
2404
2823
  protected extractSchemaDefaults(schemaJson: string | null | undefined): Record<string, unknown>;
2824
+ /**
2825
+ * The finishIf settings of the current step, from its merged agent-type prompt params. A gate is
2826
+ * evaluated when the master switch is on ({@link DecisionsEnabled}), `finishIfMode` is `shadow` or
2827
+ * `on`, and `includeResponseTypeDefinition.finishIf` is not `false`; it ends the run only in `on`.
2828
+ */
2829
+ private finishIfSettings;
2830
+ /** Whether a passing finishIf gate ends the run: only in `on` mode. */
2831
+ private finishIfActs;
2832
+ /**
2833
+ * Whether an evaluated gate ends the run. In shadow mode a passing gate is only logged: the
2834
+ * outcome is already recorded on its `Finish check` step, and the model takes its next turn.
2835
+ */
2836
+ private gateEndsRun;
2837
+ /**
2838
+ * Runs the finishIf gate after an Actions step, and returns the Success step when it passes.
2839
+ * ForEach and While call executeActionsStep without a conversation message, and are never gated.
2840
+ */
2841
+ private finishAfterActions;
2842
+ /**
2843
+ * Runs the finishIf gate after a Sub-Agent step that succeeded without terminating, and returns
2844
+ * the step with `terminate: true` when it passes, as `terminateAfter` would.
2845
+ */
2846
+ private finishAfterSubAgent;
2847
+ /**
2848
+ * Asks the finishIf questions about the step's results, then checks that the normal Success
2849
+ * validation would allow the run to end. Records the check as a `Finish check` Decision step.
2850
+ * Never throws: any error means the gate did not pass, and the run continues as it would have.
2851
+ */
2852
+ private evaluateFinishIf;
2853
+ /**
2854
+ * Asks each finishIf question as a Likelihood. Every one must reach the threshold. The call's
2855
+ * prompt run is linked to the `Finish check` step, so the run's cost and tokens count it.
2856
+ */
2857
+ private askFinishIf;
2858
+ /**
2859
+ * Returns why the normal Success validation would refuse to end the run, or `undefined` when it
2860
+ * allows it. The check must not count as a validation retry, so the counters are restored:
2861
+ * otherwise a gate that keeps not passing could exhaust the retries and fail the run.
2862
+ */
2863
+ private finishIfValidationRefusal;
2864
+ /** The Success step a passing gate returns after actions, in the shape of the client-tools `terminateAfterExecution` branch. */
2865
+ private finishIfSuccessStep;
2866
+ /** Finalizes the `Finish check` step with the outcome. A failure to save it never affects the run. */
2867
+ private finalizeFinishCheckStep;
2868
+ /**
2869
+ * Whether the merged agent-type prompt params turn the payload change check on. It is off unless
2870
+ * the master switch ({@link DecisionsEnabled}) and `payloadFeedbackCheck` are both `true`.
2871
+ */
2872
+ private isPayloadFeedbackCheckOn;
2873
+ /**
2874
+ * Runs the payload change check ({@link checkPayloadChanges}) on a step's applied payload changes
2875
+ * when it applies: the analyzer flagged a change for feedback, the check is on
2876
+ * ({@link isPayloadFeedbackCheckOn}), and a turn will read the result. A step that ends the run
2877
+ * skips it: no call to pay for, and no message left in the conversation. Never throws.
2878
+ */
2879
+ private checkPayloadChangesWhenOn;
2880
+ /**
2881
+ * Whether the step ends the run, so no turn would read the payload change check's message: it
2882
+ * terminates, or it is a `Success` or `Chat` step, which hand the run back to the caller.
2883
+ */
2884
+ private stepEndsRun;
2885
+ /**
2886
+ * The payload change check. Asks whether each change the analyzer flagged was intended, as one
2887
+ * Likelihood per change in one decision call, and records it as a `Payload change check`
2888
+ * Decision step. The changes judged unintended are listed in a message for the agent's next
2889
+ * turn, which asks it to confirm or restore them.
2890
+ *
2891
+ * It never reverts or blocks a change: the agent decides. When the decision cannot answer,
2892
+ * every change is accepted, as it is with the check off. Never throws.
2893
+ */
2894
+ private checkPayloadChanges;
2895
+ /**
2896
+ * What the payload change check's decision reads: the agent's own reasoning for the step (from its
2897
+ * response, else from the step), its message, and the reasoning it gave with the change. The check
2898
+ * never runs on a `Chat` or `Success` step, so the message comes from the response alone.
2899
+ */
2900
+ private payloadFeedbackContext;
2901
+ /**
2902
+ * Finalizes the `Payload change check` step with each change's probability and outcome. The step
2903
+ * fails when no decision answered, and its error says why. A failure to save it never affects the run.
2904
+ */
2905
+ private finalizePayloadCheckStep;
2906
+ /** Adds the payload change check's message to the conversation, for the agent's next turn. */
2907
+ private injectPayloadCheckMessage;
2908
+ /**
2909
+ * The {@link AIPromptExecutionScope} of model work this run starts outside the agent's own turn —
2910
+ * summarizing a range, compacting a message or the conversation, decision calls (FinishIf,
2911
+ * discovery, catalog narrowing, decision requests, the payload change check) and self-check
2912
+ * rubrics. Each built its params with only `contextUser`, so it ran on the platform's keys and
2913
+ * default configuration inside a run on a customer's keys, and under a `'RuntimeOnly'` scope
2914
+ * would have bypassed it.
2915
+ */
2916
+ private runPromptExecutionScope;
2405
2917
  /**
2406
2918
  * Whether THIS action may use the run's runtime API key for THIS driver class. The default is
2407
2919
  * yes: the run was started on those keys, and an action that calls a vendor on the user's behalf
2408
2920
  * (Generate Image) is doing what the prompts do. Override to narrow it — an agent that knows
2409
2921
  * which of its actions talk to which vendor can refuse everything else, and a refusal costs the
2410
2922
  * action nothing but the customer's key: it falls back to the platform key as if the run had none.
2923
+ * Under a `'RuntimeOnly'` credential scope a refusal leaves the action with no key for that class.
2411
2924
  */
2412
2925
  protected actionMayUseRuntimeAPIKey(action: MJActionEntityExtended, driverClass: string, params: ExecuteAgentParams): boolean;
2413
2926
  /**
@@ -3023,8 +3536,10 @@ export declare class BaseAgent {
3023
3536
  * by one in-flight sub-agent would race the others' reads.
3024
3537
  *
3025
3538
  * Uses `structuredClone` (Node 17+) where available; falls back to a JSON
3026
- * round-trip for environments without it. Returns the original value on
3027
- * non-cloneable inputs.
3539
+ * round-trip (`ToPlainJSON`) for environments without it AND when
3540
+ * `structuredClone` throws (a Proxy such as a live JSONType `<Field>Object`
3541
+ * view, or functions). Returns the original value — with an error logged —
3542
+ * only when even the JSON clone fails.
3028
3543
  *
3029
3544
  * **JSON fallback caveats** — the round-trip is *not* shape-preserving:
3030
3545
  * - `Date` → ISO string
@@ -3282,6 +3797,8 @@ export declare class BaseAgent {
3282
3797
  * them calls this after MJ's gates
3283
3798
  * (AcceptsSkills, Status, agent grant, user Run permission, the ActivationMode double gate) and
3284
3799
  * before anything activates. The default is the identity: MJ's gates are the whole policy.
3800
+ * Catalog narrowing (plan Task 3.7) is not part of this policy: it runs after it, at the catalog
3801
+ * site, and only hides skills from the prompt. An override never needs to call `super` for it.
3285
3802
  *
3286
3803
  * Override it to layer a policy MJ has no table for — a tenant licensing model, a per-organization
3287
3804
  * entitlement, a feature flag — and it applies everywhere at once. Without this seam a subclass