Skip to content

State control signals: Skip and TryAfter #288

@NiveditJain

Description

@NiveditJain

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=true and a reason
    • Dependents receive no outputs by default; allow opt-in pass-through if provided
  • TryAfter(delay_s?: int, retry_at?: ISO8601, reason?: str)

    • Treat as a soft failure that schedules a retry
    • Increment attempt and set next_retry_at using 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}/complete body { 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 EXECUTED with metadata.skipped=true
  • For TryAfter set ERRORED with next_retry_at and 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 SkipState and TryAfter
  • Server persists and acts on signals exactly once per attempt
  • No new public state names are introduced
  • Docs include short examples for both signals

Metadata

Metadata

Assignees

Labels

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions