6.2 KiB
Runtime Refactor and Prompt Centralization Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Refactor CrewAI runtime into reusable modules, centralize all prompt text under core/agent/prompt, and diagnose flaky front-tool interrupt behavior without adding hardcoded runtime heuristics.
Architecture: Keep runtime.py as a thin facade and move parsing/tool/prompt composition/stage execution into cohesive modules. Prompt strings (including stage contracts and injected tool-context instructions) are generated exclusively by prompt-module functions. Keep behavior equivalent by default; only add diagnostic observability for flaky live scenario analysis.
Tech Stack: Python 3.12, FastAPI backend, CrewAI, Pydantic v2, pytest, ruff, basedpyright.
Task 1: Add prompt module and centralize all runtime prompt text
Files:
- Create:
backend/src/core/agent/prompt/__init__.py - Create:
backend/src/core/agent/prompt/runtime_stage_prompts.py - Modify:
backend/src/core/agent/infrastructure/crewai/runtime.py - Test:
backend/tests/unit/core/agent/test_crewai_runtime.py
Step 1: Write failing test
- Add unit test asserting runtime uses prompt builder output (not inline literals) for stage description/contract/tool context.
Step 2: Run test to verify it fails
- Run:
uv run pytest backend/tests/unit/core/agent/test_crewai_runtime.py::test_runtime_uses_prompt_module_for_stage_descriptions -q - Expected: FAIL because runtime still composes inline strings.
Step 3: Implement prompt module
- Add prompt functions:
build_stage_output_contract(stage: str) -> strbuild_stage_task_description(...) -> strbuild_intent_multimodal_prompt(...) -> str
- Use mainstream prompt structure: role/objective/context/constraints/output-format.
- Keep rules non-hardcoded and behavior-oriented, avoid keyword-triggered branching rules.
Step 4: Wire runtime to prompt functions
- Replace inline prompt strings in runtime with prompt-module function calls.
- Ensure no prompt literals remain in runtime except minimal wiring labels.
Step 5: Run tests
- Run:
uv run pytest backend/tests/unit/core/agent/test_crewai_runtime.py -q - Expected: PASS.
Task 2: Split runtime into reusable modules and keep facade stable
Files:
- Create:
backend/src/core/agent/infrastructure/crewai/runtime_models.py - Create:
backend/src/core/agent/infrastructure/crewai/runtime_parsers.py - Create:
backend/src/core/agent/infrastructure/crewai/runtime_tools.py - Create:
backend/src/core/agent/infrastructure/crewai/runtime_stage_runner.py - Modify:
backend/src/core/agent/infrastructure/crewai/runtime.py - Modify:
backend/src/core/agent/infrastructure/crewai/__init__.py(if needed) - Test:
backend/tests/unit/core/agent/test_crewai_runtime.py
Step 1: Write failing test
- Add/adjust unit test that imports
CrewAIRuntimefacade and verifies existing contract (execute,map_events,is_registered_backend_tool) still works after split.
Step 2: Run test to verify it fails
- Run:
uv run pytest backend/tests/unit/core/agent/test_crewai_runtime.py::test_runtime_facade_contract_stable_after_refactor -q - Expected: FAIL before module split wiring.
Step 3: Extract models/parsers/tools/stage-runner
- Move Pydantic result models to
runtime_models.py. - Move parse/normalize helpers to
runtime_parsers.py. - Move tool normalization, routing tool class, pending-front-tool extraction to
runtime_tools.py. - Move
_run_stage_with_crewai+ usage extraction toruntime_stage_runner.py.
Step 4: Keep runtime facade thin
runtime.pyretains orchestration flow and public API only.- Import and compose extracted modules; no behavior change intended.
Step 5: Run tests
- Run:
uv run pytest backend/tests/unit/core/agent/test_crewai_runtime.py -q - Expected: PASS.
Task 3: Diagnose front-tool interrupt instability with explicit observability
Files:
- Modify:
backend/src/core/agent/infrastructure/crewai/runtime.py - Modify:
backend/src/core/agent/infrastructure/crewai/runtime_stage_runner.py - Modify:
backend/tests/e2e/test_agent_live_flow.py - Modify:
docs/bugs/2026-03-08-backend-tool-no-events.md
Step 1: Add failing/diagnostic assertion in live test path
- Extend test to capture and print structured diagnostics when
pending_tool_call_idisNone:- intent/execution raw+structured output
- tool payload injected into prompts
- captured tool calls list
Step 2: Run targeted live test for evidence
- Run:
AGENT_LIVE_E2E=1 uv run pytest backend/tests/e2e/test_agent_live_flow.py::test_agent_live_front_tool_interrupt_resume_continue -v -rs - Expected: still flaky/fail, but with actionable diagnostics.
Step 3: Analyze evidence and apply non-hardcoded fix
- If input ambiguity: refine test input prompt text under test fixture.
- If tool-description injection issue: fix prompt-builder injection logic.
- Do not add keyword heuristics in runtime branching.
Step 4: Re-run live targeted test
- Same command as Step 2.
- Expected: improved stability or clearly documented unresolved root cause.
Step 5: Update bug doc
- Add root-cause findings and next actions under Bug 3 section.
Task 4: Full verification and hygiene
Files:
- Modify (if needed):
backend/tests/unit/core/agent/test_run_resume_service.py
Step 1: Run impacted unit suites
uv run pytest backend/tests/unit/core/agent/test_crewai_runtime.py -quv run pytest backend/tests/unit/core/agent/test_run_resume_service.py -q
Step 2: Run lint/type checks
uv run ruff check backend/src/core/agent/prompt backend/src/core/agent/infrastructure/crewai backend/tests/unit/core/agent/test_crewai_runtime.py backend/tests/e2e/test_agent_live_flow.pyuv run basedpyright backend/src/core/agent/prompt backend/src/core/agent/infrastructure/crewai backend/tests/unit/core/agent/test_crewai_runtime.py
Step 3: Optional live regression pack (if env ready)
AGENT_LIVE_E2E=1 uv run pytest backend/tests/e2e/test_agent_live_flow.py -m live -v -rs
Step 4: Report residual risk
- If live still flaky, report exact failure mode and captured diagnostics (no workaround heuristics).