Member Junction
    Preparing search index...

    The Harness agent type — an MJ agent whose reasoning is supplied by an external agent harness.

    A harness turn is protocol-identical to a Loop agent's prompt iteration. The harness reasons, then ends its turn by emitting the same next-step JSON envelope a Loop model emits. Everything downstream of that decision — validateActionsNextStep, validateSubAgentNextStep, per-action MaxExecutionsPerRun, skill activation gates, plan-mode blocking, PayloadManager path ACLs, checkExecutionGuardrails between iterations, run-step recording — is already written and already correct.

    Inheriting DetermineNextStep wholesale is therefore not a shortcut, it is the entire point: it means a harness agent runs inside MJ's enforcement stack rather than beside it, with no second authority path to audit. An independent implementation would have to re-derive every one of those guarantees and would drift from the Loop path the first time either changed.

    ClassFactory registrations are namespaced per base class, so the string 'HarnessAgentType' is registered TWICE against different roots:

    · here, under BaseAgentType — resolved by BaseAgentType.GetAgentTypeInstance from AIAgentType.DriverClass, giving the turn-protocol behaviour; · in HarnessAgentBase, under BaseAgent — resolved by AgentRunner from the same column, giving the execution driver that substitutes a harness turn for a prompt call.

    That is the mechanism working as designed rather than an overload: AgentRunner already treats the agent type's DriverClass as a BaseAgent key and falls back to plain BaseAgent when the key is unregistered there, which is exactly why every Loop agent gets the base execution class today. Registering both makes one metadata column select both halves.

    The subtlety is worth stating because it is invisible at each registration site on its own: seeing only this file, a reader would reasonably assume 'HarnessAgentType' names one class.

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    _jsonValidator: JSONValidator

    JSON validator instance for cleaning and validating responses

    CURRENT_PAYLOAD_PLACEHOLDER: "_CURRENT_PAYLOAD"

    Common placeholder for current payload injection

    Accessors

    • get InjectLoopResultsAsMessage(): boolean

      Determines if loop results should be injected as a temporary user message before the next prompt execution (for LLM reasoning).

      Default: true (most agent types benefit from seeing loop results) Flow agents override to false (deterministic path navigation, no LLM)

      Returns boolean

      true to inject results as message, false to skip

      2.112.0

    • get RequiresAgentLevelPrompts(): boolean

      Indicates whether this agent type requires agent-level prompts (AI Agent Prompts relationship).

      Some agent types (like Flow) use step-level prompts exclusively and don't need agent-level prompts. Other agent types (like Loop) require agent-level prompts for their main reasoning loop.

      Default: true (most agent types require agent-level prompts)

      Returns boolean

      True if agent-level prompts are required, false if optional

      2.113.0

    • get SupportsNativeToolCalls(): boolean

      The Loop type reads tool calls back as Actions steps (§8.1), so its Actions may be declared as tools.

      Returns boolean

    Methods

    • Called after each loop iteration completes to process results.

      Flow agents use this to apply ActionOutputMapping and update payload. Loop agents typically don't need this (just collect results).

      Type Parameters

      • P

      Parameters

      • iterationResult: {
            actionResults?: ActionResult[];
            currentPayload: P;
            index: number;
            item: any;
            itemVariable: string;
            loopContext: any;
            subAgentResult?: any;
        }

        Results from this iteration

      Returns P

      Modified payload or null for default behavior (just collect result)

      2.112.0

    • Called before each loop iteration to prepare parameters and payload.

      Loop agents use this to resolve template variables ("item.email"). Flow agents typically don't need this (params already resolved).

      Type Parameters

      • P

      Parameters

      • context: {
            actionParams: Record<string, unknown>;
            index: number;
            item: any;
            itemVariable: string;
            loopType: "ForEach" | "While";
            payload: P;
            subAgentRequest?: {
                message: string;
                name: string;
                templateParameters?: Record<string, string>;
            };
        }

        Current iteration context

      Returns {
          actionParams?: Record<string, unknown>;
          payload?: P;
          subAgentRequest?: {
              message: string;
              name: string;
              templateParameters?: Record<string, string>;
          };
      }

      Modified context or null for default behavior

      2.112.0

    • Protected

      Creates a standardized next step object with common defaults

      Type Parameters

      • P

        The payload type

      Parameters

      • step:
            | "Failed"
            | "Actions"
            | "Chat"
            | "ForEach"
            | "Retry"
            | "Sub-Agent"
            | "Success"
            | "While"

        The step type

      • Optionaloptions: Partial<BaseAgentNextStep<P>>

        Additional options to merge

      Returns BaseAgentNextStep<P>

      The next step object

    • Analyzes the output from prompt execution to determine the next step.

      This method is called after the hierarchical prompts have been executed and should parse the LLM's response to determine what the agent should do next. The implementation depends on the specific agent type's logic and the format of output expected from its system prompt.

      Type Parameters

      • P = any
      • ATS = any

      Parameters

      Returns Promise<BaseAgentNextStep<P>>

      The determined next step and optional return value

      public async DetermineNextStep(): Promise<BaseAgentNextStep> {
      // Implementation might parse JSON output from LLM
      const response = JSON.parse(this.lastExecutionResult);

      if (response.taskComplete) {
      return { step: 'success', payload: response.payload };
      } else if (response.needsSubAgent) {
      return { step: 'subagent', payload: response.subAgentConfig };
      } else {
      return { step: 'action', payload: response.nextAction };
      }
      }
    • Provides agent-type-specific guidance for configuration errors related to missing prompts. This allows each agent type to give contextual help based on its architecture.

      Default implementation provides generic guidance. Agent types should override to provide specific instructions relevant to their configuration requirements.

      Returns string

      Configuration guidance specific to this agent type

      2.113.0

    • Determines how to handle Success or Failed steps when no explicit termination is requested.

      This allows agent types to control their own fallback behavior:

      • Loop agents use default behavior (return null) to process results with their main prompt
      • Flow agents should terminate instead of falling back to prompts (return terminate step)
      • Pipeline agents might want to move to the next stage

      Default implementation returns null, which causes base-agent to fall back to prompt execution if prompts are configured. Agent types can override this to provide custom behavior.

      Type Parameters

      • P = any
      • ATS = any

      Parameters

      Returns Promise<BaseAgentNextStep<P>>

      Custom step to execute, or null for default behavior

      2.113.0

    • This method allows each agent type to initialize its agent-run-specific state package as required. Not all agent types require this and are able to live off just the current payload or other properties passed to them to DetermineNextStep(), but some require more complex internal state tracking.

      Type Parameters

      • ATS = any
      • P = any

      Parameters

      Returns Promise<ATS>

      the fully initialized initial agent-type state

    • Injects a payload into the prompt parameters. For LoopAgentType, this could be used to inject previous loop results or context.

      Type Parameters

      • T = any
      • ATS = any

      Parameters

      • payload: T

        The payload to inject

      • agentTypeState: ATS
      • prompt: AIPromptParams

        The prompt parameters to update

      • agentInfo: { agentId: string; agentRunId?: string }

        Agent identification info (unused by LoopAgentType)

      Returns Promise<void>

    • Protected

      Validates that the response conforms to the expected LoopAgentResponse structure.

      Parameters

      • simpleResponse: unknown

      Returns { message?: string; success: boolean }

      True if the response is valid, false otherwise

    • Turns native tool calls on the turn into an Actions step, or returns null when there were none (the envelope path).

      Resolution is by the reverse map rather than by re-sanitizing names, because sanitization is lossy: two Action names can collapse to one tool name, which buildActionToolSet rejects at build time precisely so this lookup can be exact.

      A call naming a tool that was never declared is a Retry, not a silent drop. Cerebras is documented to do this, measured at roughly one forced call in six, so the loop has to be able to say "that tool does not exist" rather than appear to hang.

      Parameters

      Returns BaseAgentNextStep

    • Post-processes the result of action execution.

      This method is called by BaseAgent after action(s) have been executed. Agent types can override this method to perform custom processing of action results, such as mapping output parameters to the payload or storing results in agent-specific context.

      Type Parameters

      • P = any
      • ATS = any

      Parameters

      • actionResults: ActionResult[]

        The results from action execution

      • actions: AgentAction[]

        The actions that were executed

      • currentPayload: P

        The current payload

      • agentTypeState: ATS
      • currentStep: BaseAgentNextStep<P>

        The current step being executed

      Returns Promise<AgentPayloadChangeRequest<P>>

      Optional payload change request

      2.76.0

    • Post-processes the result of sub-agent execution.

      This method is called by BaseAgent after a sub-agent has been executed. Agent types can override this method to perform custom processing of sub-agent results, such as extracting specific data from the sub-agent's payload or updating context.

      Type Parameters

      • P = any
      • ATS = any

      Parameters

      • subAgentResult: any

        The result from sub-agent execution

      • subAgentRequest: AgentSubAgentRequest

        The sub-agent request that was executed

      • currentPayload: P

        The current payload

      • agentTypeState: ATS
      • currentStep: BaseAgentNextStep<P>

        The current step being executed

      Returns Promise<AgentPayloadChangeRequest<P>>

      Optional payload change request

      2.76.0

    • Pre-processes action parameters to resolve conversation references.

      Loop agents get action parameters directly from the LLM's JSON response. This method resolves any "conversation.*" references in those parameters before the actions are executed.

      Type Parameters

      • P = any
      • ATS = any

      Parameters

      • actions: AgentAction[]

        The actions that will be executed (modified in place)

      • currentPayload: P

        The current payload

      • agentTypeState: ATS

        The agent type state

      • currentStep: BaseAgentNextStep<P>

        The current step being executed

      • Optionalparams: ExecuteAgentParams<P>

        The execution parameters with conversation messages

      Returns Promise<void>

      Actions are modified in place

      2.120.0

    • Removes a markdown code fence WRAPPING an entire response, if one is present.

      Models fenced their JSON long before this existed — the retry feedback in LoopAgentType already tells them not to — but a retry costs a whole turn to recover something we already received intact. Observed with an external harness: the response was perfectly valid {"taskComplete": true, ...} inside a ```json fence, rejected by JSON.parse, and the identical answer came back on the retry. Half the latency and half the cost of that run bought nothing.

      It strips ONLY the first line and the trailing fence, never anything interior. A response's own payload frequently contains fenced code — the case that prompted this had ```haskell blocks inside its message string — so a global strip would corrupt exactly the responses it was meant to rescue.

      The stripped text is only used if it PARSES. On failure the original is returned untouched, so the outcome is either "an unparseable response became parseable" or "no change" — never a previously-good response turned bad. Deterministic, no model call, microseconds.

      Parameters

      • raw: string

      Returns string

    • Protected

      Instantiates an agent type class using a specific driver class name.

      This method is used when an individual agent has its own DriverClass override, allowing for specialized implementations per agent instance.

      Parameters

      • driverClass: string

        The driver class name to instantiate

      Returns Promise<BaseAgentType>

      Instance of the agent type class

    • Protected

      Instantiates the appropriate agent type class based on the agent type entity.

      This method uses the MemberJunction class factory to dynamically instantiate agent type classes. It uses the DriverClass field. If DriverClass is not specified it throws an error.

      Parameters

      Returns Promise<BaseAgentType>

      Instance of the agent type class

      // For an agent type with DriverClass "LoopAgentType"
      const agentTypeInstance = await this.getAgentTypeInstance(loopAgentType);

      @protected
    • Helper method that retrieves an instance of the agent type based on the provided agent type entity.

      This method uses the ClassFactory to create an instance of the agent type class specified in the DriverClass field of the agent type entity. If the DriverClass is not specified, it throws an error.

      Parameters

      Returns Promise<BaseAgentType>

      An instance of the agent type class

      GetAgentTypeInstance

      If the agent type does not have a DriverClass specified or if instantiation fails