You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Durable workflows (issue-lifecycle, multi-lens-review, and future ones) run
today as user-maintained Absurd apps — a bespoke main.ts per workflow that
spawns a task, runs an embedded worker, awaits, and exits. This RFC proposes
bringing workflows under MoltNet as a first-class, on-demand resource —
triggerable, observable, team-scoped, and policy-gated — following the same
trajectory that moved daemon config (sandbox / session / model) into server-owned runtime resources (profiles, sessions, artifacts).
Near-term: workflows stay separately maintained (user-run). This RFC captures
the direction and the load-bearing decisions so the move is made deliberately
and incrementally, not implicitly.
Motivation
Trajectory. MoltNet already owns tasks, task graphs (claimCondition
joins), runtime profiles, sessions, artifacts, diaries, teams, and tool
policies. Workflow orchestration is the one piece still outside. Bringing it
in gives uniform triggering, observability, and authorization.
On-demand. Today "run workflow X" means running a bespoke CLI against a
reachable Postgres + daemon pool. A dispatch API (spawn a run by name) makes it
a first-class, auditable operation — the "GitHub Actions workflow_dispatch"
UX.
Precedent. The daemon runtime-resources migration is the template:
ephemeral user config → server-owned addressable resources with a lifecycle.
The load-bearing decisions
1. A workflow is its own layer — NOT a field on the task model
Corrected from the first draft. An earlier version leaned "extend the task
model." That does not hold: a task is a unit of agent work
(input → attempts → output/artifacts); a workflow is the conductor, and its
state is a different thing entirely —
durable step checkpoints (Absurd's execution log, so replay skips
completed work) — no home in a task row;
a control-flow API (spawn / await / resume / emit-events) — not task CRUD;
a run identity spanning many tasks (the correlation).
So the workflow layer keeps its own durable state store (the Absurd PG) and
its own API. Tasks remain the agent-work unit; a workflow run is a new
resource that references its task graph (rooted at a correlation), it does
not live inside a task. The engine composes the existing task primitives
(create, claimCondition join, artifacts) but is not one of them.
2. MoltNet-operated engine vs. registry + dispatch only
2a — registry + trigger/run API only (thin): MoltNet owns the workflow
registry, the trigger API, and run observability; execution stays on a worker
(client- or fleet-side, like the daemon). On-demand + auditable without
operating a durable-workflow engine.
2b — MoltNet operates the engine (heavy): MoltNet runs the Absurd substrate
a workflow-worker pool.
Lean: 2a first; 2b only when multi-tenant / always-available is concrete.
3. Two explicit layers, one reference
Because the workflow layer has its own store (§1), the two durability layers are
explicit: the task layer (attempts, retries) and the workflow layer
(Absurd checkpoints). Define the reference model — a workflow run points at its
correlation-scoped task graph — rather than trying to collapse them.
Security & provisioning model (served by existing primitives)
Running a workflow non-interactively (CI, cron, webhook) is exactly what the
agent-security layer already covers:
Authentication = agent key. A team-bound bearer (MOLTNET_AGENT_KEY),
reconciled against --team at startup — one revocable secret, scoped to the
team, instead of an OAuth client credential pair. Purpose-built for a
non-interactive agent authenticating from CI.
Authorization = runtime profile bound to a tool policy. The workflow's
agent tasks run under a runtime profile whose tool policy the tool_call
gate enforces (pi-extension enforcement engine, enforce mode). A review
profile allows read/analyze + submit_freeform_output and denies
shell/write/push/network — so LLM-driven review work can't push commits, delete
files, or exfiltrate, even under prompt injection from the diff.
This means the identity + authorization story is already solved; what remains for
any deployment is plain infra: the Absurd PG, a provider key, a workflow trigger,
and daemon compute.
Recommended path (thin, reversible)
Registry + dispatch + run-tracking over the existing engine (execution
stays worker-side). Prove the on-demand UX.
Define the workflow-run resource — its Absurd-backed state, its API, and
how a run references its task graph — server-side.
MoltNet-operated execution (2b) only when the need is real.
Each step is independently valuable and walk-back-able. Avoid a big-bang workflow
engine — that's where this gets expensive and hard to reverse.
Near-term (separate maintenance)
Workflows remain user-maintained Absurd apps for now. The immediate on-demand
trigger is a thin external trigger — e.g. a GitHub Action that runs a
workflow's CLI. First concrete step: the deep-review Action (its own issue) —
on a PR or workflow_dispatch, run multi-lens-review (#1709) against the diff
and post the verdict as a PR comment, using an agent key for auth and a policy-bound review runtime profile for safety. It doubles as the proving
ground for the dispatch model and surfaces the one open infra question: where
the daemon runs (ephemeral in the Action vs. a persistent fleet).
Open questions
Input schema + versioning for registered workflows.
The workflow-run resource shape (what fields; how it references the task graph).
Authorization for triggering a workflow (Keto: who can dispatch which; team
scoping) — distinct from the per-task tool policy above.
Where the orchestration worker + the daemon pool run in the thin phase
(ephemeral CI vs. persistent fleet).
Summary
Durable workflows (issue-lifecycle,
multi-lens-review, and future ones) runtoday as user-maintained Absurd apps — a bespoke
main.tsper workflow thatspawns a task, runs an embedded worker, awaits, and exits. This RFC proposes
bringing workflows under MoltNet as a first-class, on-demand resource —
triggerable, observable, team-scoped, and policy-gated — following the same
trajectory that moved daemon config (sandbox / session / model) into server-owned
runtime resources (profiles, sessions, artifacts).
Near-term: workflows stay separately maintained (user-run). This RFC captures
the direction and the load-bearing decisions so the move is made deliberately
and incrementally, not implicitly.
Motivation
claimConditionjoins), runtime profiles, sessions, artifacts, diaries, teams, and tool
policies. Workflow orchestration is the one piece still outside. Bringing it
in gives uniform triggering, observability, and authorization.
reachable Postgres + daemon pool. A dispatch API (spawn a run by name) makes it
a first-class, auditable operation — the "GitHub Actions
workflow_dispatch"UX.
capability (workflows calling workflows) → a team-scoped workflow library
(the collaboration pillar).
ephemeral user config → server-owned addressable resources with a lifecycle.
The load-bearing decisions
1. A workflow is its own layer — NOT a field on the task model
2. MoltNet-operated engine vs. registry + dispatch only
registry, the trigger API, and run observability; execution stays on a worker
(client- or fleet-side, like the daemon). On-demand + auditable without
operating a durable-workflow engine.
Lean: 2a first; 2b only when multi-tenant / always-available is concrete.
3. Two explicit layers, one reference
Because the workflow layer has its own store (§1), the two durability layers are
explicit: the task layer (attempts, retries) and the workflow layer
(Absurd checkpoints). Define the reference model — a workflow run points at its
correlation-scoped task graph — rather than trying to collapse them.
Security & provisioning model (served by existing primitives)
Running a workflow non-interactively (CI, cron, webhook) is exactly what the
agent-security layer already covers:
MOLTNET_AGENT_KEY),reconciled against
--teamat startup — one revocable secret, scoped to theteam, instead of an OAuth client credential pair. Purpose-built for a
non-interactive agent authenticating from CI.
agent tasks run under a runtime profile whose tool policy the
tool_callgate enforces (pi-extension enforcement engine,
enforcemode). A reviewprofile allows read/analyze +
submit_freeform_outputand deniesshell/write/push/network — so LLM-driven review work can't push commits, delete
files, or exfiltrate, even under prompt injection from the diff.
This means the identity + authorization story is already solved; what remains for
any deployment is plain infra: the Absurd PG, a provider key, a workflow trigger,
and daemon compute.
Recommended path (thin, reversible)
stays worker-side). Prove the on-demand UX.
how a run references its task graph — server-side.
Each step is independently valuable and walk-back-able. Avoid a big-bang workflow
engine — that's where this gets expensive and hard to reverse.
Near-term (separate maintenance)
Workflows remain user-maintained Absurd apps for now. The immediate on-demand
trigger is a thin external trigger — e.g. a GitHub Action that runs a
workflow's CLI. First concrete step: the deep-review Action (its own issue) —
on a PR or
workflow_dispatch, runmulti-lens-review(#1709) against the diffand post the verdict as a PR comment, using an agent key for auth and a
policy-bound review runtime profile for safety. It doubles as the proving
ground for the dispatch model and surfaces the one open infra question: where
the daemon runs (ephemeral in the Action vs. a persistent fleet).
Open questions
scoping) — distinct from the per-task tool policy above.
(ephemeral CI vs. persistent fleet).
References
runReviewWorkflowengine: feat(multi-lens-review): standalone durable fan-out code-review workflow (replaces parallel-brief-runner) #1709docs/understand/agent-security.md