Skip to content

Core SDK: consolidate duplicated workflow engine in memory/workflows.py (~1,983 LOC) into a re-export of workflows/workflows.py #2117

Description

@MervinPraison

Summary

The core SDK ships two independent copies of the workflow engine. praisonaiagents/memory/workflows.py (1,983 LOC) defines its own WorkflowContext, StepResult, the pattern helpers (Route, Parallel, Loop, Repeat, route, parallel, loop, repeat), a full Workflow class and a full WorkflowManager class. The canonical engine now lives in praisonaiagents/workflows/workflows.py (4,531 LOC) and is newer/feature-richer. This is duplicate logic with drift, not a feature.

This is a structural consolidation only — every public import path and behaviour is preserved.

Current behaviour

  • Canonical engine: praisonaiagents/workflows/workflows.py (4,531 LOC) — the version exported everywhere.
  • Stale duplicate: praisonaiagents/memory/workflows.py (1,983 LOC) — separate WorkflowContext/StepResult dataclasses, Workflow (lines ~182–719) and WorkflowManager (lines ~720–1968).
  • praisonaiagents/memory/__init__.py already re-exports all workflow symbols from ..workflows, not from memory.workflows:
    • praisonaiagents/memory/__init__.py:96from ..workflows import WorkflowManager
    • lines 99–135 → Workflow, Task, WorkflowContext, StepResult, Pipeline, Route, Parallel, Loop, Repeat, route, parallel, loop, repeat all sourced from ..workflows
    • line 155 → create_workflow_manager from ..workflows.workflows
  • So from praisonaiagents.memory import Workflow / WorkflowManager already resolves to the canonical engine. The 1,983 LOC file is reachable only via the explicit module path praisonaiagents.memory.workflows.

No production module imports memory.workflows. The only references are tests asserting the backward-compatible path still works:

  • tests/test_workflow_patterns.py:462from praisonaiagents.memory.workflows import (Workflow, Task, WorkflowContext, StepResult, route, parallel, loop, repeat)
  • tests/unit/test_paths_wiring.py:289+ — inspects workflows.WorkflowManager source for DEFAULT_DIR_NAME / _get_checkpoints_dir paths wiring.

Why it matters

  • Maintenance: every workflow fix/feature must be applied in two places or silently diverge. The duplicate is already stale relative to workflows/workflows.py (e.g. newer route/parallel/output_file parsing paths exist only in the canonical file).
  • Correctness risk: a user importing via praisonaiagents.memory.workflows gets the older implementation, while praisonaiagents.memory gives the newer one — same names, different behaviour.

Category

Duplicate logic

Capability preserved

  • from praisonaiagents.memory.workflows import Workflow, Task, WorkflowContext, StepResult, route, parallel, loop, repeat keeps working (backward-compatible path).
  • from praisonaiagents.memory import Workflow, Pipeline, WorkflowManager, ... keeps working (already routed to canonical).
  • All workflow patterns (Route/Parallel/Loop/Repeat), WorkflowManager, checkpoints, and paths-wiring behaviour unchanged.

Proposed approach

Turn memory/workflows.py into a thin re-export shim that imports the canonical symbols from praisonaiagents.workflows.workflows, deleting the duplicated bodies. This collapses ~2,000 LOC to a few lines while keeping the legacy import path alive.

Resolution sketch

# Before: praisonaiagents/memory/workflows.py  (1,983 LOC)
@dataclass
class WorkflowContext: ...
class Workflow: ...          # full duplicate body
class WorkflowManager: ...   # full duplicate body

# After: praisonaiagents/memory/workflows.py  (thin shim, same public names)
"""Backward-compatible re-export. Canonical engine lives in
praisonaiagents.workflows.workflows."""
from ..workflows.workflows import (  # noqa: F401
    WorkflowContext, StepResult, Workflow, WorkflowManager,
    Route, Parallel, Loop, Repeat,
    route, parallel, loop, repeat,
    create_workflow_manager,
)
from ..task.task import Task  # noqa: F401

Severity

Medium

Validation

  • Traced: memory/__init__.py re-exports workflow symbols from ..workflows, never from memory.workflows; no production code imports memory.workflows.
  • Confirmed the only consumers of the explicit module path are backward-compat tests (tests/test_workflow_patterns.py, tests/unit/test_paths_wiring.py).
  • Confirmed this is duplication/drift, not two intentional engines — both define the same public surface; the canonical one is the superset.
  • Before merging, verify the canonical workflows.WorkflowManager still satisfies tests/unit/test_paths_wiring.py (uses DEFAULT_DIR_NAME, no hard-coded ".praisonai/workflows", _get_checkpoints_dir routed through paths.py); if any wiring assertion is specific to the old copy, port it onto the canonical class as part of the shim change.

Keep unchanged

  • The canonical praisonaiagents/workflows/workflows.py engine and its full feature set.
  • All public import paths (praisonaiagents.memory, praisonaiagents.memory.workflows, praisonaiagents.workflows).
  • Lazy-loading behaviour in memory/__init__.py.

Metadata

Metadata

Assignees

No one assigned

    Labels

    claudeAuto-trigger Claude analysis

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions