Treat a step-executor timeout with an active remote job as a waiting handoff - #222
Merged
Merged
Conversation
… an active remote job
…tor and flash mode
Copilot created this pull request from a session on behalf of
ruoyuwang1995nya
July 28, 2026 08:24
View session
ruoyuwang1995nya
marked this pull request as ready for review
July 30, 2026 01:57
ruoyuwang1995nya
approved these changes
Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A step executor has a fixed 3600s wall-clock timeout, but an e2b job it submits is durable and tracked independently by
RemoteJobStore+RemoteJobMonitor. Previously any timeout returnedneeds_replanning, which the orchestrator turned into a terminalfailednode with blocked dependents — even while the job was still running — and re-attachment then only worked by luck, if the replacement plan happened to reuse the same node id and template so the submission idempotency key matched.The
waitingstate and_active_remote_joblookup that solve this already existed, but only ran on process-restart reconciliation. This routes the live-timeout path into that same seam rather than extending or removing the timeout (which would make a bounded LLM session the single point of failure for an arbitrarily long job).Timeout path (
step_executor_runner.py)_await_step_completionreplacesasyncio.wait_for, so a timeout no longer unconditionally kills the executor.STEP_REMOTE_JOB_GRACE_TIMEOUT, default 300s) for nearly-finished work, then releases the executor and returnsstatus: "waiting"instead ofneeds_replanning._mark_node_waiting_on_remote_jobwrites the status and job identity directly onto the graph node, so the handoff doesn't depend on the orchestrator LLM callingset_node_status.Deterministic re-attachment
recovery.py: newactive_remote_job_for_attempt()reloads the persisted job reference (record_remote_job_referencewrites through the durable record, so a live attempt only learns of it on its next heartbeat).reconcile_recovery_statenow handleswaitingattempts — node stayswaitingwhile the job is in progress, returns topendingonce it settles so a fresh executor collects results. A planner-initiated resume is explicitly not undone; without that guard the retry would deadlock._remote_job_prior_contextinjects the job identity and explicit re-attach instructions into the retry executor's context, replacing reliance on an accidental idempotency-key match.get_ready_nodessurfacesremote_jobon ready nodes and reportswaiting_nodes; orchestrator, planner, and step-executor instructions updated to treatwaitingas a handoff, not a failure.Flash mode
run_flash_step's fallback node id wasflash_{counter}with an incrementing counter, so a retry got a fresh id, broke the idempotency key, and could submit a duplicate sandbox. Now derived from the action:Notes
SUB_STEP_TIMEOUTis unchanged; the grace window is deliberately secondary.succeeded/collectingare excluded from the "still in progress" set used to decide waiting-vs-pending — those mean results are ready, which is exactly when the node should run again.waitingadded tograph_logger's node status literal;docs/remote_job_monitoring.mdupdated.