A daily agent task should not need a new sidebar entry every day. Separate conversations make individual runs easy to isolate, but they also scatter a task's history and fill the conversation list with repeated titles.
AIClaw 3.8.4 changes ordinary scheduled tasks to reuse their most recent execution conversation. The first run creates it; subsequent runs resume it and add a new turn. Existing tasks can continue from their saved lastSessionId without a separate migration. This is published behavior, with source links pinned to the release.
Reuse the conversation, keep each run distinct
The session manager chooses its destination according to the task mode:
| Mode | Conversation used |
|---|---|
| Ordinary scheduled task, stored as cron | The task's lastSessionId, when it is still an eligible conversation |
| Follow-up task | The explicitly selected sessionId |
For an ordinary task with no saved destination, the host creates a background conversation using the current application configuration and a task title. If the saved conversation still exists, is not a child-agent conversation, and is not archived, the host resumes it instead.
Resuming retains that conversation's model and history. Tool, skill, and approval configuration are refreshed through the existing resume mechanism. This means recurring execution now has conversational continuity; it does not promise a fresh context or a newly selected default model on every run.
The host does not switch the conversation the user is viewing. Its sidebar assignment hook assigns the scheduled-task group when a new destination is created. Reusing the same destination does not overwrite a later manual grouping choice.
Preserve the binding before starting asynchronous work
The scheduler stores task metadata in schedules.json. Previously, the start of an ordinary run cleared its lastSessionId while the host opened another conversation. The new start transition preserves the previous identifier while recording the new run as running.
That detail matters on failure. If resuming the conversation fails, the task still knows which conversation it intended to use. A later attempt can try that destination again instead of losing the association and creating another duplicate.
The host binds a newly selected destination before starting the agent turn. Run IDs and turn IDs remain separate from the conversation ID: reusing one conversation does not turn multiple scheduled executions into one indistinguishable running operation.
After the start receipt is recorded, completion matching includes the returned turn ID. The regression test checks that an older completed turn does not finish the newer run. This is not a claim of exactly-once execution across arbitrary crashes or missing receipts.
Missing history and unavailable runtime are different cases
The replacement rules are deliberately narrow:
- If an ordinary task's saved conversation has been deleted or archived, a new task conversation is created.
- If an eligible conversation exists but resuming it fails, that failure is reported; the host does not silently open a replacement.
- If an explicitly chosen follow-up conversation is missing or archived, the follow-up fails rather than choosing another destination.
Starting the turn also uses the client's idleOnly option. A busy target is not an invitation to interrupt the user, add scheduled input to an unrelated in-progress turn, or create another conversation. The scheduled attempt can fail; this change does not guarantee that a busy destination will eventually accept the run.
Ordinary cron-mode tasks keep their existing notification policy of notifying after each run. Follow-up tasks retain their separate result-comparison and optional stop-condition behavior. Sharing a conversation does not automatically give an ordinary task change-only notifications or require it to report a follow-up result.
Restart persistence is not automatic replay
A completed task's saved conversation binding survives recreating the scheduler. That is different from knowing whether an interrupted execution actually finished its work.
The scheduler's runtimeStopped path treats persisted running executions as uncertain: it disables the affected task and records a failure asking the user to inspect the original conversation before enabling it again. It does not blindly replay an input whose outcome may be unknown.
Existing duplicate conversations are preserved. The release changes the destination of future runs; it does not merge old histories or delete sidebar entries. Scheduled work still requires AIClaw to be running, subject to the scheduler's existing catch-up rules.
What the tests establish
For this article, I ran the public, tag-pinned scheduler tests and schedule-rule tests from a clean checkout matching the v3.8.4 commit. All 26 tests passed.
The new binding regression uses a temporary task store and a controlled host. It completes one run, recreates the scheduler, forces a resume failure, verifies that the destination remains saved, and then starts another run. It also checks that an old turn's completion leaves the newer run marked running until its own completion arrives.
The public desktop smoke script separately exercises the real session-manager method with fake client responses for reuse, resume failure, busy targets, archived destinations, and missing follow-ups. The release notes report 351 passing desktop UI checks and broader local validation. I did not rerun that desktop suite, wait for a real recurring task, or inspect release-workflow completion for this article.
The useful boundary is straightforward: one conversation holds a task's history, while each execution still has its own identity, completion receipt, and failure state.
Top comments (0)