Skip to content

Latest commit

 

History

History
448 lines (308 loc) · 17.8 KB

File metadata and controls

448 lines (308 loc) · 17.8 KB

Workflow authoring API reference

Generated by pnpm docs:authoring from public declarations and TSDoc in src/flow. Do not edit directly.

For the guided introduction, see Authoring workflows.

Steps

CreateAgentStepOptions

interface CreateAgentStepOptions<TInputSchema extends TSchema | undefined, TOutputSchema extends TSchema> { name: string description?: string input?: TInputSchema output?: TOutputSchema model?: string prompt: (args: AgentPromptArgs<InferInput<TInputSchema>>) => string asks?: boolean retry?: RetryPolicy maxOutputRepairs?: number maxDurationMs?: number | ((args: { ctx: RunContext }) => number) optional?: boolean maxTokens?: number background?: boolean resumable?: boolean | string | ((args: { ctx: RunContext }) => string) }

Agent-step configuration, including model selection, output repair, budgets, isolation, and resumability.

Remarks: An acting agent omits output. A reporting agent declares output; an asking agent additionally sets asks: true. Asking cannot be combined with background. Static resumable keys cannot be shared by executions that may overlap.

createAgentStep

createAgentStep<TInputSchema extends TSchema | undefined = undefined, TOutputSchema extends TSchema = TSchema>(options: CreateAgentStepOptions<TInputSchema, TOutputSchema>): AgentStep

Creates an agent step that acts, reports structured output, or interactively asks for information.

Remarks: Omit output for an acting step whose result is its side effects. Declare output for a reporting step; the agent must call workflow_submit_result with a matching value. Add asks: true when it may submit questionnaire batches before its result. Never combine asks: true with background: true.

Example: ```ts const review = createAgentStep({ name: "review", input: changeSchema, output: reviewSchema, prompt: ({ input }) => Review ${input.path}, })


### `CreateQuestionnaireStepOptions`

```ts
interface CreateQuestionnaireStepOptions<TOutputSchema extends TSchema> { name: string description?: string output: TOutputSchema questionnaire?: Questionnaire }

Configuration for deterministic, schema-driven user input collection.

createQuestionnaireStep

createQuestionnaireStep<TOutputSchema extends TSchema>(options: CreateQuestionnaireStepOptions<TOutputSchema>): QuestionnaireStep

Questionnaire step (spec §2.4): collect structured input to satisfy an annotated target output schema. Deterministic and LLM-free — the framework derives a questionnaire from output (or uses the questionnaire override), blocks with it, and on answers reassembles + validates them into output.

For elicitation — an agent that composes and re-batches questions until it can satisfy output — use createAgentStep({ asks: true }) instead.

Example: ```ts const collectTarget = createQuestionnaireStep({ name: "collect-target", output: Type.Object({ environment: Type.String({ title: "Environment" }) }), })


### `CreateStepOptions`

```ts
interface CreateStepOptions<TInputSchema extends TSchema | undefined = undefined, TOutputSchema extends TSchema | undefined = undefined> { name: string description?: string input?: TInputSchema output?: TOutputSchema retry?: RetryPolicy maxDurationMs?: number | ((args: { ctx: RunContext }) => number) optional?: boolean run: StepRunFn<InferInput<TInputSchema>, InferOutput<TOutputSchema>> }

Configuration shared by a function step, including retry, duration, and optional-failure controls.

Remarks: retry.maxRetry counts attempts after the first. optional should only be used when downstream nodes do not require this step's output, because a final failure produces undefined.

createStep

createStep<TInputSchema extends TSchema | undefined = undefined, TOutputSchema extends TSchema | undefined = undefined>(options: CreateStepOptions<TInputSchema, TOutputSchema>): FunctionStep

Creates a TypeScript function step whose input and output types are inferred from its TypeBox schemas.

Remarks: The engine validates input before calling run and validates the returned value against output. The callback may use ctx for earlier results, abortSignal for cancellation, and logger for structured run-log messages.

