Metadata-Version: 2.3
Name: labelbox-recursion-sdk
Version: 0.1.0
Summary: Typed Python SDK for the Recursion API
Requires-Dist: httpx>=0.28.1,<0.29
Requires-Dist: pydantic>=2.12,<3
Requires-Dist: jsonschema>=4.23,<5
Requires-Dist: rfc3339-validator>=0.1.4,<0.2
Requires-Python: >=3.12
Project-URL: Repository, https://github.com/Labelbox/recursion-platform/tree/main/packages/recursion-python-sdk
Description-Content-Type: text/markdown

# Recursion Python SDK

Typed, synchronous and asynchronous request/response access to the Recursion
API. The client and Pydantic models are generated from Recursion's committed
public OpenAPI contract snapshots. Session-event streaming is excluded.

The distribution is
[`labelbox-recursion-sdk`](https://pypi.org/project/labelbox-recursion-sdk/),
and the Python import is `recursion_sdk`. This implementation starts at version
`0.1.0`; earlier releases contain the retired SDK and its different import/API.
Build a wheel from this checkout to try the implementation before its first
release. Versions remain below 1.0 while the public API evolves.

```python
import os

from recursion_sdk import Recursion

with Recursion(api_key=os.environ["RECURSION_API_KEY"]) as recursion:
    result = recursion.managed_agents.list_sessions()
    print(result.data, result.response.headers.get("etag"))
```

`AsyncRecursion` exposes the same methods as coroutines and supports
`async with`. The production base URL is `https://api.recursion.labelbox.com`.
Set `organization_id` or `tenant_id` on the constructor when the API key
requires those selectors. Operation-level selectors may repeat those values;
they cannot change the constructor's scope.

Methods return `ApiResponse` with typed `data` and the original HTTPX
`response`, including status and headers. A declared bodyless 304 has
`data=None`. Declared API errors raise `RecursionAPIError`; malformed or
undeclared responses raise `RecursionContractError`. HTTPX transport failures
retain their HTTPX exception types. Request and response values are validated
against the canonical schemas, including constraints beyond Pydantic's model
annotations.

JSON methods accept generated models from `recursion_sdk.models`, with
snake_case attributes and canonical JSON field aliases. Omitted model
fields stay omitted; explicitly supplied `None` becomes JSON null where the
contract permits it. Multipart methods accept `Upload` values, and binary
download methods return bytes. The client has no automatic retries or
pagination; callers retain control of mutation replay and iteration.

## Development

All Python tooling uses uv. Run these commands from the repository root through
the worktree's devbox:

```sh
./devbox exec -- packages/recursion-python-sdk/tools/uv run --locked --project packages/recursion-python-sdk --group dev --script packages/recursion-python-sdk/tools/check.py
```

The package's uv wrapper reuses uv on `PATH` or installs a checksum-verified,
pinned copy under the worktree's `.local/` directory on a Linux devbox. Other
hosts can use an existing uv installation. Nothing is installed globally.

The check command generates, checks formatting, runs strict typing and behavioral
tests, verifies deterministic generation, builds wheel/sdist artifacts, and
checks an isolated installation of the wheel with hashed runtime dependencies
from `uv.lock`. Generated files under
`src/recursion_sdk/_generated/` are ignored; change the public contract or
generator inputs and rerun the check. `yarn check recursion:python-sdk` invokes
the same command through the repository's check registry.

Python dependencies and generated outputs belong to this independent package.
Root Yarn installation, postinstall, JavaScript code generation, and ordinary
application checks do not install or run Python tooling. Dedicated CI runs when
this package or the canonical Recursion public contract changes.

## Generation and ownership

`datamodel-code-generator` compiles schemas into Pydantic v2 models. A small
operation emitter produces typed methods and bundles the unmodified canonical
contract. One shared HTTPX transport owns wire behavior and uses JSON Schema
validation at its boundaries. No endpoint or request/response model is
maintained by hand, and generation requires no JVM or hosted service.

Generation uses the evaluations-enabled snapshot served by production, named
`recursion-public-openapi.preview.generated.json`. Release qualification can
select an exact earlier snapshot with `RECURSION_PYTHON_SDK_CONTRACT_PATH`.

Build after generation, then add the wheel to your application's uv project:

```sh
uv build --project packages/recursion-python-sdk
uv add --project /absolute/path/to/your-python-project /absolute/path/to/labelbox_recursion_sdk-0.0.0-py3-none-any.whl
```

Published releases reuse the existing `labelbox-recursion-sdk` PyPI project.
The source version `0.0.0` identifies local preview builds; the release process
stamps the requested version into release artifacts. The TypeScript SDK release
process is independent.

## Release

The manual [Python release workflow](../../.github/workflows/release-python-sdk.yml)
builds and qualifies an explicit version. Its default run only uploads artifacts:

```sh
gh workflow run release-python-sdk.yml --ref main -f version=0.1.0
```

The SDK code comes from the workflow's commit. By default, its API contract does
too. When `main` contains API changes that have not reached production, set
`PYTHON_SDK_CONTRACT_SOURCE_SHA` to a deployed commit's full SHA and select its
contract explicitly:

```sh
gh workflow run release-python-sdk.yml --ref main -f version=0.1.0 -f contract-source-sha="$PYTHON_SDK_CONTRACT_SOURCE_SHA" -f publish=true
```

The contract source must be a full commit SHA in the workflow commit's ancestry.
The release extracts that commit's production contract without modifying any
tracked snapshot. Generation, behavioral tests, and strict production
verification all consume those exact bytes. Newer API changes on `main` can
therefore coexist with a release for the deployed API. The artifact manifest
records the SDK source commit, contract source commit, snapshot path, and hash.

For a local build without publishing, use an ignored artifact directory from a
clean checkout:

```sh
yarn release python-sdk:prepare --version 0.1.0 --artifact-dir "$PWD/.agent/python-sdk-release"
```

The local command also accepts `--contract-source-sha <full-commit-sha>` and
`--verify-production true` for the same source selection and production check
without uploading anything.

The release command rejects published/older versions, temporarily stamps the
package and lockfile, runs the full qualification, and restores the source
metadata. The immutable candidate contains the wheel, source distribution,
checksums, and its source commit.

Passing `-f publish=true` to the workflow additionally verifies the source
contract in production and publishes those exact archives with `uv publish`
through PyPI trusted publishing. It retains the existing publisher identity:
repository `Labelbox/recursion-platform`, workflow `release-python-sdk.yml`,
environment `publish`, project `labelbox-recursion-sdk`. The final job verifies
PyPI's archive hashes before recording `python-sdk-v<version>` at the source
commit. Publication and Git tagging have separate credentials; release runs
never commit version changes to the branch.
