Skip to content

Prepare OpenAI Agents package cutover - #23

Merged
brianstrauch merged 39 commits into
mainfrom
cutover/python-openai-agents
Sep 16, 2026
Merged

brianstrauch merged 39 commits into
mainfrom
cutover/python-openai-agents

Conversation

@brianstrauch

@brianstrauch brianstrauch commented Sep 15, 2026 •

Copy link
Copy Markdown
Member

Summary

  • make ai-integrations authoritative by removing the SDK upstream metadata
  • move the standalone package from temporalio.contrib.openai_agents to temporalio.openai_agents
  • support temporalio>=1.33.0, avoiding all file overlap with the SDK-bundled integration
  • enable final releases and remove transitional overlap workarounds
  • flatten the OpenAI Agents test tree
  • retain the shared reinstall behavior for future overlapping plugin migrations
  • teach repository conventions to validate either declared Temporal package root

Release order

  1. Merge this PR and publish temporalio-openai-agents 1.0.0 through the normal release workflow.
  2. Update Remove OpenAI Agents integration sdk-python#1868 so the existing openai-agents extra depends on temporalio-openai-agents>=1.0.0, and its old temporalio.contrib.openai_agents public imports forward to the new package.
  3. Merge #1868 and publish temporalio 1.34.0.

Because the standalone package now installs under temporalio.openai_agents, it can safely coexist with Temporal 1.33, whose bundled implementation remains under temporalio.contrib.openai_agents. This removes the circular release dependency without publishing a broken package or bypassing either release workflow.

User migration

New code should install the standalone package and use the new canonical import:

uv add temporalio-openai-agents
from temporalio.openai_agents import OpenAIAgentsPlugin

After Temporal 1.34.0, existing users of temporalio[openai-agents] can upgrade normally: the extra will install the standalone distribution, and SDK compatibility modules will preserve the old public temporalio.contrib.openai_agents imports. Users may migrate imports to temporalio.openai_agents independently.

Documentation and downstream repository migrations remain deferred.

Validation

  • make sync && make format && make lint && make test && make build
    • 229 passed, 2 skipped
  • wheel and sdist ownership/metadata checks
  • repository conventions
  • tooling tests: 93 passed
  • dedicated convention tests for both supported package-root forms: 17 passed

brianstrauch and others added 30 commits August 27, 2026 11:01
A failed operation evicted the pooled connection by closing it outright,
which unwound the owning task's `async with backend` while concurrent
operations were still using the same connection. Since `CancelledError` is
a `BaseException`, activity cancellation and worker shutdown hit this path
too, so cancelling one MCP activity aborted every other in-flight activity
sharing the connection. The failing operation also never released its slot.

Failures now retire the record: it is dropped from the cache so no later
operation reuses it, and the last operation to release it closes it.

Also drop a dead uniqueness check in `_MCPActivities` (`set()` over a dict
compares key counts, so it never fired) and correct the deprecation
directives to 1.32, the unreleased version.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Migrated-From: temporalio/sdk-python@4fb9cc8
`temporalio.contrib.mcp` is an implementation detail shared by the contrib
integrations, not a public API, but it was advertised as one: the CHANGELOG
called it stable, `workflow.py`/`MCPClient` were the only non-underscore
names in an otherwise private package, and pydoctor rendered the package
into the published docs. Rename to `_workflow._MCPClient`, mark the package
PRIVATE for pydoctor, and describe the release in terms of the OpenAI Agents
surface users actually call.

`meta` was threaded through all seven operations, but only `call_tool` has a
caller that supplies it (the OpenAI Agents base `MCPServer` resolves it per
tool call). The other six accepted it and dropped it on the floor, so a
caller passing metadata would silently get none. Drop the parameter there;
`_CallToolRequest` now owns the field.

Replace the `-k 'legacy_mcp_apis_are_deprecated or mcp_server'` CI selection
with `@pytest.mark.mcp_v1`. Substring matching silently under-selects on a
rename while still passing, and `mcp_server` also matches `mcp_servers` and
any future `test_hosted_mcp_server_*`. The marker selects the same 13 tests
today and stays correct as tests are renamed or added.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Migrated-From: temporalio/sdk-python@8b74c9e
An idle-eviction task armed before an operation acquired a pooled record
could close the connection while that operation was still in flight: once
a peer failure unmapped the record, `_unmap` skipped the idle check and
reported the record closable. Apply the idle check regardless of whether
the record is still mapped.

Restore the legacy `inspect.signature` handling for MCP server factories,
now shared by both backends. A factory declaring a positional parameter
receives the `factory_argument` (`None` when a workflow supplied none), and
a parameterless factory is called bare. Signatures that could satisfy
neither form raise when the plugin is built, and passing a
`factory_argument` to a parameterless factory raises a non-retryable error
instead of a bare `TypeError` that retries forever.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Migrated-From: temporalio/sdk-python@0168e19
Fix the proto Docker build, which pinned googleapis-common-protos into
the dev group while the conflicting requirement now lives in dev-common,
leaving the following uv sync unsatisfiable.

Bound the MCP pool close during worker shutdown. The run context swallows
the shutdown cancellation, so an MCP server that never finishes closing
its transport would hang the worker with no cancellation left to break
out with.

Stop treating activity cancellation as a transport failure in the
connection pool. The MCP client cancels the in-flight request on the
wire, so the shared connection stays healthy and should not be retired
out from under every other workflow using it.

