You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(temporal): opt-in continue-as-new for long-lived agent workflows
Long-lived chat/session agents run as a single Temporal workflow that stays
open indefinitely, so their event history grows until it hits Temporal's
~50k-event / 50MB limit and the workflow stalls. This adds an opt-in
continue-as-new pattern on BaseWorkflow that recycles the history so a session
can stay open forever.
It is opt-in by design: an agent gets recycling only by calling
run_until_complete from its @workflow.run instead of a bare
wait_condition(timeout=None). There is no env flag.
BaseWorkflow helpers:
- run_until_complete(*args, is_complete, can_recycle=True, timeout=None): keep the
workflow open; recycle history when Temporal suggests it. timeout mirrors the old
wait_condition(timeout=...); can_recycle lets an agent opt out when a recycle
prerequisite is missing.
- should_continue_as_new(): recycle when workflow.info().is_continue_as_new_suggested().
- drain_and_continue_as_new(): waits all_handlers_finished (so an in-flight turn is
not lost) and re-checks completion before workflow.continue_as_new.
- recycling_active(): workflow.patched() gate, so a workflow that started before an
agent adopted run_until_complete replays its original command stream unchanged.
- is_continued_run(): the hook agents use to gate state rehydration after a recycle.
Restoring state after a recycle is framework-specific (rebuild from adk.messages,
an adk.state snapshot, or a framework's own memory, e.g. a LangGraph checkpointer)
and is intentionally left to follow-up PRs, one per integration. The 000_hello_acp
example adopts the pattern; it keeps no cross-turn state, so it needs no rehydration.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# 2. Wait for the task to be completed indefinitely. If we don't do this the workflow will close as soon as this function returns. Temporal can run hundreds of millions of workflows in parallel, so you don't need to worry about too many workflows running at once.
66
-
67
-
# Thus, if you want this agent to field events indefinitely (or for a long time) you need to wait for a condition to be met.
68
-
awaitworkflow.wait_condition(
69
-
lambda: self._complete_task,
70
-
timeout=None, # Set a timeout if you want to prevent the task from running indefinitely. Generally this is not needed. Temporal can run hundreds of millions of workflows in parallel and more. Only do this if you have a specific reason to do so.
71
-
)
65
+
# 2. Keep the workflow open to field events. We use run_until_complete
66
+
# instead of a bare wait_condition: it still waits indefinitely, but also
67
+
# recycles the Temporal event history via continue-as-new before it hits the
68
+
# ~50k-event / 50MB limit, so this chat can stay open forever. Adopting
69
+
# run_until_complete IS the opt-in — agents that keep the old wait_condition
70
+
# never recycle. This agent keeps no cross-turn state, so nothing needs
71
+
# restoring across a recycle and `params` is the only carry-forward. (Agents
72
+
# that DO keep state rebuild it at the top of @workflow.run, gated on
0 commit comments