Skip to content

Python: Add reset() to workflow - #1

Draft
ShiyunXu wants to merge 3 commits into
benchmark-basefrom
python-workflow-reset
Draft

Python: Add reset() to workflow#1
ShiyunXu wants to merge 3 commits into
benchmark-basefrom
python-workflow-reset

Conversation

@ShiyunXu

Copy link
Copy Markdown
Owner

Motivation & Context

When a workflow is hosted as an agent (e.g. in a Foundry hosted-agent session), the workflow instance is built once when the session starts. A new interaction that doesn't carry a conversation/previous-response id should start a fresh run without any residual state from prior interactions. Today that requires rebuilding the workflow from the builder, which isn't possible when the instance is long-lived.

This adds Workflow.reset(), which restores a workflow instance to its captured initial state so the same instance can be reused for a clean run.

Description & Review Guide

This is the next slice of breaking down microsoft#6407 into smaller PRs (following the runner/workflow refactor and the per-executor serialization PRs).

  • What are the major changes?

    • Add Workflow.reset(). It restores the instance to an in-memory baseline checkpoint captured once per instance ({"kind": "initial_in_memory"}) via _ensure_initial_checkpoint(). The baseline is captured lazily just before the first run (or on first reset() if that comes first), so it always reflects the pristine just-built state. reset() is rejected with WorkflowException while a run is active.
    • Harden Runner.capture_checkpoint_object() to accept optional metadata and to reject capture while in-flight executor messages are present, raising WorkflowCheckpointException. Mid-superstep message state is not a clean, resumable baseline; capture is only valid when the runner is quiescent. Pending request_info events are intentionally not blocked, since idle-with-pending-requests is a stable point.
  • What is the impact of these changes?

    • A long-lived workflow instance can be reset between runs instead of rebuilt. No public API removals; reset() is additive.
    • capture_checkpoint_object() now enforces the quiescence precondition it always implied.
  • What do you want reviewers to focus on?

    • The baseline-capture timing (before first run vs. first reset()) and the reset() active-run guard.

Related Issue

Part of the microsoft#6407 breakdown.

Fixes #

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

Introduce Workflow.reset(), which restores a workflow instance to its
captured initial state so the same instance can be re-run cleanly (e.g.
in a hosted-agent session where the instance is created once). The
initial state is captured once per instance as an in-memory baseline
checkpoint before the first run; reset() is rejected while a run is
active.

Also harden Runner.capture_checkpoint_object() to accept optional
metadata and to reject capture while in-flight executor messages are
present (mid-superstep state is not a clean baseline), raising
WorkflowCheckpointException.

This is part of breaking down the changes in microsoft#6407 into smaller PRs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Describe the quiescence precondition (no in-flight executor messages) in
terms of checkpoint coherence rather than any specific caller, so the
contract does not assume the WorkflowExecutor is the only consumer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rather than the runner querying has_messages() to guard capture, put the
message-quiescence check where the messages live: the context's
create_checkpoint_object now rejects creation while in-flight executor
messages are present. The persisting create_checkpoint path (superstep
boundaries, which legitimately snapshot pending messages) shares a new
private _build_checkpoint helper and is not guarded. The runner's
capture_checkpoint_object just prepares executor state and delegates.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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