Skip to content
SurfaceDocs
FRGet started
DocsModel reference

FlowComposition · types

Interfaces, values and named contracts for FlowComposition.

The following types define named objects and their relationships. Tables include inherited properties. Schema-derived types refer to their validated structures; a TypeScript declaration does not replace the compiler’s semantic checks.

FlowComposition

Explicit Model grammar for the existing canonical Flow engine’s composed extension.

export type FlowComposition = z.infer<typeof flowCompositionSchema>;

FlowCompositionStep

One referenced control or executable step, distinct from canonical parenthood and layout.

export type FlowCompositionStep = FlowComposition['steps'][number];
type FlowCompositionStep = { key: string; kind: "task"; workNodeKey: string; actionKey: string; inputs: Record<string, { kind: "input"; key: string; } | { kind: "input-node-id"; key: string; } | { kind: "field"; definitionPath: string; fieldKey: string; } | { kind: "literal"; value: string | number | boolean | null; } | { kind: "collection-item"; } | { kind: "collection-node-id"; } | { kind: "iteration-number"; } | { kind: "step-output"; stepKey: string; outputKey: string; }>; outputs: { key: string; type: "number" | "boolean" | "text" | "surface-reference" | "result-reference"; provenance: "caller" | "canonical" | "derived"; minimum: number; maximum: number; result: "outputs" | "reference" | "summary" | "decisions" | "nextSteps" | "blockers"; }[]; reservedCostUnits: number; maximumAttempts: number; } | { key: string; kind: "sequence"; steps: string[]; } | { key: string; kind: "choice"; mode: "exclusive" | "multiple"; branches: { key: string; stepKey: string; ruleKey: string; }[]; minimum: number; maximum: number; selection: "all-eligible" | "explicit"; confirmation: "required" | "not-required"; freshness: "captured" | "require-current"; join: { mode: "all"; remaining: "wait"; } | { mode: "quorum"; successes: number; remaining: "wait" | "request-cancel"; }; } | { key: string; kind: "parallel"; branches: { key: string; stepKey: string; }[]; maximumConcurrency: number; join: { mode: "all"; remaining: "wait"; } | { mode: "quorum"; successes: number; remaining: "wait" | "request-cancel"; }; } | { key: string; kind: "subflow"; blueprintKey: string; inputs: Record<string, { kind: "input"; key: string; } | { kind: "input-node-id"; key: string; } | { kind: "field"; definitionPath: string; fieldKey: string; } | { kind: "literal"; value: string | number | boolean | null; } | { kind: "collection-item"; } | { kind: "collection-node-id"; } | { kind: "iteration-number"; } | { kind: "step-output"; stepKey: string; outputKey: string; }>; } | { key: string; kind: "collection"; queryKey: string; parameters: Record<string, { kind: "input"; key: string; } | { kind: "input-node-id"; key: string; } | { kind: "field"; definitionPath: string; fieldKey: string; } | { kind: "literal"; value: string | number | boolean | null; } | { kind: "collection-item"; } | { kind: "collection-node-id"; } | { kind: "iteration-number"; } | { kind: "step-output"; stepKey: string; outputKey: string; }>; stepKey: string; maximumItems: number; maximumPages: number; maximumOutputBytes: number; maximumConcurrency: number; freshness: "captured" | "require-current"; join: { mode: "all"; remaining: "wait"; } | { mode: "quorum"; successes: number; remaining: "wait" | "request-cancel"; }; } | { key: string; kind: "iterate"; stepKey: string; stopRuleKey: string; maximumIterations: number; inputs: Record<string, { kind: "input"; key: string; } | { kind: "input-node-id"; key: string; } | { kind: "field"; definitionPath: string; fieldKey: string; } | { kind: "literal"; value: string | number | boolean | null; } | { kind: "collection-item"; } | { kind: "collection-node-id"; } | { kind: "iteration-number"; } | { kind: "step-output"; stepKey: string; outputKey: string; }>; } | { key: string; kind: "wait"; inputs: ({ key: string; minimum: number; maximum: number; type: "number" | "boolean" | "text"; provenance: "caller"; } | { key: string; minimum: number; maximum: number; type: "surface-reference" | "result-reference"; provenance: "canonical"; selector: { contract: "SurfaceFlowReferenceSelector@1"; queryKey: string; parameters: Record<string, { kind: "input"; key: string; } | { kind: "input-node-id"; key: string; } | { kind: "field"; definitionPath: string; fieldKey: string; } | { kind: "literal"; value: string | number | boolean | null; } | { kind: "collection-item"; } | { kind: "collection-node-id"; } | { kind: "iteration-number"; } | { kind: "step-output"; stepKey: string; outputKey: string; }>; }; })[]; arrival: "active-only"; ordering: "first-committed"; eventKey: string; recipient: "initiator"; timeoutMilliseconds: number; onExpiration: "fail" | "cancel"; } | { key: string; kind: "delay"; resume: { kind: "duration"; milliseconds: number; } | { kind: "instant"; at: number; }; };