Reject a callable tool_filter on a worker-side MCPServer. It needs the
run context and agent, which exist only in the workflow, so the Agents
SDK raises for it and the list-tools Activity would retry forever.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Migrated-From: temporalio/sdk-python@7100059
…andbox, use the public MCP client import

exclude-newer = "2 weeks" limits candidates to distributions uploaded before the cutoff, so a freshly published temporalio-mcp would have no eligible release for two weeks and uv lock would keep failing after the release; exempt it like temporalio.

MCPPlugin passes mcp_types through the sandbox and the adapter imports it directly, so OpenAIAgentsPlugin does the same. TemporalMCPClient is a public export of temporalio.contrib.mcp; import it from there instead of the private module.
…mported-files rule

The adapter was developed in sdk-python PR #1793, closed unmerged on 2026-09-03, and migrated here with Migrated-From trailers. Its commits touch ten imported files and can never arrive from sdk-python main, so AGENTS.md, CONTRIBUTING.md, scripts/migrate/README.md and IMPORTS.md now say so, and future re-syncs merge on top of them. The cooldown docs cover the second exclude-newer-package exemption.
…ents-mcp-v2

# Conflicts:
#	CONTRIBUTING.md
#	python/mcp/README.md
#	python/mcp/plugin.toml
#	python/mcp/src/temporalio/contrib/mcp/_activities.py
#	python/mcp/src/temporalio/contrib/mcp/_backend.py
#	python/mcp/src/temporalio/contrib/mcp/_client.py
#	python/mcp/src/temporalio/contrib/mcp/_pool.py
#	python/mcp/src/temporalio/contrib/mcp/_workflow.py
#	python/mcp/tests/test_activities.py
#	python/mcp/tests/test_pool.py
#	python/mcp/tests/test_workflow.py
#	python/mcp/uv.lock
#	python/openai_agents/pyproject.toml
…ents-mcp-v2

# Conflicts:
#	python/openai_agents/pyproject.toml
#	scripts/ci/check_conventions.py
Base automatically changed from sync/python-openai-agents-mcp-v2 to main September 16, 2026 00:23
…-agents

# Conflicts:
#	AGENTS.md
#	CONTRIBUTING.md
#	python/openai_agents/README.md
#	python/openai_agents/plugin.toml
#	python/openai_agents/pyproject.toml
#	python/openai_agents/src/temporalio/openai_agents/_mcp_backend.py
#	python/openai_agents/src/temporalio/openai_agents/_openai_runner.py
#	python/openai_agents/src/temporalio/openai_agents/_temporal_mcp_server.py
#	python/openai_agents/src/temporalio/openai_agents/_temporal_openai_agents.py
#	python/openai_agents/src/temporalio/openai_agents/workflow.py
#	python/openai_agents/tests/test_mcp_v2.py
#	scripts/migrate/README.md
@brianstrauch
brianstrauch marked this pull request as ready for review September 16, 2026 00:51
@brianstrauch
brianstrauch requested a review from a team as a code owner September 16, 2026 00:52
@DABH
DABH requested a balanced review from Copilot September 16, 2026 04:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@DABH DABH left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultrareview verdict: requesting changes because this head is not merge/release-ready in the coordinated state declared by #24. The namespace move itself is mechanically sound: public exports are preserved, existing history replay passes, artifact ownership is clean, and the full local suite is green.

Blocking coordination finding:

  • #24's release plan says to publish temporalio-mcp 0.2 first and then update this branch. This head still pins both runtime/dev use to temporalio-mcp>=0.1.0,<0.2, imports temporalio.contrib.mcp in production code, documents/asserts temporalio.contrib.mcp.* Activity types, and locks 0.1.0. Its own PR description instead says to publish this PR first. Thus the two release plans contradict each other, and current CI validates only the legacy combination. After #24's compatibility decision is resolved and 0.2 is published, rebase this branch; update both constraints, imports, README, tests, and lockfile; then rerun the OpenAI suite against 0.2. The branches currently conflict in AGENTS.md, root README.md, check_conventions.py, and its tests; preserve #24's stricter rule that release-ready plugins use temporalio.<name> rather than this branch's permanent either-root allowlist. Update this PR's release-order text as well.

Additional release concerns are inline: the public Documentation metadata currently leads to instructions for the SDK-bundled package, and the temporalio>=1.33 coexistence claim needs to acknowledge split-path installs. I also noted a concrete stale migration command.

One further compatibility cleanup is advisable before making this an independently released GA package: it imports TemporalIdGenerator and ReplaySafeTracerProvider through private temporalio.contrib.opentelemetry._* modules while declaring compatibility with every Temporal 1.x release. ReplaySafeTracerProvider already has a public export; the ID-generator dependency can use a local protocol or should be publicly exported by the SDK. These private imports were safe when both components shipped together, but become an unversioned cross-package contract after this cutover.

Validation completed locally: make sync with locked Temporal 1.33.0, make lint, make test (229 passed, 2 skipped), make build, wheel/sdist ownership and metadata checks, tooling tests (93 passed), repository conventions, existing replay fixtures, and a wheel-file audit confirming no SDK overlap. GitHub CI is green. There are no substantive prior review comments; Copilot only reported quota exhaustion.

Comment thread AGENTS.md Outdated
Comment thread python/openai_agents/plugin.toml
Comment thread scripts/migrate/README.md Outdated

@DABH DABH left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@brianstrauch
brianstrauch merged commit 9a6ce5b into main Sep 16, 2026
23 checks passed
@brianstrauch
brianstrauch deleted the cutover/python-openai-agents branch September 16, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants