Skip to content

Remove dead workflow lifecycle hooks (on_start / on_complete / on_error) #476

Description

@hertznsk

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 & docsHooksConfig 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

EngineWorkflowEngine._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:

  1. Renders the Jinja2 template against the workflow context (plus result / error for the respective hooks).
  2. 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:

  1. Drop HooksConfig and WorkflowDef.hooks from config/schema.py (plus re-exports in config/__init__.py).
  2. Drop WorkflowEngine._execute_hook, LifecycleHookResult, and all call sites in engine/workflow.py.
  3. 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

  • hooks: removed from the workflow schema (parsing a workflow that declares it produces a clear validation error).
  • _execute_hook / LifecycleHookResult and all call sites removed from the engine.
  • Hooks section removed from docs/workflow-syntax.md.
  • CHANGELOG entry noting the removal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions