We use Rye to manage dependencies because it will automatically provision a Python environment with the expected Python version. To set it up, run:
$ ./scripts/bootstrapOr install Rye manually and run:
$ rye sync --all-featuresYou can then run scripts using rye run python script.py or by activating the virtual environment:
# Activate the virtual environment - https://docs.python.org/3/library/venv.html#how-venvs-work
$ source .venv/bin/activate
# now you can omit the `rye run` prefix
$ python script.pyAlternatively if you don't want to install Rye, you can stick with the standard pip setup by ensuring you have the Python version specified in .python-version, create a virtual environment however you desire and then install dependencies using this command:
$ pip install -r requirements-dev.lockThis SDK is fully owned and hand-maintained by LandingAI; it is no longer regenerated by Stainless. All code in the repository can be edited directly, like any other codebase.
Please use Conventional Commits for commit messages and PR
titles (feat:, fix:, chore:, …) — the release changelog is grouped by these prefixes.
Releases are cut manually: a maintainer runs the Release workflow (Actions → Release → Run
workflow) and chooses the version bump (patch / minor / major). The workflow lands a
release: x.y.z commit on main (version stamping + changelog), tags it, and creates the GitHub
Release — which triggers publishing. Ordinary PR merges never trigger a release.
Files in the examples/ directory can be freely edited or added to.
# add an example to examples/<your-example>.py
#!/usr/bin/env -S rye run python
…$ chmod +x examples/<your-example>.py
# run the example against your api
$ ./examples/<your-example>.pyIf you’d like to use the repository from source, you can either install from git or link to a cloned repository:
To install via git:
$ pip install git+ssh://git@github.com/landing-ai/ade-python.gitAlternatively, you can build from source and install the wheel file:
Building this package will create two files in the dist/ directory, a .tar.gz containing the source files and a .whl that can be used to install the package efficiently.
To create a distributable version of the library, all you have to do is run this command:
$ rye build
# or
$ python -m buildThen to install:
$ pip install ./path-to-wheel-file.whl$ ./scripts/testThis repository uses ruff and black to format the code in the repository.
To lint:
$ ./scripts/lintTo format and fix all ruff issues automatically:
$ ./scripts/formatChanges made to this repository via the automated release PR pipeline should publish to PyPI automatically. If the changes aren't made through the automated pipeline, you may want to make releases manually.
You can release to package managers by using the Publish PyPI GitHub action. This requires a setup organization or repository secret to be set up.
If you need to manually release a package, you can run the bin/publish-pypi script with a PYPI_TOKEN set on
the environment.
The SDK tracks the live ADE OpenAPI spec automatically via .github/workflows/spec-sync.yml
(hourly cron + manual workflow_dispatch). It is driven by the staging spec; releases gate on
the production spec ("staging in, production out").
It runs two independent loops (one job each): the V1 loop tracks the V1 spec against
specs/v1-ade.json, and the V2 loop tracks the V2 spec on the AIDE gateway
(aide.[env]/openapi.json) against specs/v2-aide.json on a separate spec-sync/v2 branch. Both
reuse the same scripts. (Note the host split: the V2 spec is published at aide.[env], but the
V2 API the SDK calls is api.ade.[env].)
On each run a loop fetches and normalizes its live spec (scripts/spec-sync/fetch-normalize.sh) and
diffs it against its committed snapshot (scripts/spec-sync/check-drift.sh). Staging auto-reclaims
and must be booked, so an unavailable spec source (an unbooked cluster 404s, or the host stops
answering) is treated as an expected no-op — the run ends cleanly with no PR and no Slack alert, and
the next run picks up drift once staging is booked. A reachable source that returns an error status
(401/403/5xx) or an empty/invalid spec still fails loudly and alerts. On drift it opens one PR with
two attributed commits (paths shown for V1; the V2 loop uses the v2-aide/v2_models equivalents):
- Mechanical — updated
specs/v1-ade.jsonsnapshot plus regenerated reference models inspecs/_generated/v1_models.py(scripts/spec-sync/gen-models.sh,datamodel-code-generator). These reference models are an input for the AI step and for review — they are not shipped and do not replacesrc/landingai_ade/types/*. - AI —
anthropics/claude-code-action(automation mode) wires the resources, methods, param types, tests, and docs from the spec diff, following existing conventions.
Every spec-sync PR (and any PR to main) must pass .github/workflows/pr-gates.yml:
- surface-lock (
scripts/spec-sync/surface-lock.sh,griffe) — baseline is the last release tag, so any change to released public surface fails mechanically. Merged-but-unreleased surface stays mutable. - contract-tests —
tests/contract(markercontract) run against staging whenLANDINGAI_ADE_STAGING_APIKEYis set; skipped otherwise. Because this job executes the AI-authored commit's code with the staging key in env, it is gated behind the protectedspec-sync-contractenvironment (required reviewer) so the key is only exposed after a human has inspected the diff — configure required reviewers on that environment in repo Settings.
Spec-sync PRs are AI-drafted and require human review before merge.
Secrets required: SPEC_SYNC_TOKEN (a fine-grained PAT scoped to this repo with
Contents: Read and write and Pull requests: Read and write), ANTHROPIC_API_KEY, and
LANDINGAI_ADE_STAGING_APIKEY. SPEC_SYNC_TOKEN must not be the default GITHUB_TOKEN:
pushes and PRs authored by GITHUB_TOKEN do not trigger the gate workflows (GitHub
anti-recursion), so the gates would never run on the sync PR. A GitHub App installation token
(org-owned) is the cleaner long-term choice and can replace the PAT without other workflow
changes.
V2 status: the V2 loop is implemented (the spec-sync-v2 job + specs/v2-aide.json +
specs/_generated/v2_models.py). Its baseline is the full current spec, so it ships live but quiet
and fires only on a future real change; /v2/workflow is intentionally deferred (kept in the
baseline and excluded in the AI prompt). Its AI step is hardened beyond V1's — no shell, and a
product-code allowlist enforced before formatting/staging (see .github/workflows/spec-sync.yml).
The same pipeline shape ports to ade-typescript with openapi-typescript (mechanical) and
api-extractor (surface-lock), tracked separately.