FlowCompositionValueSource

Exact typed value mapping; arbitrary expressions, code and tool names are not admitted.

export type FlowCompositionValueSource = z.infer<typeof valueSource>;

FlowReferenceSelector

Exact Query and closed Flow bindings; the canonical Query service owns execution.

export type FlowReferenceSelector = z.infer<typeof referenceSelector>;

All references

Applied examples : Prepare a quote

The Flow declares Client and Need inputs, an executable step and a bounded budget.

Configuration

Fragment placed in flowBlueprints[].composition. Properties and accepted values.

{
  "contract": "FlowComposition@1",
  "rootWorkNodeKey": "prepare-quote",
  "stateSurfaceDefinitionPath": "workspace/work/surface/preparation",
  "subflowLinkTypePath": null,
  "entryStepKey": "prepare",
  "inputs": [
    {
      "key": "client",
      "type": "surface-reference",
      "provenance": "caller",
      "minimum": 1,
      "maximum": 1
    },
    {
      "key": "need",
      "type": "text",
      "provenance": "caller",
      "minimum": 1,
      "maximum": 1
    }
  ],
  "contexts": [],
  "outputs": [],
  "steps": [
    {
      "key": "prepare",
      "kind": "task",
      "workNodeKey": "prepare",
      "actionKey": "prepare",
      "inputs": {},
      "outputs": [
        {
          "key": "proposal",
          "type": "result-reference",
          "provenance": "canonical",
          "minimum": 1,
          "maximum": 1,
          "result": "reference"
        }
      ],
      "reservedCostUnits": 1,
      "maximumAttempts": 1
    }
  ],
  "budgets": {
    "maximumDepth": 2,
    "maximumOccurrences": 20,
    "maximumConcurrency": 2,
    "maximumIterations": 3,
    "maximumDurationMilliseconds": 86400000,
    "maximumCostUnits": 100,
    "maximumStateBytes": 32000
  }
}

Variation and connection

Fragment placed in flowBlueprints[].composition.inputs. Properties and accepted values.

[
  {
    "key": "client",
    "type": "surface-reference",
    "provenance": "caller",
    "minimum": 1,
    "maximum": 1
  },
  {
    "key": "need",
    "type": "text",
    "provenance": "caller",
    "minimum": 1,
    "maximum": 1
  }
]

UI layout example

The illustrative layout below places this configuration in the Clients/Quotes app. Insert each fragment at the stated location, with Field, Query and Action references matching the Model declarations.

  1. Qualify need
  2. Prepare proposal
  3. Wait for decision
  4. Retain result
ILLUSTRATIVE LAYOUTClients / Quotes app
SurfaceClients / North StudioExample
FlowComposition · typesPrepare a quote
Clients
✓
Qualify needCompleted
✓
Prepare proposalCompleted
03
Wait for decisionDecision required
04
Retain resultUpcoming
Preparation is awaiting a decision

The proposal and its sources remain available while waiting.

Review proposal
Search for a concept, field or action.Esc