Example: ```ts const summarize = createStep({ name: "summarize", input: Type.Array(Type.String()), output: Type.String(), run: ({ input }) => input.join("\n"), })


## Data Flow

### `ScopeFrame`

```ts
interface ScopeFrame { readonly kind: "loop" | "foreach" | "branch-arm" | "parallel" | "workflow" readonly name: string readonly iteration?: number readonly itemIndex?: number readonly itemCount?: number readonly input: unknown }

One enclosing construct's position and input, exposed through RunContext.scope (iteration-context spec, Feature 1). Values are pure data derived from the engine's walk state: deterministic, identical on resume (rebuilt as re-entry descends), and identical regardless of concurrency interleaving. Retry attempt is deliberately NOT here (spec 1.5): loop iteration and retry attempt are different axes, and conflating them would invite resume keys that fork per retry.

RunContext.scope

RunContext.scope(name?: string): ScopeFrame | undefined

The enclosing construct frames (iteration-context spec 1.2/1.6). Called with no argument it returns the NEAREST enclosing frame; called with a construct name it walks outward to that construct (a nested loop-in-foreach is addressable by name, not just the innermost). Returns undefined at the top level, or when no enclosing construct carries the given name.

RunContext.getStepResult

RunContext.getStepResult<T = unknown>(stepName: string): T | undefined

Look up a prior step's or construct's output by its BARE name (names-only addressing, spec 4.1) — resolved lexically to the nearest enclosing scope that declares it, walking outward from the calling step's own scope to the root. A declared name whose step has not been reached, or was skipped, reads undefined — a structural fact, not an error. A name NO enclosing scope declares THROWS (a provable wiring bug, spec 4.2), as does any argument carrying path syntax (/, #, @) — the path form was removed outright. Paths remain identity in the event log and resume addressing; they are no longer an authoring query language.

RunContext.getInitData

RunContext.getInitData<T = unknown>(): T | undefined

The workflow's initial input, or undefined when the workflow has no input schema.

CreateWorkflowOptions

interface CreateWorkflowOptions<TInputSchema extends TSchema | undefined = undefined> { name: string description?: string input?: TInputSchema defaultModel?: string maxConcurrency?: number }

Root workflow configuration. The optional TypeBox input schema validates initial run data and infers its author-facing type; maxConcurrency defaults to 4.

WorkflowBuilder.then

WorkflowBuilder.then(step: StepDefinition): WorkflowBuilder

Append a step node in sequence. Its input is the previous node's output and is validated against the step's input schema.

WorkflowBuilder.commit

WorkflowBuilder.commit(): WorkflowDefinition

Finalize and validate the workflow definition.

createWorkflow

createWorkflow<TInputSchema extends TSchema | undefined = undefined>(options: CreateWorkflowOptions<TInputSchema>): WorkflowBuilder

Starts a fluent workflow definition and returns its builder. Append at least one node and call .commit() to obtain a loadable WorkflowDefinition.

Remarks: Linear hand-off passes every node's output to the next node. Use ctx.getStepResult() for a non-adjacent result, ctx.getInitData() for the root input, and ctx.scope() for enclosing loop/foreach/branch/parallel input. Node names must be unique and cannot contain /, #, or @.

Example: ```ts export default createWorkflow({ name: "review", input: requestSchema }) .then(loadRequest) .then(reviewRequest) .commit()


Throws: If the workflow is empty, names are invalid or duplicated, concurrency exceeds its ceiling,
or incompatible execution options are combined.

## Map

### `MapFn`

```ts
type MapFn<TOutput = unknown> = (ctx: RunContext) => TOutput

A .map() transform (spec §3.7): derives the next step's input purely from the run context — prior step outputs (getStepResult) and workflow init data (getInitData). Pure and deterministic; it has no host, network, or LLM access beyond ctx. The returned value is validated by the downstream step's input schema, so a map declares no schema of its own.

MapOptions

interface MapOptions { name?: string }

Options for a .map() construct.

WorkflowBuilder.map

WorkflowBuilder.map(transform: MapFn, options?: MapOptions): WorkflowBuilder

Insert a pure transform whose result becomes the next node's input via the linear hand-off (spec §3.7). Reads earlier, non-adjacent outputs via ctx.getStepResult / ctx.getInitData.

