-
Notifications
You must be signed in to change notification settings - Fork 42
Description
Summary
Allow a node to emit control signals instead of a final output when special handling is needed. Initial signals: SkipState and TryAfter. Signals are interpreted by State Manager and do not introduce new public state names.
Signals
-
SkipState(reason: str, outputs?: any)- Record state as executed with
metadata.skipped=trueand a reason - Dependents receive no outputs by default; allow opt-in pass-through if provided
- Record state as executed with
-
TryAfter(delay_s?: int, retry_at?: ISO8601, reason?: str)- Treat as a soft failure that schedules a retry
- Increment attempt and set
next_retry_atusing provided delay or timestamp
SDK shape
-
Python SDK exposes helpers or exceptions:
exo.signals.skip(reason, outputs=None)exo.signals.try_after(delay_s=None, retry_at=None, reason=None)
-
Nodes either return a signal object or raise a typed Signal exception
API shape
-
Extend state completion to accept a signal
POST /api/states/{id}/completebody{ signal: { type: "TRY_AFTER", delay_s: 300, reason: "rate limit" } }- For
SkipState, body{ signal: { type: "SKIP", reason: "...", outputs: {...} } }
-
All writes are attempt-scoped and idempotent using
(state_id, attempt_id)
Behavior
- No new public statuses. For Skip record
EXECUTEDwithmetadata.skipped=true - For TryAfter set
ERROREDwithnext_retry_atand respect backoff rules - Metrics: count skips and try-after events; expose reasons in logs
Tests
- Skip returns immediately, dependents behave per default policy and pass-through option
- TryAfter schedules a retry for the same state with correct
next_retry_at - Idempotency across duplicate completion calls with the same
attempt_id
Acceptance criteria
- SDK can emit
SkipStateandTryAfter - Server persists and acts on signals exactly once per attempt
- No new public state names are introduced
- Docs include short examples for both signals
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Done