
Tool Runtimes Need Serialized Lifecycle Authority
Shared tool and connector runtimes should serialize connect, reconnect and cleanup under one lifecycle authority, keep cleanup accountable across caller cancellation, bound waits and preserve failed teardown as governance state before a new generation is allowed to start.
Tool Runtimes Need Serialized Lifecycle Authority
Connect, reconnect and cleanup look like ordinary helper methods until multiple callers operate on the same tool runtime. At that point they become control-plane transitions: they mutate shared resource state, determine which generation owns the connection, and decide whether teardown has finished safely enough for replacement.
Summary
The central judgment is that shared tool runtimes need one serialized lifecycle authority per managed resource domain. Cleanup ownership should survive an initiating caller's cancellation when resource safety requires completion, waits should be bounded, cleanup failures should remain observable, and a replacement generation should not begin until the previous generation is confirmed stopped or explicitly force-recovered by policy.
The completed Reading Result examines a merged OpenAI Agents Python fix for MCPServerManager. It is concrete engineering evidence for manager-local lifecycle serialization and cancellation-safe cleanup ownership. It is not evidence for distributed locking across processes or hosts.
Source
Production consumes the same-day Research Object Q-20260810-03 and uses its completed Reading Result only to verify citations and implementation boundaries. Primary evidence comes from OpenAI Agents Python issue #4334, merged PR #4340 and commit 7da5696020a82d7ee2546a557eb8990169e23815.
- Issue: https://github.com/openai/openai-agents-python/issues/4334
- Merged PR: https://github.com/openai/openai-agents-python/pull/4340
- Implementation commit: https://github.com/openai/openai-agents-python/commit/7da5696020a82d7ee2546a557eb8990169e23815
Observation
Before the fix, public lifecycle operations could overlap while sharing manager and worker state. Commands could be queued after cleanup even though the relevant worker had already exited, leaving unresolved futures and inconsistent state.
The merged repair introduces one manager-level lifecycle lock above public connect_all(), reconnect() and cleanup_all() transitions. Parallel cleanup is represented by one cleanup future and awaited through asyncio.shield, so cancellation of a caller does not automatically cancel the underlying cleanup operation. A stopping worker is awaited before replacement, cleanup failures are retained, and connect/cleanup operations use finite 10-second defaults unless the application explicitly opts out.
Figure 1. Connect, Reconnect, and Cleanup share one serialized lifecycle authority; a new Generation cannot start before the previous one closes. Source: Research Center synthesis based on the cited primary sources.
Comparison
| Lifecycle model | Transition ownership | Cancellation behavior | Wait boundary | Failed cleanup handling | Replacement safety |
|---|---|---|---|---|---|
| Independently callable lifecycle methods | Competing callers | Caller cancellation can interrupt coordination | Undefined by ordering alone | Easy to lose in races | New work may overlap teardown |
| Per-server worker queue only | Per worker, not manager-wide | Task affinity preserved | Queue-local | Does not prevent manager races | Insufficient for overlapping public transitions |
| Manager-level serialized lifecycle | One lock orders public transitions | Cleanup future can outlive caller cancellation | Connect/cleanup defaults finite | Failure remains observable | Stopping worker must finish before replacement |
| Governed multi-process lifecycle | Research Center proposal: lease/fencing authority per resource domain | Ownership survives caller/session boundaries by policy | Lock, operation and recovery deadlines separated | Failure becomes quarantine/recovery state | New generation requires fencing token and explicit policy |
The first three rows summarize mechanisms documented by the issue, PR, commit and Reading Result. The final row is a Research Center engineering proposal for systems that extend beyond one in-process manager.
Discussion
A mutex alone is not enough. Serialization converts unsafe overlap into ordered waiting, but a protected operation that can wait forever merely turns races into queue stalls. Lifecycle governance therefore needs both a single transition authority and explicit time budgets.
Cancellation also needs a resource-centric interpretation. A caller disappearing does not prove that teardown is complete. If cleanup owns sockets, subprocesses, browser sessions or external leases, abandoning cleanup with the caller can leave the next generation operating against partially torn-down resources.
Finally, cleanup failure should not be overwritten by a convenient “clean” state. Preserving terminal teardown errors creates an explicit safety decision: quarantine, restart, operator approval or force replacement. Fabricating a clean state merely to reconnect destroys the evidence needed to govern the transition.
Engineering impact
For Digital Employees, treat browser sessions, MCP connections, credential sessions and other external-tool runtimes as managed resources with lifecycle owner, generation id, timeout, cleanup status and recovery policy. Two workflow branches should not independently reconnect or tear down the same resource.
For CodeFlowMu, place a per-resource lifecycle mutex or lease above adapter-specific workers, persist lifecycle transitions in the operation log, keep finite connect/cleanup deadlines by default, and expose wait duration, timeout, retained cleanup failure and generation replacement events.
When multiple processes can address the same external resource, add fencing or generation tokens; a process-local lock is no longer enough.
For TMPA, the merged implementation is useful engineering evidence for bounded ownership transitions, but one library fix is not sufficient to define protocol-level lifecycle semantics.
Boundaries and uncertainty
The evidence is manager-local. It does not coordinate replicas across hosts. Applications can explicitly set lifecycle timeouts to None, removing the finite operation deadline. The regression suite uses controlled fake servers and therefore cannot cover every subprocess, transport, shutdown or OS-level failure. The suppress_cancelled_error policy also changes what a cancelled caller observes and must be understood by applications.
Future work
The next design questions are whether lifecycle lock acquisition needs a deadline distinct from connect/cleanup deadlines; how generation fencing should work across processes; which cleanup failures require quarantine, process restart, human approval or force replacement; and which telemetry should expose lock wait, stopping state, cleanup timeout and retained errors.
Visualization note
The header cover uses controlled, sequential resource chambers to represent serialized lifecycle authority. The explanatory figure embedded in the Observation section shows the relationship among connect, reconnect and cleanup. The two visual roles use different assets; no vendor artwork or invented quantitative data is used.
References
- OpenAI
openai-agents-pythonIssue #4334, lifecycle overlap race reproduction: https://github.com/openai/openai-agents-python/issues/4334 - OpenAI
openai-agents-pythonPR #4340, merged lifecycle serialization fix: https://github.com/openai/openai-agents-python/pull/4340 - OpenAI
openai-agents-pythoncommit7da5696020a82d7ee2546a557eb8990169e23815: https://github.com/openai/openai-agents-python/commit/7da5696020a82d7ee2546a557eb8990169e23815 - Research Center Research Object:
research/analysis/Q-20260810-03-serialized-lifecycle-governance.md - Research Center Reading Result:
research/reading/Q-20260810-03-mcp-lifecycle-serialization.md
Editing status: published. Manager-local scope, cancellation semantics, timeout boundary, preserved cleanup failure, bilingual structure and evidence traceability checked.