Skip to main content
← Back to list
01Issue
FeatureOpenSwamp CLIPublicTeam
AssigneesNone

Relationships

#3578 workflow placement: run a workflow transparently on a specified host, local or via swamp workers (incl. nested child workflows)

Opened by svendowideit · 10/17/2026

Problem

A workflow that must run on a specific host has to declare placement (target/labels/platform) in its YAML. Placement presence is static, and hasPlacement() (src/domain/remote/scheduler.ts) treats a non-undefined target/platform — even an empty string — or a non-empty labels as active. When placement is active but no dispatcher is running (a plain local swamp workflow run), the run fails:

Step requests remote placement but no worker dispatcher is active — remote execution
requires running under 'swamp serve' with enrolled workers

So one workflow file cannot transparently:

  • run locally (standalone swamp, break-glass/dev on a single host), and
  • be routed to a worker host when the same repo is served by swamp serve with workers.

This is worse for reuse via nested workflows: a nested type: workflow step does not inherit the caller's placement — the child run uses its own workflow.placementFields only (src/domain/workflows/execution_service.ts). A shared child workflow therefore cannot be written once and used by parents that run in different deployment configs.

What we want

A way to control where a child workflow's steps run such that:

  • a high-level workflow can reuse other workflows (component architecture), and
  • all of them run on the same specified host, and
  • the same workflow file works unchanged whether run by a standalone swamp, a standalone swamp serve, or a distributed swamp serve with workers doing different jobs — i.e. a workflow written for one deployment config runs on the others transparently.

Is there — or can there be — such a mechanism?

What we tried (swamp 20261017.001604.0)

  1. Nest a child that declares its placement from an input: target: ${{ inputs.target }}.
    • Under serve with inputs.target=figy-eieio: works — the child's model-method steps dispatch to that worker (and a grandchild too, when the input is forwarded).
    • Standalone with the input defaulting to "": fails — hasPlacement("") is true, so it still demands a dispatcher.
    • No default and no --input: CEL error No such key: target.
    • null: schema rejects (target: Invalid input: expected string, received null).
  2. labels: ${{ inputs.labels }} (object input, default {}): works under serve; an empty object correctly means "no placement" (runs locally). But standalone it fails at load: labels: Invalid input: expected record, received string — record-valued placement fields reject expression strings (only serve resolves runtime selectors).
  3. Static labels: {} runs locally — but it is static, so it cannot also route to a worker.

Conclusion: there is currently no way to write one child workflow that is placed on a worker under serve and runs locally otherwise. Reusing a shared child across deployment configs requires forking a placed copy kept in lockstep, or an all-or-nothing migration of every caller.

Proposed

Any of:

  • Inherit placement into nested runs when the child declares none (child-wins merge), so a child runs wherever its caller is placed — and the caller's absence of placement keeps it local. (Lab #2465)
  • A serve-side default placement, applied only when a dispatcher is active and only to steps whose merged placement is empty. (Lab #2344)
  • A fallback-to-local for placement when no dispatcher is active, behind an opt-in workflow field (e.g. placementFallback: local), so a placed workflow still runs locally.

Related: #2344, #2465.

02Bog Flow
◉OPEN○TRIAGED○IN PROGRESS○SHIPPED

Open

10/17/2026, 1:10:23 PM

No activity in this phase yet.

03Sludge Pulse
svendowideit moved this from the private collective work-test to public10/17/2026, 1:18:30 PM
Editable. Press Enter to edit.

svendowideit commented 10/17/2026, 1:16:37 PM

hmmm, i've been pondering this for a while, and still am not sure if this is intentional for security like reasons, but ... it's hard for me to work out what the reuse development flow is going to be.

assuming a user is building nested workflows on a non-clustered swamp (or even a non-swamp-serve setup) - I suspect they're likely (like i was hoping) to expect that when a workflow calls another workflow, that the child runs where the parent does - for eg the caddy workflow calls the systemd-service workflow to make a service with it's bits - on whatever host the caddy workflow was told to do so on.

but ... idk - I just feel unsure - and i hope that whatever solution is planned makes it in everyone's face obvious how something built with an understanding of one swamp topology will function in the other topologies that the author might not yet be aware of.

Sign in to post a ripple.