Skip to content

Agent Workflows let you define, manage, and run multi-step automations on a live session. A workflow definition is the static recipe (an ordered set of steps with an entry point); a workflow run is a live execution of that recipe against a particular session. Use these endpoints to list, read, create, replace, delete, or hide workflow definitions, to dispatch a workflow onto a session, and to inspect or cancel in-flight runs.

All routes are realm-scoped to the GATEWAY’s own realm and resolve definitions and runs through the per-request X-Hoody-Cwd / X-Hoody-Config-Dir headers. A client-supplied X-Hoody-Realm / ?realm= is accepted on read-only listing routes but rejected on the routing tables that have no realm dimension to scope.

List the workflow definitions visible to the requesting cwd / config_dir (name, summary, step briefs, system flag). Read one with GET /workflows/{name}; create or replace with PUT /workflows/{name}; delete with DELETE /workflows/{name}; hide with POST /workflows/{name}/hide.

NameInTypeRequiredDescription
pagequeryintegerNo1-based page number for pagination.
limitqueryintegerNoMaximum items per page (0 = no pagination).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
{
"items": [
{
"name": "build",
"summary": "Build the project and run smoke tests",
"system": false,
"steps": [
{ "id": "compile", "summary": "Run the build" },
{ "id": "test", "summary": "Run smoke tests" }
]
},
{
"name": "deploy",
"summary": "Deploy the built artifact to staging",
"system": true,
"steps": [
{ "id": "upload", "summary": "Upload artifact" },
{ "id": "promote", "summary": "Promote to staging" }
]
}
],
"meta": {
"total": 12,
"page": 1,
"limit": 50
}
}
await client.agent.workflows.listWorkflowsIterator({ limit: 50 });

Read one workflow definition as JSON. The result rides the {output, is_error} tool envelope; is_error: true with output "workflow X not found" for an unknown name.

NameInTypeRequiredDescription
namepathstringYesWorkflow name (path identifier).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
include_revisionquerybooleanNoIf “true”, the tool output’s first line is revision: <opaque>“ — pass that value as putWorkflow’s expected_revision to guard against concurrent edits; the JSON below it is unchanged. Strictly parsed: exactly one value, “true” or “false”; anything else (empty, “TRUE”, “1”, repeated) is a 400 bad_request.
{
"output": {
"name": "build",
"summary": "Build the project and run smoke tests",
"system": false,
"entry_point": "compile",
"steps": [
{ "id": "compile", "summary": "Run the build" },
{ "id": "test", "summary": "Run smoke tests" }
]
},
"is_error": false
}
await client.agent.workflows.getWorkflow({ name: "build" });

Create or replace one workflow definition. The body carries the definition object; the {name} path value is authoritative. The daemon validates the definition strictly before writing atomically (unknown fields rejected, the loader’s structural gate enforced), so a malformed definition is refused (is_error: true) rather than corrupting workflow.json. The system flag is authoritative from the embedded defaults — a caller cannot forge it.

NameInTypeRequiredDescription
namepathstringYesWorkflow name (path identifier).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
FieldTypeRequiredDescription
definitionobjectYesThe full workflow definition object (steps, entry_point, summary). Validated strictly daemon-side before an atomic write.
{
"definition": {
"summary": "Build the project and run smoke tests",
"entry_point": "compile",
"steps": [
{ "id": "compile", "summary": "Run the build" },
{ "id": "test", "summary": "Run smoke tests" }
]
}
}
{
"output": "workflow build upserted",
"is_error": false
}
await client.agent.workflows.putWorkflow({
name: "build",
data: {
definition: {
summary: "Build the project and run smoke tests",
entry_point: "compile",
steps: [
{ id: "compile", summary: "Run the build" },
{ id: "test", summary: "Run smoke tests" }
]
}
}
});

Delete one USER workflow definition. System workflows are refused (is_error: true — they re-seed on boot; hide them instead via hideWorkflow).

NameInTypeRequiredDescription
namepathstringYesWorkflow name (path identifier).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
{
"output": "workflow build deleted",
"is_error": false
}
await client.agent.workflows.deleteWorkflow({ name: "build" });

Hide or un-hide a workflow from the Workflows tab. Hiding is the only way to remove a SYSTEM workflow from view — system workflows are re-seeded on every boot and can never be deleted. User workflows can be hidden too. Pass hidden: false in the body to un-hide. The hide stays realm-private (the gateway’s own realm only); a client-supplied X-Hoody-Realm / ?realm= is ignored.

NameInTypeRequiredDescription
namepathstringYesWorkflow name (path identifier).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
FieldTypeRequiredDescription
hiddenbooleanNotrue (default) to hide the workflow; false to un-hide it.
{
"hidden": true
}
{
"hidden_workflows": ["build", "deploy"]
}
await client.agent.workflows.hideWorkflow({ name: "build", data: { hidden: true } });

POST /api/v1/agent/sessions/{id}/workflows/{name}/runs

Section titled “POST /api/v1/agent/sessions/{id}/workflows/{name}/runs”

Dispatch a workflow run onto a live session. The daemon returns no RunID synchronously, so the gateway mints its own job_id and correlates the daemon RunID lazily — job.run_id is null during the brief dispatch window and is populated once the workflow loop registers the run (observe workflow_start on the session’s stream). Run events flow on the owning session’s WS/SSE attach; there is no per-run event bus.

NameInTypeRequiredDescription
idpathstringYesSession id (path identifier).
namepathstringYesWorkflow name (path identifier).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
FieldTypeRequiredDescription
promptstringNoOptional input text fed to the workflow run.
{
"prompt": "Build main and run smoke tests on the staging artifact"
}
{
"job_id": "job-9c1f5e2a",
"session_id": "sess-3a4b6c8d",
"run_id": null
}
await client.agent.workflows.runSessionWorkflow({
id: "sess-3a4b6c8d",
name: "build",
data: { prompt: "Build main and run smoke tests on the staging artifact" }
});

Snapshot of in-flight and recently-finished workflow runs. The registry exposes Snapshot(), not Subscribe(), so poll this endpoint to track a run’s progress. Live events also flow on the owning session’s stream.

NameInTypeRequiredDescription
pagequeryintegerNo1-based page number for pagination.
limitqueryintegerNoMaximum items per page (0 = no pagination).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
{
"items": [
{
"run_id": "run-7a2b1c3d",
"workflow": "build",
"session_id": "sess-3a4b6c8d",
"status": "running",
"started_at": "2026-01-12T09:14:33Z",
"current_step": "test"
},
{
"run_id": "run-1f9e0a4b",
"workflow": "deploy",
"session_id": "sess-3a4b6c8d",
"status": "finished",
"started_at": "2026-01-12T08:50:02Z",
"finished_at": "2026-01-12T08:52:11Z"
}
],
"meta": {
"total": 2,
"page": 1,
"limit": 50
}
}
await client.agent.workflows.listWorkflowRunsIterator({ limit: 50 });

Get a single workflow run row by run id from the registry snapshot. Returns 404 not_found when the run id is no longer in the snapshot (evicted or never existed).

NameInTypeRequiredDescription
run_idpathstringYesRun id (path identifier).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
{
"run_id": "run-7a2b1c3d",
"workflow": "build",
"session_id": "sess-3a4b6c8d",
"status": "running",
"started_at": "2026-01-12T09:14:33Z",
"current_step": "test"
}
await client.agent.workflows.getWorkflowRun({ run_id: "run-7a2b1c3d" });

POST /api/v1/agent/workflows/runs/{run_id}/cancel

Section titled “POST /api/v1/agent/workflows/runs/{run_id}/cancel”

Cancel an in-flight workflow run by run id.

NameInTypeRequiredDescription
run_idpathstringYesRun id (path identifier).
X-Hoody-CwdheaderstringNoPer-request working-directory scope (§6.1): the .hoody project layer / record cwd / tool+workflow cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override (§6.1) selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (§6.1; omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector (§6.1): "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector (§6.1) — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
{
"cancelled": true,
"run_id": "run-7a2b1c3d"
}
await client.agent.workflows.cancelWorkflowRun({ run_id: "run-7a2b1c3d" });