Member Junction
    Preparing search index...

    Implementation of the Realtime Agent Type pattern.

    A first-class peer of Loop and Flow that drives a BaseRealtimeModel session rather than an iterative reasoning loop. Because it is a real MJ agent type, an agent of this type inherits the entire framework for free: server tools (actions), client tools, artifacts, prompts, memory, permissions, and observability. The first agent shipped of this type is the Realtime Co-Agent, which voices on behalf of a target agent.

    Execution branch. The realtime path is session-driven: BaseAgent (in a later task) will detect IsSessionDriven (or instanceof RealtimeAgentType) and hand control to a RealtimeSessionRunner rather than entering the loop. As a consequence, the loop-oriented abstract methods below are implemented defensively — they should never be reached in normal operation.

    RealtimeAgentType

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    _jsonValidator: JSONValidator = ...

    JSON validator instance for cleaning and validating responses

    CURRENT_PAYLOAD_PLACEHOLDER: "_CURRENT_PAYLOAD" = '_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 IsSessionDriven(): boolean

      Marks this agent type as session-driven rather than loop-driven.

      BaseAgent will use this getter (added on this subclass; base-agent-type.ts is left untouched in this task) to branch into a RealtimeSessionRunner instead of the iterative reasoning loop. Other agent types do not expose this member; BaseAgent should treat its absence as false, or equivalently detect this type via instanceof RealtimeAgentType.

      Returns boolean

      Always true — realtime agents are driven by a long-lived duplex session.

    • get RequiresAgentLevelPrompts(): boolean

      Realtime agents drive their conversation through a live model session, not through agent-level loop prompts. The companion/system prompt is supplied to the realtime model at session start, so the agent-level prompt relationship is not required.

      Returns boolean

      Always false — agent-level loop prompts are not required for realtime agents.

    • get SupportsNativeToolCalls(): boolean

      Whether this agent type can read a native tool call back as a step (plan §8.1).

      BaseAgent declares an agent's Actions as native tools ONLY when this is true. Declaring them to a type that cannot consume the call is not harmless: the model answers with a tool call and no text, the type's DetermineNextStep parses the empty text, and the turn becomes a Retry — a run that would have worked on the envelope path fails because tools were offered. That is exactly the failure a catalog-wide DefaultToNativeToolCalling would have produced on every Flow agent with Actions.

      Defaults to false. A type opts in by overriding this AND by honouring the nativeToolBindings argument of DetermineNextStep; the two go together, and LoopAgentType is the only type that does both today.

      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:
            | "Actions"
            | "Chat"
            | "Failed"
            | "ForEach"
            | "Retry"
            | "Sub-Agent"
            | "Success"
            | "While"

        The step type

      • options: Partial<BaseAgentNextStep<P>> = {}

        Additional options to merge

      Returns BaseAgentNextStep<P>

      The next step object

    • 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

    • Injects a payload into a prompt.

      Realtime conversations are not driven by loop prompts, so there is no per-turn payload to inject. This is a no-op (defensive against a mis-wired caller), in contrast to LoopAgentType.InjectPayload which injects the current payload into the loop prompt.

      Type Parameters

      • P = any
      • ATS = any

      Parameters

      • payload: P

        The payload to inject (unused).

      • agentTypeState: ATS

        The agent-type state (unused).

      • prompt: AIPromptParams

        The prompt parameters (unused).

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

        Agent identification info (unused).

      Returns Promise<void>

    • 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