Skip to content

Commit 8a47c72

Browse files
jayleatonclaude
andcommitted
fix(server): leaving an agent no longer keeps the agent's old thread
Moving an agent task to Continue or Fresh session with no thread chosen sent profileId: null and threadId: null, and the save coalesced the null back to the agent's thread. Later runs then went into that conversation with its model and modes. Leaving an agent with an explicit null thread now clears the binding; an omitted threadId still keeps it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 6da755c commit 8a47c72

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

‎apps/server/src/scheduledTasks/ScheduledTaskService.profile.test.ts‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,21 @@ it.effect(
141141
overrideFields: ["runtimeMode"],
142142
});
143143
assert.equal(launches[1]?.runtimeMode, "approval-required");
144+
145+
// Leaving the agent for an unbound continuing thread drops the agent's thread.
146+
const plain = yield* service.upsert({
147+
...input,
148+
id: task.id,
149+
profileId: null,
150+
threadId: null,
151+
threadMode: "continue",
152+
});
153+
assert.isUndefined(plain.task.profileId);
154+
assert.isNull(plain.task.threadId);
155+
yield* service.runNow({ id: task.id });
156+
assert.equal(launches.length, 3);
157+
assert.isUndefined(launches[2]?.profileSelection);
158+
assert.equal(sends.length, 1);
144159
}).pipe(Effect.provide(ScheduledTaskService.layer.pipe(Layer.provide(dependencies))));
145160
}).pipe(Effect.provide(memoryDatabase)),
146161
);

‎apps/server/src/scheduledTasks/ScheduledTaskService.ts‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1491,7 +1491,14 @@ export const layer = Layer.effect(
14911491
profileId !== undefined && requestedThreadMode === "new_thread"
14921492
? "continue"
14931493
: requestedThreadMode;
1494-
const keptThreadId = input.threadId ?? existingTask?.threadId ?? null;
1494+
// The agent owned its thread, so leaving it with an explicit null thread starts fresh.
1495+
const leftAgentUnbound =
1496+
input.profileId === null &&
1497+
input.threadId === null &&
1498+
existingTask?.profileId !== undefined;
1499+
const keptThreadId = leftAgentUnbound
1500+
? null
1501+
: (input.threadId ?? existingTask?.threadId ?? null);
14951502
// A bound thread belongs to its project, so moving the task leaves it for a new one.
14961503
const movedOffThread =
14971504
existingTask !== null &&

0 commit comments

Comments
 (0)