Summary
examples/templates/hourly_tracking/tools.py uses a module-global _correction_attempts counter. It persists across agent runs in the same Python process, so a second hourly run can skip the auto-fix loop and jump straight to human review incorrectly.
Evidence
_correction_attempts = 0
@tool
def correct_transactions() -> dict[str, Any]:
global _correction_attempts
_correction_attempts += 1
...
@tool
def validate_transactions() -> dict[str, Any]:
global _correction_attempts
requires_human_review = not validation_passed and _correction_attempts >= 1
Daemon / timer mode (--daemon, 60-min timer) reuses the same process → state leak.
Expected behavior
Correction attempt count resets per session or per timer tick.
Proposed fix (pick one)
- Reset counter at start of
fetch_transactions node via a small @tool reset_correction_state()
- Store count in session/shared memory keyed by run ID
- Use
contextvars scoped to execution stream
Avoid breaking mock demo path (first run still shows auto-fix → HITL escalation).
Acceptance criteria
Effort
~30 minutes
Related
#2 Hourly Tracking
Summary
examples/templates/hourly_tracking/tools.pyuses a module-global_correction_attemptscounter. It persists across agent runs in the same Python process, so a second hourly run can skip the auto-fix loop and jump straight to human review incorrectly.Evidence
Daemon / timer mode (
--daemon, 60-min timer) reuses the same process → state leak.Expected behavior
Correction attempt count resets per session or per timer tick.
Proposed fix (pick one)
fetch_transactionsnode via a small@tool reset_correction_state()contextvarsscoped to execution streamAvoid breaking mock demo path (first run still shows auto-fix → HITL escalation).
Acceptance criteria
./engine run examples/templates/hourly_tracking --input '{}'runs both follow the same validate → correct → HITL demo path./engine validate examples/templates/hourly_trackingpassesEffort
~30 minutes
Related
#2 Hourly Tracking