Minor Changes
-
#2245
beff78aThanks @mattzcarey! - Add theQueueLifecycle capability (agents/queue) for durable background work. Each pushed item is a job in the Lifecycle job queue, due immediately, run from the alarm loop one at a time in push order with Lifecycle's retry, deadman, and memory-limit policy. Callbacks are registered in the constructor and typed at declaration and push;push()accepts a stableid(upsert) and per-itemretry.Agent.queue()and friends now delegate to the capability. Queued callbacks run from the alarm loop in a fresh invocation, so they no longer see the enqueuing request'sconnectionorrequestthroughgetCurrentAgent()(the agent itself is still available). Thecf_agents_queuestable and the in-isolate drain are gone; legacy rows migrate into the job queue on the next start.queue()acceptsoptions.id;dequeue,dequeueAll,dequeueAllByCallback,getQueue, andgetQueuesare now asynchronous; andQueueItem.created_atis renamedcreatedAt.LifecycleServices.starting()is replaced bystatus(), which returns"zero" | "starting" | "started".Think's workflow-notification outbox and submission drain now run as queue items; the
cf_think_workflow_notificationstable migrates and is dropped on start.Both one-shot migrations (
cf_agents_queuesin Queue,cf_think_workflow_notificationsin Think) are temporary upgrade paths and will be removed in the next minor release, by which point every started object has migrated. Deployments skipping this release should upgrade through it. Workflow-notification delivery retries with backoff capped at ten minutes (previously five) and gives up after twelve hours of continuous failure (previously never), reporting the failure throughonError.
Patch Changes
-
#2304
4f2e5a3Thanks @ben-reitz! - Requireagents >=0.24.0for Think's background work, which relies on the Queue capability's stable item IDs and alarm-driven execution. -
#2256
ee6a8cfThanks @mattzcarey! - Recover an interrupted Think turn that had opened its stream but persisted no content by re-running its user message instead of trying to continue it. Think opens the resumable stream row before inference, so a Durable Object reset in the window before the first chunk left a turn with a stream id, no partial, and a user message as the latest leaf; recovery classified it ascontinue, found no assistant message to continue from, and marked the incidentskipped. A parent tailing such a child through agent tools then sealed the run as an error. This mirrorsAIChatAgent's empty-partial new-turn rule (#1691). -
#2297
0fd3c8bThanks @ben-reitz! - Preserve running durable submissions during startup when either a retry or continuation chat-recovery callback is still pending. This applies to both current Tasks recovery attempts and legacy scheduled callbacks, allowing interrupted empty streams to retry and complete after a restart instead of being marked as errors.Keep recovery ownership until the successor chat turn is durably accepted, and bind the submission to that successor before handing off. Scope the handoff signal to the successor turn so concurrent turns cannot claim it, including facet-hosted turns after their legacy successor fiber is durably created. New recovery payloads carry stable submission identity; exact submission IDs take precedence over request-ID fallback, preventing collisions from recovering or terminalizing another submission. Record each turn's actual outcome and structured output on the submission row in the same transaction that settles its stream, so a restart between turn completion and ledger settlement records the completed, aborted, or errored outcome from recorded fact instead of inferring from stream state — without rerunning the turn or duplicating response callbacks: aborted turns stay aborted, recovered workflow completions keep their output, an overflow retry segment is never mistaken for an answer, and the recorded fact survives unrelated turns reclaiming stream rows.