Repository navigation
Description
User Story
As a maintainer of the Python SDK, I want to move it out of core into ai-openshell/sdk-python the way the Go SDK moved (#5031), so that it gets its own CI, reviews and releases without changing anything for the people who pip install openshell.
Problem Statement
RFC 0019 (#4426) moves the SDKs out of core first. The Python SDK still lives in core, spread across several paths:
python/openshell/, plus its SDK tests inpython/;- the repository-root
pyproject.toml, which is the SDK's package definition; tasks/python.toml;tasks/scripts/generate_python_proto.pyandverify-python-wheel.py.
Core CI builds, lints and type-checks the SDK on every PR. Core's release workflows build the wheel and publish it to PyPI through wheel-publish.yml, and the openshell PyPI project trusts only that workflow. Core's e2e/python suites import the SDK from the working tree. The root uv.lock serves both the SDK and core's own Python tooling.
Impact / Why This Matters
- SDK maintainers own CI, reviews and releases without core review bandwidth, which is the goal of RFC 0019.
- Users see no change. The package name
openshell, the import paths and the API stay the same, includingopenshell._proto. Public code on GitHub depends on that module: Airflow's sandbox provider, dify-agent, NeMo Gym and others import it directly. So the move must not be combined with a breaking change to the generated bindings. - Core stops building and publishing the Python wheel. Its e2e suites consume the SDK as a pinned dependency.
Proposed Design
Follow the Go SDK's phases (#5031, and the lessons in discussion 5273), adapted to Python:
- Prerequisites.
- Confirm the
sdkteam and the sdk-python repository settings. - Plan the PyPI trusted-publisher handover and the version scheme. The first release from sdk-python must sort after the last core-built wheel.
- Announce the freeze at a release tag and merge the SDK PRs that are ready before it.
- Confirm the
- Import.
- Extract the SDK paths with history, using
git filter-repo --paths-from-file: the package moves tosrc/openshell/, the tests totests/and the scripts toscripts/. Core-only tests stay in core, and#Nreferences are rewritten toNVIDIA/OpenShell#N. - A second PR makes the package build on its own: bindings generated from protos fetched at the pinned core tag and committed, vendored test fixtures with drift checks, and standalone CI with a Python 3.11–3.14 test matrix.
- Extract the SDK paths with history, using
- Cutover in core.
- Switch
e2e/pythonto the SDK as a pinned dependency. - Remove the
pythonjob andbuild:python:wheelfrom PR gating. - Add a required check that fails on changes to the moved paths, and port the open SDK PRs.
- Move the open SDK issues. GitHub can't transfer issues between organizations, so
gh issue transferfrom NVIDIA/OpenShell to ai-openshell isn't available.- Triage the open Python SDK issues in core. Close the ones already fixed or obsolete.
- Recreate each one that's still valid in sdk-python, with a link back to the original.
- Comment on each original with the new link, and close it as moved.
- Keep issues about core's own Python tooling or e2e suites in core (for example bug(test): Python E2E cleanup deadline is shorter than Kubernetes sandbox termination #4685).
- Today's candidate is bug(python): OIDC refresh drops the gateway's oidc_scopes #4919 (OIDC refresh drops the gateway's
oidc_scopes).
- Route new reports to sdk-python. Point core's issue templates (the
config.ymlcontact links) and CONTRIBUTING at sdk-python for Python SDK reports.
- Switch
- Automation in sdk-python. As planned for sdk-go: bump PRs for each core release, E2E against that release's gateway, release tagging and a nightly drift check.
- Retire in core.
- Ship a final core-built wheel with a deprecation note.
- Remove the SDK paths,
tasks/python.tomlSDK tasks, CodeQL entries, the wheel build andpublish-pypijobs,wheel-publish.yml, and core's PyPI trusted publisher. - Update
docs/sdk/python.mdx, AGENTS.md, CONTRIBUTING and the skills.
- Release. Publish the first
openshellrelease from sdk-python.
Progress:
- History import, frozen at
v0.1.7: chore: import the Python SDK history from NVIDIA/OpenShell ai-openshell/sdk-python#2. - Standalone build, test and packaging, with a Python 3.11–3.14 CI matrix: feat: build, test, and package the Python SDK standalone ai-openshell/sdk-python#3.
- An earlier draft, feat!: package sdk with public Buf protos ai-openshell/sdk-python#1, bootstraps from copied sources and switches the bindings to Protobuf-Py. That breaking change is better done after the move, as its own announced release.
Acceptance Criteria
- ai-openshell/sdk-python builds, tests and packages the SDK without a core checkout or network access at build time.
- The first release from sdk-python installs as a drop-in replacement for the last core-built wheel: same exports and the same
openshell._protomodules. - Core CI, releases and
e2e/pythonno longer build the SDK frompython/, and core proto PRs no longer regenerate Python bindings. - PyPI publishes
openshellonly from sdk-python. - No open Python SDK issues remain in core: each is closed as fixed, obsolete, or moved, with a link to its sdk-python copy. Core's issue templates send new Python SDK reports to sdk-python.
- The Python-specific lessons are added to the migration playbook for the next repository move.
Alternatives Considered
- Bootstrap from a copy without history (feat!: package sdk with public Buf protos ai-openshell/sdk-python#1). This loses blame and authorship, and the Go move kept history.
- Generate bindings at build time from the Buf Schema Registry with remote plugins. Every wheel or sdist build would then need network access, which breaks sdist rebuilds, and it pairs with a runtime change that breaks users of
openshell._proto. - Keep the SDK in core and delegate through CODEOWNERS. RFC 0019 already weighs this option.
Agent Investigation
An agent mapped the SDK's footprint in core (paths, mise tasks, workflows, CodeQL, PyPI publishing, e2e consumers), rehearsed the history extraction and the standalone build in a private repository, and surveyed public GitHub code that imports the SDK. Rehearsal results:
- 76 commits from 24 authors, with a tree hash that matches core.
- 34 imported commits are older core squash merges without
Signed-off-by, so the import PR needs a DCO override.
Activity
ci(branch-checks): freeze the Python SDK sources in core
pimlock commentedon Nov 8, 2026
Status
This comment is kept up to date. Last updated 2026-11-09.
Merged 2026-11-09
v0.1.7.Open PRs
mainmainnow that #12 has merged.pypienvironment now exists (#10), so nothing blocks the merge.Python SDK Freezebranch checkv0.1.8(Tuesday 2026-11-10), or core publishes0.1.8to PyPI first.Phases
e2e/python, drop the SDK from PR gating, move the open SDK issues (bug(python): OIDC refresh drops the gateway's oidc_scopes #4919), and point the issue templates at sdk-python.python/and its tasks, the dev wheel, CodeQL entries, core's PyPI trusted publisher, anddocs/sdk/python.mdx.0.1.8.Tracked in sdk-python
core-watch), nightly drift against coremain(core-drift)sdk-botenvironmentrelease.yml, environmentpypi); ⬜ TestPyPI not set uppypiandtestpypienvironmentsDecisions
git filter-repoand kept, as for sdk-go. The extraction and verification scripts aren't onmain. They're kept at the tagmigration/v0.1.7.OPENSHELL_CORE_REF) and committed.openshell._protostays as it is. Switching to Protobuf-Py (feat!: package sdk with public Buf protos ai-openshell/sdk-python#1) is a separate breaking release after the move.0.1.8. Core's0.1.7wheel is the last one core builds.X.Y.Z.post1) is the likely option.mainwhen a stable bump PR merges, not from a pushed tag. Thepypienvironment allows onlymain, as in core.pip install "openshell @ git+https://github.com/ai-openshell/sdk-python@main", orgo get github.com/ai-openshell/sdk-go@main. sdk-python can do this because its bindings are committed, and setuptools-scm gives such a build a dev version (X.Y.Z.devN+g<sha>). Core's rollingdevrelease and dev wheel stay untilpython/leaves core.mainis only checked nightly for drift. Dependabot is an alternative to evaluate later; if we switch, sdk-go switches too.test_sandbox_api,test_workspace_api,test_sandbox_exec_python,test_exec_admission; OIDC later). The enforcement suites stay in core and get ported to the Rust testkit.python/plustasks/scripts/generate_python_proto.pyandverify-python-wheel.py, exactly the imported tree. Core-only tests moved out ofpython/. Deletions are allowed.SPDX-License-Identifier: Apache-2.0. Existing headers keep theirSPDX-FileCopyrightTextline (sdk-python#11).Next
v0.1.8tag. CI is green; no review yet.mainand pass CI. Bump PRs from Example: Run worldsim from a sandbox #13 run E2E against the proposed core version.0.1.8: merge sdk-python#14. Once core tagsv0.1.8, open the bump PR (mise run core:bump -- v0.1.8) and merge it;release.ymlpublishes. The version stays free as long as core doesn't publish it.e2e/python.Also open in sdk-python: Dependabot bumps (sdk-python#16–#22) and a docs PR for the usage guide and package metadata (sdk-python#23).