Skip to content

feat(workflows): per-attempt task timeout and continue-on-error - #212

Merged
Tsuyoshi Ushio (TsuyoshiUshio) merged 4 commits into
mainfrom
tsuyoshiushio-workflow-task-timeout-continuation
Sep 16, 2026
Merged

Tsuyoshi Ushio (TsuyoshiUshio) merged 4 commits into
mainfrom
tsuyoshiushio-workflow-task-timeout-continuation

Conversation

@TsuyoshiUshio

@TsuyoshiUshio Tsuyoshi Ushio (TsuyoshiUshio) commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Limit the wait for each task attempt and let a workflow continue after selected task failures.

Scope

Design only. This PR updates docs/frds/0004-dynamic-workflows.md. It does not change runtime code.

The implementation uses two stacked PRs:

Order Scope
1 execution.timeout, @workflow_tool(timeout=...), per-field precedence, and the Activity deadline
2 Plan-only execution.continue_on_error, bounded failure results, and continuation in both schedulers

Each implementation PR includes tests, sample coverage, and user documentation. Telemetry, status changes, and UI changes are separate later work.

Design rules

  • Use handler_transient with workflow_task_timeout; do not add a failure kind.
  • If neither plan nor decorator declares retry, use one attempt with no retry delay.
  • Preserve existing failure and cancellation order for waves without enabled continuation.
  • Stop on authorization failures, contract failures, and unclassified Durable failures.

Limits

The one-hour admission cap is a library validation rule, not an Azure execution guarantee. Hosting-plan limits and host.json settings also apply.

A timeout does not stop a running tool thread. Workflows must finish or be terminated before a runtime downgrade.

The retry foundation this slice depended on landed through PRs #193 and #207
rather than through the stale PR #186 branch, whose versions of `schema.py`,
`activity.py`, and `engine.py` now conflict with the shipped contracts
wholesale. Record the remaining timeout and continue-on-error slice as a clean
reimplementation against current `main` instead of a rebase.

The design makes all three `execution` fields optional so a deadline can be
declared alone, resolves `@workflow_tool` precedence per field, bounds one
attempt at the Activity boundary under a new retryable `timeout`
classification, and lets a declared-continuation node commit a bounded
controlled-failure result so its dependents run.

Fail-fast is preserved for everything that cannot be continued: the wave
selection loop keeps awaiting only when the completed instance both declared
continuation and failed continuably, so a non-continuable failure never waits
behind a slow sibling or a long timer. Both persisted keys are written only
when authored, so a task that declares neither freezes and replays the payload
the retry-only runtime wrote.

An independent architecture review raised four blocking findings — whole-wave
collection, unaddressed downgrade, an underspecified continuation contract, and
missing coverage of mixed waves, cancellation races, and `for_each` failure
shapes. Decisions 88 and 92-96 and the expanded test plan resolve them.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f32b40a3-603f-48d9-ad29-43179afe265b
Comment thread docs/frds/0004-dynamic-workflows.md
Comment thread docs/frds/0004-dynamic-workflows.md
Comment thread docs/frds/0004-dynamic-workflows.md
@TsuyoshiUshio
Tsuyoshi Ushio (TsuyoshiUshio) marked this pull request as ready for review September 15, 2026 06:00
Comment thread docs/frds/0004-dynamic-workflows.md
Comment thread docs/frds/0004-dynamic-workflows.md
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@TsuyoshiUshio
Tsuyoshi Ushio (TsuyoshiUshio) merged commit 8c8a682 into main Sep 16, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants