Skip to content

[Fix] Follow-ups start disconnected tasks after delegated work completes - #1633

Draft
roomote-roomote[bot] wants to merge 1 commit into
developfrom
fix/resume-settled-tasks-0d9lkwukovh9t
Draft

[Fix] Follow-ups start disconnected tasks after delegated work completes#1633
roomote-roomote[bot] wants to merge 1 commit into
developfrom
fix/resume-settled-tasks-0d9lkwukovh9t

Conversation

@roomote-roomote

Copy link
Copy Markdown
Contributor

​Opened on behalf of @mrubens. Follow up by mentioning @roomote-roomote, in the web UI, or in Slack.

What changed

Task follow-up discovery now uses one shared lifecycle predicate for active runs and settled runs with resumable snapshots. The canonical task-message path serializes resume creation, rechecks lifecycle state when sandbox delivery races with settlement, and deduplicates retries using a stable delivery ID.

Fast remains a thin adapter: it presents session-scoped follow-up candidates, supplies the delivery ID, and calls the existing task-message endpoint. Snapshot restoration continues to create an internal run under the existing task, preserving task history, workspace metadata, and task-linked status surfaces.

Why this change was made

A follow-up sent just after delegated work settled could be rejected or routed as unrelated work even though the completed run had a valid snapshot. Concurrent retries could also race to create multiple resume runs.

Impact

Users can continue recently settled delegated work through the same task and conversation. Active follow-ups retain existing steering behavior, expired or missing snapshots remain non-resumable, and renewable contention leases prevent duplicate resume creation during slow enqueue operations.

@roomote-community

roomote-community Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

2 issues outstanding. See task

  • Discord follow-ups reuse a conversation-level delivery ID, so a second instruction can be acknowledged and dropped while a resume is pending. (packages/cloud-agents/src/server/fast-agent/fast-agent-service.ts:1127)
  • Resumable-task discovery includes canceled and snapshot-failed runs. (packages/db/src/lib/task-run-continuation.ts:25)

Reviewed 0a402fc

isNull(columns.canceledAt),
),
and(
inArray(columns.status, [...exitedRunStatuses]),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The settled-run branch does not exclude canceledAt or snapshotFailedAt. A canceled task retains its snapshot, so a later Fast session now lists it as resumable and can reopen a task the user explicitly canceled; similarly, a snapshot whose creation failed is advertised despite being unusable. Existing completed-run lookups require both fields to be null. Include those guards in this shared predicate and select the failed-at column at the call site.

{
taskId: target.taskId,
message: args.message,
clientMessageId: `fast-agent:${session.id}:${currentMessageId ?? conversation.conversationId}:${target.taskId}`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currentMessageId falls back to conversation.conversationId, but the Discord caller never supplies currentMessageId even though it has message.id. Every Discord follow-up to the same task therefore gets the same delivery ID. If a second message arrives while the first snapshot resume is pending, hasMatchingResumeDelivery treats it as a retry and returns success without delivering the second instruction. Pass the Discord message ID through (or generate a per-turn ID) before building this value.

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.

1 participant