Skip to content

Let an assistant plan its own workflow

An assistant connected to Realm can write a workflow for a task that none of yours covers. It lists the steps it intends to take, and Realm then holds it to that list: in order, with each answer checked, and with a record at the end. This guide shows what the assistant sends, what Realm does with it, what it refuses, and how such a workflow differs from one you write in a file.

You need an assistant connected to Realm. See Connect an MCP client.

The tool is called create_workflow, and every connected assistant has it. Realm suggests it when the assistant lists your workflows:

Call get_workflow_protocol with a workflow_id before calling start_run. If no workflow matches your task, use create_workflow to define and start your own plan.

So an assistant may create a workflow without being asked to, when the task is long and nothing registered fits.

A list of steps, and a few words about the task. This plan drafts release notes in three steps:

{
"metadata": {
"name": "release-notes",
"description": "Draft release notes for a version.",
"task_description": "Collect the merged changes, group them, then write the notes."
},
"steps": [
{
"id": "collect",
"description": "List the changes merged since the last release.",
"input_schema": {
"type": "object",
"additionalProperties": false,
"required": ["changes"],
"properties": {
"changes": { "type": "array", "items": { "type": "string" }, "minItems": 1 }
}
}
},
{
"id": "group",
"description": "Group the changes into Added, Changed and Fixed.",
"depends_on": ["collect"]
},
{
"id": "write",
"description": "Write the release notes as Markdown.",
"depends_on": ["group"],
"input_schema": {
"type": "object",
"additionalProperties": false,
"required": ["markdown"],
"properties": { "markdown": { "type": "string", "minLength": 20 } }
}
}
]
}

A step can have these fields and no others:

Field Meaning
id The step’s name. Required.
description What the step is for. Required.
depends_on Steps that must finish first. Each must be earlier in the list.
input_schema The shape the step’s answer must have.
structured_output strict, to have the model provider hold answers to that shape when realm agent drives the step.
llm_timeout_seconds The longest one model request for this step may take under realm agent.

metadata takes name, description and task_description. task_description is returned as quick_start when an assistant asks how to run the workflow.

Realm registers the workflow, starts a run of it, and returns the first step to do:

status: ok
workflow_id: release-notes-86de43b5661ea6e9
run_id: 4fe4f2e3-14b4-4f9c-9e8c-b96052cb8ed9
Run '4fe4f2e3-14b4-4f9c-9e8c-b96052cb8ed9' created for workflow 'release-notes-86de43b5661ea6e9'. Ready for the agent: 'collect'.
next: execute_step collect

The Ready for the agent: … sentence was added after version 0.46.0, which ends the line at created for workflow '…'..

The assistant does not choose the workflow’s ID. Realm makes it from the name and a code computed from the plan’s content. The same plan sent again gets the same ID and a new run. A plan with no name gets an ID that starts with dynamic-.

From here the run behaves like any other. The assistant tried group before collect, and was refused:

status: blocked
Step 'group' cannot be called now: its dependencies are not settled ('collect'). Ready for the agent: 'collect'.
eligible_steps: collect

The reason after cannot be called now: was added after version 0.46.0, which says Step 'group' is not eligible in the current run state.

It then answered collect with an empty list, which its own schema does not allow:

status: error
VALIDATION_INPUT_SCHEMA: Invalid input for step 'collect'
/changes must NOT have fewer than 1 items
agent_action: provide_input

With a valid answer to each step in order, the run completed.

The workflow is in the list, marked as made by an agent:

Terminal window
realm workflow list
ID NAME VERSION ORIGIN SCHEMA
release-notes-86de43b5661ea6e9 release-notes 1 agent 1 (current)

The run has a record like any other. realm run inspect <run-id> shows each step’s answer:

Phase: completed ✓
…
Completed: collect, group, write
…
1. collect success 1ms hash: 8d7a0354
Taken by: ops@server-1 (from the OS user, via mcp-stdio)
Input: {"changes":["Add replay page","Fix copy button"]}
…
2. group success 0ms hash: 3a5f234a
Taken by: ops@server-1 (from the OS user, via mcp-stdio)
Input: {"whatever":true}

The workflow stays registered. Anyone can start another run of it by its ID.

Every step is done by the assistant. A created workflow has no steps that Realm runs by itself, no services, no handlers, no conditions and no human gates. It is a checklist with checked answers, not an automation.

An assistant cannot give itself a human gate. If it sends trust, gate, execution or any other field that is not in the table above, Realm leaves the field out, creates the workflow without it, and says so in the reply:

status: ok
⚠ step 'a': unknown key 'trust' — ignored (not a recognized step field).
⚠ step 'a': unknown key 'gate' — ignored (not a recognized step field).

If a task needs your approval part-way, write the workflow yourself. See Add a human gate.

A step is only as strict as its schema. In the plan above, group has no input_schema, so any answer to it is accepted. The record in step 4 shows the one it got: {"whatever":true}. The assistant writes the checks that are then applied to its own answers.

It has no project. It cannot name code to load, and it reads no realm.yaml unless the server was started with --project. See Deploy a project.

In each of these cases nothing is created. Except for the first, the reply has agent_action: provide_input, which tells the assistant to correct the plan and send it again.

The plan has The reply says
No steps Array must contain at least 1 element(s) at steps
Two steps with one id Duplicate step id: 'a'
A depends_on naming no step Step 'a': depends_on references unknown step 'zzz'
A depends_on naming a later step Step 'a': depends_on must reference a step that appears earlier in the list
An input_schema that is not valid JSON Schema Step 'a': 'input_schema' is not a valid JSON Schema — 'type' must be one of array, boolean, integer, …
structured_output: strict with a schema it cannot use Step 'a': 'structured_output: strict' is not eligible for this step's schema — add 'additionalProperties: false' …
extensions extensions is not supported on dynamically-created workflows. Project extensions are register-time and operator-only: …

In these cases the workflow is created and the run starts. The reply lists what was left out.

The plan has The warning says
A step field that is not in the table step 'a': unknown key 'handler' — ignored (not a recognized step field).
A top-level field Realm does not know unknown key 'services' — ignored (not a recognized create_workflow field).
workflow_id 'workflow_id' is ignored — create_workflow mints its own workflow id and returns it as data.workflow_id; …
name beside steps, not under metadata 'name' belongs under metadata — submitted at the top level it is ignored; use metadata.name.
timeout_seconds on a step 'timeout_seconds' was removed (#412) — nothing enforces it on agent steps; the model-request bound is 'llm_timeout_seconds'.

Created workflows add up, one for each different plan. No command removes a workflow. Each is one file in ~/.realm/workflows/, named after its ID, and deleting the file removes it from the list. Runs of it stay in the store, and realm run inspect still shows their record.