Loop

LoopCondition

type LoopCondition = (ctx: RunContext, lastOutput: unknown) => boolean

A pure loop predicate (spec §3.3) over the run context and the body's most recent output. lastOutput is the RAW body output (loop-feedback spec 2.4): it may be undefined when the round produced nothing (a failed optional tail) even though the fed-back value passes through defined — a predicate may legitimately need to know the round came up empty. The fed value itself is readable as ctx.scope(loopName)?.input.

LoopOptions

interface LoopOptions { name?: string maxIterations?: number }

Options shared by .dowhile() and .dountil(); maxIterations defaults to 100.

WorkflowBuilder.dowhile

WorkflowBuilder.dowhile(body: WorkflowDefinition, condition: LoopCondition, options?: LoopOptions): WorkflowBuilder

Loop (spec §3.3): run body, then repeat while condition holds.

Feedback (loop-feedback spec, Feature 2): each iteration's body receives the PREVIOUS iteration's body output as its input — the first iteration receives the value flowing into the loop from upstream. It is ordinary, schema-validated step I/O, so the body's input and output schemas must agree (checked at .commit() where both are declared). An iteration that produces no output (a failed optional tail) passes its input through unchanged, and the loop's own output is the final effective value — readable downstream by the loop's bare name.

WorkflowBuilder.dountil

WorkflowBuilder.dountil(body: WorkflowDefinition, condition: LoopCondition, options?: LoopOptions): WorkflowBuilder

Run body, then repeat until condition holds. Feedback follows WorkflowBuilder.dowhile.

Foreach

ForeachSelector

type ForeachSelector = (ctx: RunContext) => readonly unknown[]

A pure item selector for a foreach (spec §3.4): derives the collection to iterate from the run context. Must be side-effect-free and deterministic — a resume re-runs it and relies on it yielding the same array so recorded per-item outputs line up by index.

ForeachOptions

interface ForeachOptions { name?: string concurrency?: number feedback?: boolean }

Options for .foreach(); concurrency defaults to 1. Feedback threads each body's output into the next item and therefore requires concurrency: 1; the current item remains available through ctx.scope(foreachName)?.input.

WorkflowBuilder.foreach

WorkflowBuilder.foreach(body: WorkflowDefinition, selector: ForeachSelector, options?: ForeachOptions): WorkflowBuilder

Foreach (spec §3.4): run body once per item selected by selector (pure), with the item as the body's input. options.concurrency (default 1) bounds how many items run at once. Output is the array of per-item outputs, in item order — independent of completion order.

Author contract (spec §8.3, "non-overlapping side effects"): at concurrency > 1, items run genuinely concurrently — the engine does not, and cannot, know what a step or its subagent will touch, so it enforces nothing here. Give each item's body its own files/branches/external resources; anything shared across items (two agents editing the same file, say) must be sequenced — either keep concurrency at 1, or restructure so the shared resource is touched outside the fan-out.

Parallel

ParallelOptions

interface ParallelOptions { name?: string }

Options for a .parallel() construct.

WorkflowBuilder.parallel

WorkflowBuilder.parallel(arms: readonly StepDefinition[], options?: ParallelOptions): WorkflowBuilder

Parallel (spec §3.5): structural fan-out over independent STEPS — every arm runs concurrently against the same input, bounded only by the workflow ceiling (spec §3.6). Output is an object keyed by each arm's own step name, independent of completion order.

Author contract (spec §8.3, "non-overlapping side effects"): every arm runs genuinely concurrently — the same rule as .foreach's doc above applies per arm here: no two arms may touch the same file, branch, or external resource, since the engine has no way to detect or prevent two concurrent agents rewriting the same working-tree state. Sequence anything that shares state with .then() instead of putting it in the same .parallel([...]).

Branch

BranchCondition

type BranchCondition = (ctx: RunContext) => boolean

A pure branch predicate over the run context; it must be side-effect-free to keep transitions deterministic.

BranchOptions

interface BranchOptions { name?: string }

Options for a .branch() construct.

BranchArmSpec

type BranchArmSpec = readonly [BranchCondition, WorkflowDefinition]

One .branch() arm: a pure condition paired with the committed sub-workflow to run when it holds.

WorkflowBuilder.branch

WorkflowBuilder.branch(arms: readonly BranchArmSpec[], options?: BranchOptions): WorkflowBuilder

Multi-match branch (spec §3.2): every arm whose condition holds runs sequentially; the node's output is an object keyed by the executed arm names (each arm name is its body's workflow name).

Workflow

NestedWorkflowOptions

interface NestedWorkflowOptions { name?: string }

Options for a .workflow() nested-workflow construct.

WorkflowBuilder.workflow

WorkflowBuilder.workflow(subWorkflow: WorkflowDefinition, options?: NestedWorkflowOptions): WorkflowBuilder

Nested workflow (spec §2.3/§11): run a committed sub-workflow's nodes here, transparently folding into the parent run/log. Output is the sub-workflow's final output. Every step/node name must be unique across the flattened tree, so nesting the same sub-workflow twice is a commit() error.

Advanced Agent

RetryPolicy

interface RetryPolicy { readonly maxRetry: number readonly backoffMs?: number }

Unified repeat policy for a step (spec §9.1). Covers thrown errors and invalid output uniformly; an input-schema violation is a deterministic wiring failure and is never retried.

CreateAgentStepOptions

interface CreateAgentStepOptions<TInputSchema extends TSchema | undefined, TOutputSchema extends TSchema> { name: string description?: string input?: TInputSchema output?: TOutputSchema model?: string prompt: (args: AgentPromptArgs<InferInput<TInputSchema>>) => string asks?: boolean retry?: RetryPolicy maxOutputRepairs?: number maxDurationMs?: number | ((args: { ctx: RunContext }) => number) optional?: boolean maxTokens?: number background?: boolean resumable?: boolean | string | ((args: { ctx: RunContext }) => string) }

Agent-step configuration, including model selection, output repair, budgets, isolation, and resumability.

Remarks: An acting agent omits output. A reporting agent declares output; an asking agent additionally sets asks: true. Asking cannot be combined with background. Static resumable keys cannot be shared by executions that may overlap.

CreateStepOptions

interface CreateStepOptions<TInputSchema extends TSchema | undefined = undefined, TOutputSchema extends TSchema | undefined = undefined> { name: string description?: string input?: TInputSchema output?: TOutputSchema retry?: RetryPolicy maxDurationMs?: number | ((args: { ctx: RunContext }) => number) optional?: boolean run: StepRunFn<InferInput<TInputSchema>, InferOutput<TOutputSchema>> }

Configuration shared by a function step, including retry, duration, and optional-failure controls.

Remarks: retry.maxRetry counts attempts after the first. optional should only be used when downstream nodes do not require this step's output, because a final failure produces undefined.

Interactive

CreateInteractiveStepOptions

interface CreateInteractiveStepOptions<TInputSchema extends TSchema | undefined, TRequestSchema extends TSchema, TOutputSchema extends TSchema> { name: string description?: string input?: TInputSchema request: TRequestSchema output: TOutputSchema buildRequest: (args: InteractionRequestArgs<InferInput<TInputSchema>>) => Static<TRequestSchema> render: ( args: InteractionRenderArgs<Static<TRequestSchema>>, ) => Static<TOutputSchema> | undefined | Promise<Static<TOutputSchema> | undefined> }

Configuration for a workflow-defined interaction rendered by the attended PI host.

createInteractiveStep

createInteractiveStep<TInputSchema extends TSchema | undefined = undefined, TRequestSchema extends TSchema = TSchema, TOutputSchema extends TSchema = TSchema>(options: CreateInteractiveStepOptions<TInputSchema, TRequestSchema, TOutputSchema>): InteractiveStep

Create a resumable interactive step whose request and response types are inferred from TypeBox.

The engine remains UI-free: it persists the request and returns blocked. Only an attended host invokes render, after the engine call has ended. Offline callers can inspect the pending request and submit a response directly without loading PI UI.