Authoring processes

A process is a JSON document. You can write it by hand, generate it with the Studio Assistant (which loads the learn_process_design skill), or iterate with an LLM in any editor and paste the result. This page covers both paths and the rules a valid definition must satisfy.

The editor in Vertesia Studio

Studio gives you both a visual authoring surface and a code editor for the same definition:

  • Statechart / process board. The visual view renders the process as cards and transitions. For larger definitions, use lanes and phases so the graph reads like a business process board instead of a raw dependency graph.
  • Inspector. Clicking a node or transition opens the selected definition as YAML, plus readable fields such as type, tool, interaction, writes, phase, lane, and order.
  • Explain. The inspector can call sys:ExplainProcess for the selected node, guard, or whole process. Use this before changing an unfamiliar definition.
  • Code tab. The full definition is still editable as JSON/YAML when you need bulk changes, search/replace, or a reviewable diff.
  • Live parse. Save is blocked while the document is unparseable.
  • Validation. The save path runs the same server-side process-definition validation used by the validate_process tool. The Studio Assistant calls that tool directly while iterating.

The stored definition contract is explicit about its schema generation: native process definitions carry format_version: 1. Studio can prefill that field for a new draft, but the saved JSON keeps it present so future migrations have a stable boundary.

Authoring with the Studio Assistant

The fastest way to go from "I want a process that does X" to a committed draft is the Studio Assistant. When you ask it to author or change a process, it loads the learn_process_design skill — which unlocks the process tools and grammar before it drafts anything:

  • learn_process_design — loads the full process grammar and authoring rules before drafting.
  • list_tools, list_interactions, get_interaction — confirm every name it references actually exists.
  • validate_process — validates a draft JSON against the schema. The assistant iterates until clean.
  • create_process / update_process — write or revise a draft in the catalog.
  • publish_process — publishes a draft only after explicit confirmation.
  • start_process_run, get_process_run — run and inspect a draft to test it end to end.
  • LayoutProcessDefinition — improves visual metadata and transition labels without changing runtime behavior.
  • ask_user, plan, update_plan, think — standard authoring scaffolding.

Its iteration loop is:

  1. Discover — one ask_user batch with all open questions.
  2. Load the grammar (learn_process_design).
  3. Confirm tool / interaction names with the user before referencing them.
  4. Draft the JSON.
  5. Validate; fix every error; repeat until clean.
  6. Create or update a draft. Do not set status or version; the server owns them.
  7. Publish only after explicit confirmation. Include an optional publish comment when one is provided.
  8. Summarize: node graph, inputs expected per run, outputs written to context, where humans intervene.

Rules a valid definition must satisfy

These are the traps that catch first-time authors. They're codified in the learn_process_design skill and in the server-side validator:

  1. node.input is a runtime mapping, not a schema. Use a bare template: "invoice": "{{invoice_doc_id}}". Never put a JSON-schema fragment like { "type": "string", "editor": "document" } inside node.input — that belongs on the target interaction's input schema.
  2. Document fields in context.schema must set both format and editor. Use { "type": "string", "format": "document", "editor": "document", "description": "…" }. Without editor, the Start Run modal falls back to a raw store:<id> text field.
  3. Agent nodes return structured output, not control-flow tool calls. Don't prompt worker agents to call process-control tools such as set_context, transition_to, or skip_node — those belong to the top-level supervisor, not node workers. The engine builds a result_schema from node.writes (plus a _next_node enum on multi-transition nodes) and constrains the child's output to match. See Agent nodes.
  4. Agent nodes get only the tools you declare in node.tools. Skills (learn_*) are available so the agent can self-unlock capabilities.
  5. Agent nodes use sys:ProcessAgentNode by default. It injects process orientation automatically. Override with node.interaction only when you need a custom interaction with its own input schema.
  6. Every node should have a human_description. One or two sentences in plain language, distinct from the developer-facing description. Surfaces in observability. Undescribed nodes read as noise in the run report.
  7. Template references throw on missing fields. Only reference context fields guaranteed to exist at the node.
  8. Every condition node must match a branch or have default: true. No match and no default = runtime error.
  9. Context is capped at 64 KB serialized. Store large payloads as artifact URIs and reference them.
  10. Do not overload collection fanout and fixed split/join in your own mental model. Use condition to choose one path, branch to run a fixed set of named branches and join, and foreach to repeat a child body over a collection.
  11. Fanout child bodies do not own routing. In foreach and branch, the child body should be tool, interaction, agent, or process only, with no nested transitions or branches.
  12. Any node that writes context must declare writes. A non-empty context_update, human task answer, interaction result, agent result, collected foreach output, or collected branch output is rejected unless the parent node declares the target fields in writes.
  13. Supervisor overrides must be explicit. transition_to follows declared exits by default, and skip_node requires skippable: true. Use metadata.supervisor.allow_transition_override or metadata.supervisor.allow_skip only for deliberate break-glass cases.
  14. Large processes need visual metadata. Set metadata.phase, metadata.lane, and metadata.order on nodes when the graph has more than a straight-line handful of steps. The run UI uses those values for the Process Navigator and stable layout.
  15. set_context tool nodes use an updates envelope. A process tool node that calls set_context must pass { "updates": { ... } }, not raw context fields at the top level. The node still declares writes for every updated field.
  16. Use real interaction names. For open-ended agent behavior, prefer sys:GeneralAgent or a custom agent interaction. Use sys:ProcessAgentNode for normal worker-agent nodes unless you have a specific interaction contract to override.

Assignees

Human-task assignee is either a group reference (group:<name>) or a concrete user id. role:<name> is not supported — use group:<name> instead. Leave unset if the task should be available to anyone who can see the inbox.

Process board metadata

The process graph is readable only when authors describe the business structure, not just the transitions. For larger processes, model the visual board deliberately:

  • metadata.phase is the stage of work: intake, AI review, approval, fulfillment, closeout.
  • metadata.lane is the responsible actor or system: requester, AI assistant, policy, legal, procurement, outcome.
  • metadata.order is the stable sort key inside that lane.
  • Transition and branch label values are the business names of exits: approved, rejected, needs legal, amount >= 10000.

In the swimlane view, lanes render as vertical responsibility bands and nodes stack top-to-bottom within each lane. The main flow usually moves left-to-right across lanes; alternate paths can loop down or back across lanes. Keep lane names short and consistent.

Add layout metadata to every node in multi-stage processes:

{
    "agent2_asset_generation": {
        "type": "agent",
        "title": "Agent 2 — Campaign Asset Generation",
        "metadata": {
            "phase": "Gate 2",
            "lane": "agent",
            "order": 10
        },
        "writes": ["asset_package"],
        "transitions": [
            {
                "to": "gate2_asset_review",
                "label": "Send package to review"
            }
        ]
    },
    "gate2_asset_review": {
        "type": "human_task",
        "title": "Gate 2 — Asset Package Review",
        "metadata": {
            "phase": "Gate 2",
            "lane": "review",
            "order": 20
        }
    }
}

Use a small, stable vocabulary for lane: business roles (requester, legal, finance, claims_adjuster) are better than implementation terms when humans need to read the board. Use implementation lanes (ai_assistant, policy, tooling) when ownership is genuinely a system.

Add label to transitions and branches when the guard is not obvious. The graph renders those labels on the edge, and the inspector shows the selected transition / branch as YAML.

Improving layout with the assistant

When a graph becomes hard to read, use the Studio Assistant or the Improve layout action. It calls LayoutProcessDefinition with the current definition and optional notes about the current rendering. The interaction is constrained to visual fields:

  • node title, description, and human_description
  • node metadata.phase, metadata.lane, metadata.order, and optional metadata.position
  • transition / branch label

It should not change runtime behavior: no node ids, node types, context schema, inputs, writes, tools, interactions, guards, targets, defaults, or tasks.

Hand-authoring workflow

If you're editing directly in Studio or in a Git checkout:

  1. Start from the schema: define context.schema first. Every field a node writes must exist here.
  2. Lay out nodes and transitions. Name them for what they do, not how they work (e.g. legal_review, not human_task_1).
  3. Fill each node's human_description. Ask yourself: what would a reviewer read here during observability?
  4. For agent nodes, set the minimum writes scope — the result_schema is derived from it, so tighter writes means stricter agent output.
  5. Add visual metadata and transition labels before the graph gets large. It is much easier to keep the run view readable while authoring than to repair it later.
  6. Validate. Validation catches unreferenced nodes, branches with no default, and schema mismatches.
  7. Save the draft. Run it against a known-good input. Iterate. Publish only when it is stable and the publishing user confirms.

Versioning

Process definitions use draft/published versioning:

  • New definitions are drafts at version: 1.
  • Draft edits mutate the latest draft.
  • Published revisions are immutable.
  • Editing a published head creates the next draft head instead of changing the published version.
  • Listings show only the latest/head revision by default; use the Versions tab or all_versions only when you need history.
  • Publishing requires explicit confirmation and can include a comment.
  • A historical version can be reverted into the current draft from the Versions tab.

Already-running processes continue to execute the definition that was passed into their Temporal workflow at start. Editing or reverting the catalog entry does not change an in-flight run.

Next

  • Node types — the reference for each type.
  • Observability — how to watch a run and debug what an agent node actually produced.

Was this page helpful?