Skip to main content

recursion-sdk (Python)

The rl-gym Python SDK, generated from the same backend OpenAPI snapshot, and the same @SdkRoute opt-in set, as @labelbox/recursion-sdk with openapi-python-client — free, open source, and pinned by version. The only hand-written code is a thin auth constructor (src/recursion/__init__.py); everything under src/recursion_sdk/ is generated and gitignored.

The two SDKs share a surface, not just a set of operations. @SdkRoute('synthesizers', 'create') on a backend handler produces rl.synthesizers.create(...) in both clients, from that one declaration.

import asyncio
import os

from recursion import create_recursion_client


async def main() -> None:
    rl = create_recursion_client(api_key=os.environ["LABELBOX_API_KEY"])
    environment = await rl.environments.get(environment_id)
    print(environment.name)


asyncio.run(main())

Surface

Namespaced exactly like the TypeScript SDK, because both are driven by the same x-sdk-path:

// @labelbox/recursion-sdk
const job = await rl.synthesizers.create({
  environmentId,
  body: { name: 'Variant generator', systemPrompt: '…', runConfigVersionId },
});
# recursion-sdk
body = CreateSynthesizerJobBodyDto(name="Variant generator", system_prompt="…", ...)
job = await rl.synthesizers.create(environment_id, body=body)

Path parameters are positional, the body and query parameters are keywords. Every call is async. Non-2xx responses raise RecursionApiError, carrying .status_code, .parsed (the typed error body, when the operation documents one) and .content — matching the TypeScript client's throwOnError: true.

The namespace facade (recursion_sdk/facade.py) is generated from x-sdk-path, exactly as hey-api's nesting() callback drives the TypeScript side, so the two clients cannot drift into different namespacing. The generated per-endpoint modules underneath it (recursion_sdk.api.<namespace>.<method>) remain available directly, and expose sync/asyncio variants plus *_detailed forms that return the full response instead of raising.

Opt-in, declared at the source. An operation is in this SDK iff its backend handler carries @SdkRoute(...) (apps/recursion/api/src/common/sdk-route.decorator.ts), read through the same packages/sdk-ts/src/nesting.ts the TypeScript SDK uses, so the two clients cannot cover different operations.

Notes from real use

  • ID fields deserialize to uuid.UUID, not str.
  • Required fields are enforced at model construction, so a partial body fails fast rather than at the server.
  • Some operations document an error status with a description and no schema; for those RecursionApiError.parsed is None and .content carries the bytes.

Install

Not published to a package registry yet — no free Python index has been chosen, and the TypeScript SDK's private Artifact Registry release is npm-specific. Build and install the wheel locally:

yarn dx python-sdk:generate                    # pip venv, no Docker
cd packages/sdk-python
python3 -m build                               # or `uv build`, if you have it
pip install dist/recursion_sdk-*.whl

Requires Python 3.11+ (the generated client imports typing.Self).

Tooling: pip + hatchling, no lockfile — matching mcp_server, the repo's only other Python package. uv is not a repo dependency, and yarn dx ci:python-sdk deliberately uses stdlib venv + pip so the gate needs nothing beyond the interpreter. Both work locally; uv is just faster. There is no uv.lock or requirements.txt on purpose: this is a library, so it declares dependency ranges and lets the consuming application own the resolution.

Regenerating

# Regenerate the client from the committed spec snapshot (packages/sdk-ts/openapi.json).
yarn dx python-sdk:generate

# Everything CI runs: regenerate, build the wheel, install it into a clean
# virtualenv, and run the test suite against that installed distribution.
yarn dx ci:python-sdk

Refreshing the snapshot itself is the TypeScript SDK's job (yarn dx sdk:generate --refresh-spec); this package only ever reads it.

The generator-private projection

The committed snapshot is a mixed OAS 3.0/3.1 document: Nest + nestjs-zod emit 3.0 (nullable: true, boolean exclusiveMinimum) while the merged Managed Agents Go schemas are already JSON Schema 2020-12 (type: "null", prefixItems). Relabelling one as 3.1 would silently discard the 3.0 halves' meaning, since nullable is not a 3.1 keyword.

So yarn dx python-sdk:generate writes a generator-private projection (openapi.generated.json, gitignored) that converts rather than relabels, and feeds the generator that. It never touches the snapshot, the TypeScript SDK, or the backend. Each transform, and why it preserves semantics, is documented in tools/dx/src/commands/python-sdk.ts and pinned by tools/dx/src/commands/python-sdk.test.ts.

The projection is not cosmetic — it is measurably what makes generation complete. From the unprojected spec the generator emits 342/343 operations with parse failures on the recursive-union endpoints; from the projection, 343/343 with one allowlisted warning.

Generation then fails on any generator diagnostic that is not explicitly allowlisted, and on any opted-in operation missing from either the generated tree or the facade. The generator exits 0 while printing "Client was generated, but some pieces may be missing", so neither is implied by a successful run. The one allowlisted warning is an application/x-yaml alternative request encoding on a single Managed Agents operation; the application/json variant every other operation uses is generated normally. The allowlist is keyed by operation and signature, so the same warning elsewhere still fails.

Not a Yarn workspace

packages/AGENTS.md requires every new package under packages/ to be registered in the root workspaces array, tools/dx/src/context.ts, tools/dx/src/commands/workspace.ts, and the backend Dockerfile. None of that applies here: those steps exist so Node consumers can require.resolve() the package's dist/ and so yarn install --immutable sees every manifest. This package has no package.json, is not in the Node dependency graph, and is never installed into the backend image. Registration is keyed on package.json discovery (tools/dx/src/workspace-registration.test.ts), so there is nothing to register.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

labelbox_recursion_sdk-0.0.23.tar.gz (936.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

labelbox_recursion_sdk-0.0.23-py3-none-any.whl (2.6 MB view details)

Uploaded Python 3

File details

Details for the file labelbox_recursion_sdk-0.0.23.tar.gz.

File metadata

  • Download URL: labelbox_recursion_sdk-0.0.23.tar.gz
  • Upload date:
  • Size: 936.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for labelbox_recursion_sdk-0.0.23.tar.gz
Algorithm Hash digest
SHA256 1e566d72fa0fb06cdb95f6152c041aba1a658654dc2fedbc5f3d9c555acc84ed
MD5 6f02fc3a4d34b8d91a35e97847c76cd0
BLAKE2b-256 204ea968e78dc8edd65f0af4ab860875d9fb226c6dbb80953a73b7b4c6735b2d

See more details on using hashes here.

Provenance

The following attestation bundles were made for labelbox_recursion_sdk-0.0.23.tar.gz:

Publisher: release-python-sdk.yml on Labelbox/recursion-platform

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file labelbox_recursion_sdk-0.0.23-py3-none-any.whl.

File metadata

File hashes

Hashes for labelbox_recursion_sdk-0.0.23-py3-none-any.whl
Algorithm Hash digest
SHA256 0c7d542d49fe4e994a3435bd835a86ad8f2815324fb93e0778dcd2e7ad2a7af8
MD5 cfe91a30e8cab0ed99349e97e129c41a
BLAKE2b-256 e4120746328a9679d1021811beab602dfc47e31f0dfbff6278bcdf477379b025

See more details on using hashes here.

Provenance

The following attestation bundles were made for labelbox_recursion_sdk-0.0.23-py3-none-any.whl:

Publisher: release-python-sdk.yml on Labelbox/recursion-platform

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.0.36

2 files

0.0.35

2 files

0.0.34

2 files

0.0.33

2 files

0.0.32

2 files

0.0.31

2 files

0.0.30

2 files

0.0.29

2 files

0.0.28

2 files

0.0.27

2 files

0.0.26

2 files

0.0.25

2 files

0.0.24

2 files

This release

0.0.23 This release

2 files

0.0.22

2 files

0.0.21

2 files

0.0.20

2 files

0.0.19

2 files

0.0.18

2 files

0.0.17

2 files

0.0.16

2 files

0.0.15

2 files

0.0.14

2 files

0.0.13

2 files

0.0.12

2 files

0.0.11

2 files

0.0.10

2 files

0.0.9

2 files

0.0.8

2 files

0.0.7

2 files

0.0.6

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page