Summary
The workflow schema documents and parses a hooks: block with on_start, on_complete, and on_error lifecycle hooks (see docs/workflow-syntax.md, "Hooks"), but the feature is effectively dead code: hook templates are rendered and then discarded. Nothing observes the result.
Current state
Schema & docs — HooksConfig is defined in src/conductor/config/schema.py (~line 597) with three optional template strings, and documented as:
hooks:
on_start: "{{ template }}" # Optional: Expression evaluated on start
on_complete: "{{ template }}" # Optional: Expression evaluated on success
on_error: "{{ template }}" # Optional: Expression evaluated on error
Engine — WorkflowEngine._execute_hook (src/conductor/engine/workflow.py, ~line 5477) is called from ~12 sites (run(), resume(), the on_complete paths in _execute_loop, and on_error). It:
- Renders the Jinja2 template against the workflow context (plus
result / error for the respective hooks).
- Returns a
LifecycleHookResult(executed=True, result=rendered).
The gap — every call site ignores the returned value. The rendered string is not:
- emitted as an event (no
hook_executed / similar in the event vocabulary),
- written to the JSONL event log,
- shown on the dashboard or console,
- stored in the workflow context,
- used for any side effect (no notification, no script execution, nothing).
Hook render errors are swallowed by design ("should not fail the workflow"), which is reasonable — but combined with the discarded result it means a hook is completely unobservable, including when it fails. There is also no test coverage asserting any observable behavior, because there is none to assert.
History
The hooks block was introduced in the very first commit of the repository and has never been wired to anything. No open issue tracks plans for it.
Proposal
Remove the dead code:
- Drop
HooksConfig and WorkflowDef.hooks from config/schema.py (plus re-exports in config/__init__.py).
- Drop
WorkflowEngine._execute_hook, LifecycleHookResult, and all call sites in engine/workflow.py.
- Remove the Hooks section from
docs/workflow-syntax.md.
Removing unused, unobservable surface area is good hygiene: it stops misleading workflow authors into believing the block does something, and shrinks the schema the validator and docs must maintain.
If hooks are needed later
Lifecycle hooks are plausibly useful one day (notifications on completion, error alerting, audit trails). But when a concrete requirement arrives, the right syntax will likely differ from "render a template and throw it away" — e.g. emitting an event, invoking a type: script step, or calling a webhook. It is cheaper to design that syntax against a real requirement than to preserve a placeholder whose semantics were never defined.
Acceptance criteria
Summary
The workflow schema documents and parses a
hooks:block withon_start,on_complete, andon_errorlifecycle hooks (seedocs/workflow-syntax.md, "Hooks"), but the feature is effectively dead code: hook templates are rendered and then discarded. Nothing observes the result.Current state
Schema & docs —
HooksConfigis defined insrc/conductor/config/schema.py(~line 597) with three optional template strings, and documented as:Engine —
WorkflowEngine._execute_hook(src/conductor/engine/workflow.py, ~line 5477) is called from ~12 sites (run(),resume(), theon_completepaths in_execute_loop, andon_error). It:result/errorfor the respective hooks).LifecycleHookResult(executed=True, result=rendered).The gap — every call site ignores the returned value. The rendered string is not:
hook_executed/ similar in the event vocabulary),Hook render errors are swallowed by design ("should not fail the workflow"), which is reasonable — but combined with the discarded result it means a hook is completely unobservable, including when it fails. There is also no test coverage asserting any observable behavior, because there is none to assert.
History
The hooks block was introduced in the very first commit of the repository and has never been wired to anything. No open issue tracks plans for it.
Proposal
Remove the dead code:
HooksConfigandWorkflowDef.hooksfromconfig/schema.py(plus re-exports inconfig/__init__.py).WorkflowEngine._execute_hook,LifecycleHookResult, and all call sites inengine/workflow.py.docs/workflow-syntax.md.Removing unused, unobservable surface area is good hygiene: it stops misleading workflow authors into believing the block does something, and shrinks the schema the validator and docs must maintain.
If hooks are needed later
Lifecycle hooks are plausibly useful one day (notifications on completion, error alerting, audit trails). But when a concrete requirement arrives, the right syntax will likely differ from "render a template and throw it away" — e.g. emitting an event, invoking a
type: scriptstep, or calling a webhook. It is cheaper to design that syntax against a real requirement than to preserve a placeholder whose semantics were never defined.Acceptance criteria
hooks:removed from the workflow schema (parsing a workflow that declares it produces a clear validation error)._execute_hook/LifecycleHookResultand all call sites removed from the engine.docs/workflow-syntax.md.