Member Junction
    Preparing search index...

    Implementation of the Flow Agent Type pattern.

    This agent type enables deterministic workflow execution where agents follow predefined paths through a graph of steps. Key features:

    • Graph-based workflow definition
    • Conditional path evaluation using safe boolean expressions
    • Support for Actions, Sub-Agents, and Prompts as step types
    • Deterministic execution with optional AI-driven decision points

    Two ways to run. A top-level run compiles the flow to a task graph and hands it to the durable task-graph dispatcher. A run whose caller needs the result (a sub-agent run, or a caller that sets agentTypeParams.executionMode = 'inRun') walks the flow in this process and returns the final payload. See FlowExecutionMode.

    FlowAgentType

    // Flow agents execute steps based on graph structure
    const flowAgent = new FlowAgentType();
    const nextStep = await flowAgent.DetermineNextStep(promptResult, payload);

    // Steps are determined by evaluating path conditions
    // Path: "payload.status == 'approved' && payload.amount < 1000"
    // Leads to: "Auto-Approve" step

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    _jsonValidator: JSONValidator = ...

    JSON validator instance for cleaning and validating responses

    CURRENT_PAYLOAD_PLACEHOLDER: "_CURRENT_PAYLOAD" = CURRENT_PAYLOAD_PLACEHOLDER

    Common placeholder for current payload injection

    Accessors

    • 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

    • get UsesActionCircuitBreaker(): boolean

      Flow action nodes are chosen by the graph, not by a model: failure paths may re-run a node with the same mapped inputs, and no model reads a failure directive. The breaker's rules would only block those retries, so Flow opts out (see BaseAgentType.UsesActionCircuitBreaker).

      Returns boolean

    Methods

    • Flow agents apply ActionOutputMapping after each iteration

      Type Parameters

      • P

      Parameters

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

      Returns P

    • 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

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

        Additional options to merge

      Returns BaseAgentNextStep<P>

      The next step object

    • Decides where this flow runs, records the decision, and returns its first step.

      The rule: a run that needs the flow's result runs in-process; everything else is dispatched. A dispatched flow submits a task graph and returns before any step has run. That is right for a person starting a workflow, and wrong for anything that consumes the result: a parent agent, or an API handler answering its client. Those callers get the in-run walker, which returns the flow's final payload. See FlowExecutionMode.

      The decision is made once, here, and stored on the run's FlowExecutionState. Every later hook reads it, and BaseAgent records it on the run through DescribeExecutionRouting.

      Type Parameters

      • P = any
      • ATS = any

      Parameters

      Returns Promise<BaseAgentNextStep<P>>

      The first in-run step, or the Tasks step carrying the compiled graph

      2.76.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