Skip to main content

Surfaces overview

A surface is a versioned UI definition authored alongside workflows and agents. It describes how the console can render a workflow step's output or a paused step without embedding UI code in the workflow.

Surfaces are regular @culvii/kit resources. You create them in .culvii.ts files and the same culvii dev and culvii deploy commands that collect workflows and agents also collect surfaces. There is no separate surface command.

Surface slots

Every surface belongs to one slot:

SlotWhen it is usedSupported actions
outputAfter a step has executednavigate
waitWhile a step is paused for user inputnavigate, node.resume, node.stop

Assigning a wait surface through the Kit automatically sets the step's params.pauseAfterExecution to true. Assigning an output surface to the wait slot, or a wait surface to the output slot, is rejected.

Three surface sources

A workflow step can use one of three surface sources:

  1. Custom surface - authored by a developer with new Surface(...) and reusable by key.
  2. Node default - selected from the defaults registered for that node type and slot.
  3. Generic default - the final platform fallback. The current built-ins are default.json for output and default.resume-form for waits.

The execution response gives the renderer all candidates at once:

customSurface
→ fallbackSurface
→ remainingSurfaces
→ defaultJsonSurface

The renderer tries them in that order. If the custom definition is unavailable, inactive, invalid, or the caller does not have ui:view, customSurface is null and rendering starts from the fallback.

Runtime response

GET /api/executions/:executionId returns the normal execution detail plus a surfaces object keyed by workflow node ID:

{
"surfaces": {
"get-second-resource": {
"nodeId": "get-second-resource",
"nodeType": "core.http",
"slot": "output",
"customSurface": {},
"fallbackSurface": {},
"remainingSurfaces": [],
"defaultJsonSurface": {},
"dataModel": {
"$output": {},
"$input": {},
"$binary": {}
},
"diagnostics": []
}
}
}

Only executed nodes are included. A currently paused node uses its wait surface; other executed nodes use their output surface.

The platform supplies definitions and projected data. The UI resolves each component's path against dataModel and renders the resulting value.

Scope, drafts, and versions

  • A surface key is unique within a tenant.
  • culvii dev creates a draft for the active developer session. The draft is removed when the session ends.
  • culvii deploy publishes a new immutable version when the definition changes.
  • An unpinned reference follows the current published version, or the active session draft during development.
  • A pinned reference keeps using its explicit version.
  • An inactive surface family cannot render any version; the renderer receives fallbacks instead.

Next: