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:
| Slot | When it is used | Supported actions |
|---|---|---|
output | After a step has executed | navigate |
wait | While a step is paused for user input | navigate, 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:
- Custom surface - authored by a developer with
new Surface(...)and reusable by key. - Node default - selected from the defaults registered for that node type and slot.
- Generic default - the final platform fallback. The current built-ins are
default.jsonfor output anddefault.resume-formfor 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 devcreates a draft for the active developer session. The draft is removed when the session ends.culvii deploypublishes 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: