
Safe Agent Handoff Requires Separate Routing and Effect Ownership
An agent handoff is often described as a change in who is active: Agent A stops, Agent B takes over, and the conversation continues. That description is incomplete when Agent A has already launched streaming or non-blocking tool work in the background.
The old agent can stop being the visible owner while its tasks are still executing. A tool can stop receiving new input while an external API request it already issued continues independently. A runtime can request cancellation without being able to prove that the underlying work actually terminated.
The 2026-08-15 research object examined a merged Google ADK change and regression tests around local asyncio background work. The evidence is bounded to local runtime behavior; it does not establish distributed revocation or exactly-once external effects. Within that boundary, it exposes an important engineering model: execution ownership, routing ownership, observed termination, and external-effect ownership must be tracked separately.
Handoff is an ownership transfer
The selected change makes a live agent run responsible for streaming and non-blocking background tasks. Cleanup is invoked before handoff and again from the outer run_live finalization path.
Pre-handoff cleanup matters because the shared live request queue is itself an ownership surface. If the next agent starts consuming the route while background tools from the previous agent are still registered, old tools may continue receiving input that now belongs to the new owner.
A safe handoff should therefore be modeled as a transfer of claims. The previous run must relinquish the execution and routing resources it owns before the next run begins treating those resources as its own.
Cancellation requested is not the same as task stopped
The cleanup path cancels pending background tasks and waits for at most one second. It also observes exceptions from tasks that have completed and clears the streaming and non-blocking registries even when cancellation-resistant tasks remain alive.
That bounded wait is a deliberate availability tradeoff. Waiting indefinitely for cooperative cancellation would maximize cleanup certainty, but it could make the entire handoff hostage to one misbehaving task. Bounded cancellation protects liveness, but it creates another state that the runtime should not hide: residual work may still exist.
For low-risk local helpers, “cancellation requested and registry cleared” may be sufficient. For a high-risk tool, a runtime may need stronger proof before continuing. The policy should depend on the tool class rather than pretending one timeout proves termination for every workload.
Routing retirement is a real guarantee, but a narrower one
The selected mechanism clears the registries that route future live input to old streaming tools. That means a stale tool no longer participates in the route after handoff.
This is a meaningful guarantee. It prevents one class of ownership leak in which an orphaned background task continues to receive new user or live-session input.
But routing retirement says nothing about effects the tool has already initiated. The coroutine may still be alive. A remote HTTP request may already have been accepted. A message, payment, database mutation, or job submission may already exist outside the local runtime.
This is why routing ownership and effect ownership cannot be collapsed into one state.
External effects require provider-specific evidence
Local coroutine cancellation cannot roll back the outside world. Once an operation crosses into another system, the runtime needs mechanisms appropriate to that provider.
Some providers support cancellable jobs. Some support idempotency keys so a retry converges on the same effect. Some operations can be compensated with an explicit inverse action. Others require reconciliation: inspect the remote state and decide whether the effect already happened before attempting anything again.
A generic agent runtime therefore should not infer “external effect closed” from “local task canceled.” The evidence chain has to name what actually happened at the provider boundary.
A safer handoff sequence
A more accurate handoff model is:
cancellation requested → routing ownership retired → task termination observed or residual work declared → external effects independently reconciled.
Each milestone answers a different question. Cancellation requested records the runtime's intent. Routing retirement proves the old task can no longer consume shared live input. Termination observation tells the runtime whether local execution actually ended. Residual-work declaration preserves uncertainty when it did not. External-effect reconciliation decides whether anything outside the runtime still exists or needs repair.
This separation is useful for both recovery and observability. A dashboard or audit trail that shows only “cleanup complete” can hide exactly the uncertainty that matters most after a handoff.
Engineering implications
Agent-run ownership should include every locally spawned asynchronous task capable of writing into shared runtime channels. Handoff should revoke the previous owner's routing membership before the new owner begins consuming the same route. Bounded teardown should expose residual work explicitly when termination cannot be proven. Operational telemetry should record cancellation requested, task stopped, routing retired, and external effect reconciled as distinct milestones.
External side-effect safety should be designed per tool or provider through idempotency, cancellable jobs, compensation, or reconciliation. Local cancellation is an execution mechanism; it is not a universal transaction boundary.
When a simpler model is enough
Not every agent tool needs a durable residual-work ledger. A short-lived local helper with no persistent external effect may be adequately governed by a best-effort one-second cancellation plus logging. Persisting every ephemeral coroutine can add complexity without corresponding risk reduction.
The design should therefore be risk-sensitive. What should remain invariant is semantic honesty: if termination is not proven, do not report it as proven; if external effects are not reconciled, do not infer that they disappeared.
Limits of the evidence
The selected evidence covers ADK local asyncio and live-request execution. It does not cover remote workers, subprocesses, durable job queues, distributed revocation, forced termination, transaction rollback, compensation correctness, or exactly-once external effects.
The one-second timeout is an implementation constant, not evidence for an optimal service-level objective across tool classes.
Open questions
Which tool-risk classes should block handoff until termination is proved rather than merely routing ownership being released? How should residual local or remote work be represented durably so later agents know an effect may still be in flight? What common evidence contract can connect local cancellation state with provider-side idempotency, compensation, and reconciliation outcomes?
A safe handoff does not require pretending every old task has vanished. It requires the runtime to know exactly which ownership claims have been released, which facts remain uncertain, and which external effects still need evidence.