Skip to content

feat(sdks/python): resilient SDK transport (OSEP-0016)#1372

Open
Pangjiping wants to merge 1 commit into
opensandbox-group:mainfrom
Pangjiping:osep-0016-python-resilient-transport
Open

feat(sdks/python): resilient SDK transport (OSEP-0016)#1372
Pangjiping wants to merge 1 commit into
opensandbox-group:mainfrom
Pangjiping:osep-0016-python-resilient-transport

Conversation

@Pangjiping

Copy link
Copy Markdown
Collaborator

Summary

Python landing of OSEP-0016 Resilient SDK Transport for both sdks/sandbox/python and sdks/code-interpreter/python. Client-only; no spec change, no server change, no wire-format change.

Draft while OSEP-0016 is still under review; will be marked ready once the design lands (or updated to track any decision changes on the OSEP first).

What it adds

Retry policy (opensandbox.transport.RetryPolicy)

  • New value type on ConnectionConfig / ConnectionConfigSync.
  • Defaults retry idempotent methods only; POST / PATCH status-code retry is opt-in through retryable_status_codes_non_idempotent.
  • Default idempotent retryable set: {HTTPStatus.TOO_MANY_REQUESTS, HTTPStatus.BAD_GATEWAY, HTTPStatus.SERVICE_UNAVAILABLE} — narrower than the OSEP draft; happy to widen back to {408, 425, 429, 500, 502, 503, 504} if the OSEP thread lands there.
  • Decorrelated jitter (default), full jitter, and deterministic exponential.
  • Retry-After honored with a fixed 60s ceiling to prevent pathological server headers from stalling the client.
  • RetryPolicy.disabled() for end-to-end fast-fail (also suppresses fresh-conn recovery).
  • Public API uses frozenset[HTTPStatus] so callers get type checking and IDE completion.

Exception hierarchy

  • Extend SandboxException with an is_retryable accessor reflecting the SDK's actual retry decision at emission time (budget exhaustion / deadline / cancellation all force False even for transient causes).
  • New subclasses: SandboxRateLimitException (carries retry_after), SandboxTimeoutException, SandboxConnectionException.
  • Existing classes and their public fields are unchanged; except SandboxApiException continues to catch rate-limit and API errors.

Transport wrappers

  • RetryAsyncTransport (httpx.AsyncBaseTransport) and RetrySyncTransport (httpx.BaseTransport).
  • ConnectionConfig exposes a sse_transport property so SSE bootstraps bypass retry while sharing the underlying connection pool.
  • Command / isolated / code-interpreter SSE clients now use sse_transport.
  • Generated OpenAPI code is not touched.
  • lifecycle_metrics piggy-backs on the shared transport when possible, matching sync/async transport types.

Behavior change to call out

  • RetryPolicy is enabled by default. Callers that rely on fast-fail semantics on GET/HEAD/PUT/DELETE must opt out via ConnectionConfig(retry_policy=RetryPolicy.disabled()).
  • Under the default policy, POST/PATCH are never retried on any status code; pre-send transport failures (DNS, TCP connect, TLS handshake, fresh-conn RST) are still retried on POST/PATCH.

Non-goals

Matches OSEP-0016 non-goals: no server-side idempotency store, no per-request override, no SSE stream resume, no client-side circuit breaker.

Tests

  • Retry policy defaults, validation, HTTPStatus usage.
  • Pure decision function: status matrix, transport branch (pre-send vs. post-send), budget/deadline/cancellation predicates, opt-in rules, jitter algorithms, Retry-After parsing and clamping.
  • Async + sync httpx transport integration via scripted mock transports: success, 4xx pass-through, budget exhaustion, pre-send vs. post-send classification, opt-in, observability callback invariants.
  • ConnectionConfig wiring: default wraps, disabled() skips wrapping, user-supplied transports pass through verbatim.
  • SSE client uses the raw inner transport (end-to-end assertion against _httpx_client._transport vs _sse_client._transport).

Local verification (macOS, Python 3.12):

  • sdks/sandbox/python: uv run ruff check clean, uv run pyright clean on this PR's files, uv run pytest 396 passed.
  • sdks/code-interpreter/python: uv run ruff check clean, uv run pyright clean, uv run pytest 15 passed.

Follow-ups

  • JS/TS, Kotlin, Go, C# SDKs — separate PRs.
  • SSE stream resume with Last-Event-ID — deferred to a follow-up OSEP as noted in OSEP-0016.

Related

@github-actions github-actions Bot added sdk/python sdks size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jul 22, 2026
@Pangjiping
Pangjiping force-pushed the osep-0016-python-resilient-transport branch from 317efb4 to 10c2023 Compare July 23, 2026 02:45
@Pangjiping
Pangjiping marked this pull request as ready for review July 23, 2026 03:12

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 10c20233ea

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread sdks/code-interpreter/python/src/code_interpreter/adapters/code_adapter.py Outdated
Comment thread sdks/sandbox/python/src/opensandbox/transport/_async_retry.py
Comment thread sdks/sandbox/python/src/opensandbox/transport/retry.py
@Pangjiping
Pangjiping force-pushed the osep-0016-python-resilient-transport branch from 10c2023 to f5ae605 Compare July 23, 2026 03:30
@github-actions github-actions Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jul 23, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f5ae605ec9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread sdks/sandbox/python/src/opensandbox/transport/_async_retry.py Outdated
Comment thread sdks/sandbox/python/src/opensandbox/exceptions/sandbox.py
@Pangjiping
Pangjiping force-pushed the osep-0016-python-resilient-transport branch from f5ae605 to a62bac0 Compare July 23, 2026 03:50
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a62bac02a1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread sdks/sandbox/python/src/opensandbox/transport/_async_retry.py Outdated
Comment thread sdks/sandbox/python/src/opensandbox/config/connection.py Outdated
@Pangjiping
Pangjiping force-pushed the osep-0016-python-resilient-transport branch from a62bac0 to 7e1af4c Compare July 23, 2026 04:00
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e1af4c685

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread sdks/sandbox/python/src/opensandbox/exceptions/sandbox.py
Comment thread sdks/sandbox/python/src/opensandbox/exceptions/sandbox.py
Comment thread sdks/code-interpreter/python/pyproject.toml Outdated
@Pangjiping
Pangjiping force-pushed the osep-0016-python-resilient-transport branch from 7e1af4c to 929235a Compare July 23, 2026 04:28
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 929235abf8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread sdks/sandbox/python/src/opensandbox/transport/_async_retry.py
Comment thread sdks/sandbox/python/src/opensandbox/transport/_decision.py Outdated
@Pangjiping
Pangjiping force-pushed the osep-0016-python-resilient-transport branch from 929235a to 2a0c6d2 Compare July 23, 2026 04:50
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a0c6d280a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread sdks/sandbox/python/src/opensandbox/transport/_async_retry.py
@Pangjiping
Pangjiping force-pushed the osep-0016-python-resilient-transport branch from 2a0c6d2 to 1f66734 Compare July 23, 2026 05:08

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1f6673484b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread sdks/sandbox/python/src/opensandbox/adapters/command_adapter.py Outdated
@Pangjiping
Pangjiping force-pushed the osep-0016-python-resilient-transport branch from 1f66734 to 8685e37 Compare July 23, 2026 05:15

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8685e37d79

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread sdks/sandbox/python/src/opensandbox/config/connection.py
Comment thread sdks/sandbox/python/src/opensandbox/transport/retry.py
Implement the Python side of OSEP-0016 for the sandbox and
code-interpreter SDKs. Adds a shared retry policy, extended
exception hierarchy, and async/sync httpx transport wrappers.

Retry policy
- New `RetryPolicy` value type on `ConnectionConfig` /
  `ConnectionConfigSync`; defaults enable retry for idempotent
  methods only, `POST`/`PATCH` status-code retry is opt-in.
- Default idempotent retryable status set: `{429, 502, 503}`.
- Decorrelated jitter (default), full jitter, and deterministic
  exponential; `Retry-After` honored with a fixed 60s ceiling.
- `RetryPolicy.disabled()` gives end-to-end fast-fail semantics
  and suppresses fresh-connection recovery.
- `HTTPStatus` used at the public API surface so callers get
  type checking and IDE completion for the status sets.

Exception hierarchy
- Extend `SandboxException` with an `is_retryable` accessor
  reflecting the SDK's actual retry decision at emission time.
- New subclasses: `SandboxRateLimitException` (carries
  `retry_after`), `SandboxTimeoutException`,
  `SandboxConnectionException`. Existing classes and their
  public fields are unchanged.

Transport wrappers
- `RetryAsyncTransport` (httpx.AsyncBaseTransport) and
  `RetrySyncTransport` (httpx.BaseTransport) install the retry
  engine at the same layer the SDK already uses for transport
  concerns. Generated OpenAPI code is not touched.
- `ConnectionConfig` exposes a `sse_transport` property so SSE
  bootstraps bypass retry while sharing the underlying pool.
  Command / isolated / code-interpreter SSE clients now use it.
- `lifecycle_metrics` keeps its own short-lived httpx.Client;
  sharing the SDK transport would let the metrics client's
  `close()` tear down every other adapter's connection pool.

Tests
- Retry policy defaults, validation, and `HTTPStatus` usage.
- Pure decision function: status matrix, transport branch,
  budget/deadline/cancellation predicates, opt-in rules,
  jitter algorithms, and `Retry-After` parsing/clamping.
- Async + sync httpx transport integration via scripted mock
  transports covering success, 4xx pass-through, budget
  exhaustion, pre-send vs. post-send classification, opt-in,
  and observability callback invariants.
- `ConnectionConfig` wiring: default wraps, `disabled()` skips
  wrapping, user-supplied transports are used verbatim.
- SSE clients use the raw inner transport, verified end-to-end.
@Pangjiping
Pangjiping force-pushed the osep-0016-python-resilient-transport branch from 8685e37 to 1525809 Compare July 23, 2026 05:44
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1525809a50

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread sdks/code-interpreter/python/pyproject.toml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

sdk/python sdks size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants