This release is a pre-release and may not be stable for production use.
Synth AI SDK
Typed Index v0.2 APIs include QA and lifecycle operations, exact-revision rights attestations, and resealed research corrections.
Python SDK, CLI and MCP servers for Synth Index (cited search over reviewed
research) and Swarms (hosted research runs under client.research.swarms).
Documentation: https://docs.usesynth.ai/sdk/overview
Installation
uv add synth-ai
Authenticate
Free anonymous public Index Search needs no key (see Synth Index).
Keyed Index Search, private collections and Swarms need SYNTH_API_KEY:
export SYNTH_API_KEY="sk_..."
A key selects the paid keyed Index route; it never makes a public request free.
Local Workspaces
For local multi-repo development, synth-ai treats workspace resolution as a
read-only overlay. .env and Synth home config may provide defaults and
secrets; selecting a worktree must not rewrite those defaults.
Use SYNTH_WORKSPACE_MANIFEST or SYNTH_WORKSPACE_ROOT for command-scoped
worktree resolution. The resolver in synth_ai.core.utils.workspace returns
repo paths and a scoped env mapping for subprocesses without mutating .env.
Pass base_url when you need to pin a production, local, staging, or private
backend explicitly:
from synth_ai import SynthClient
client = SynthClient(base_url="http://127.0.0.1:8000")
The CLI also reads SYNTH_BACKEND_URL and accepts --backend-url.
Quickstart: Swarms
from synth_ai import SynthClient
from synth_ai.sdk.research.public import SwarmSpec
with SynthClient() as client:
swarm = client.research.swarms.create(
SwarmSpec(objective="Assess this repository and produce a concise report.")
)
for event in swarm.events():
print(event.kind, event.telemetry.sequence)
result = swarm.wait(timeout_seconds=900)
print(result.swarm_id, result.state)
resolved = swarm.configuration()
print(resolved.config_version_id, resolved.snapshot_sha256)
usage = swarm.usage()
print(usage.money.nominal_pico_usd, usage.tokens.totals.input_tokens)
evidence = swarm.evidence()
print(evidence.artifacts, evidence.work_products)
create returns a durable handle immediately. events() yields typed events,
including an explicit UnknownSwarmEvent for forward-compatible server events;
wait() uses a monotonic deadline and returns the terminal typed Swarm.
configuration() returns the immutable, versioned, secret-redacted launch
snapshot bound to that swarm, so replay and audit do not depend on the
project's current mutable configuration.
usage() returns one typed cost, token, and actor-attribution projection plus
its source, record count, observation time, and terminal-state freshness. It
does not expose the legacy raw ledger-entry dictionaries.
evidence() returns the complete durable artifact and WorkProduct index with
strict counts and lifecycle freshness. Artifact and WorkProduct content reads
use the same typed transport and return bytes; they do not expose storage
authority.
Research SDK (Swarms)
SynthClient().research hosts Swarms. Its stable namespaces are projects,
swarms, and factories (the last is a supported compatibility API; it is not
part of this release's recommended path).
Create a durable project when work needs reusable configuration:
from synth_ai import SynthClient
from synth_ai.sdk.research.public import EnvironmentKind, ProjectSpec, RuntimeKind, SwarmSpec
with SynthClient() as client:
project = client.research.projects.create(
ProjectSpec(
name="Repository assessment",
pool_id="pool_default",
runtime_kind=RuntimeKind("python"),
environment_kind=EnvironmentKind("docker"),
orchestrator_profile_id="profile_orchestrator",
default_worker_profile_id="profile_worker",
)
)
swarm = client.research.swarms.create(
SwarmSpec(objective="Produce the assessment."),
project_id=project.project_id,
)
print(swarm.wait().state)
Limits, economics, secrets, Tag, rich evidence projections, and administrative
resource APIs remain available under client.research.advanced while their
contracts are stabilized. Advanced APIs are not covered by the stable surface
guarantee.
CLI discovery:
synth-ai research --help
Project creation also accepts the backend-owned ProjectSpec.policy mapping.
For example, a server-enabled fresh project can request
policy={"host_resource_custody_mode": "horizons_docker_sessions_only"}.
The backend validates this restricted mode and owns its immutable resource
binding; SDK serialization does not grant additional authority.
Container pools
The optional synth-ai[pools] extra exposes the canonical synth-containers
client through AsyncSynthClient.pools. It uses the same configured backend
credential and keeps hosted admission, resource ownership, and recovery in the
backend. The enclosing async client closes the pool transport.
from synth_ai import AsyncSynthClient
async def inspect_lease(lease_id: str, task_id: str):
async with AsyncSynthClient() as client:
return await client.pools.get_lease_interactive(lease_id, task_id=task_id)
For explicit lifetime management, from synth_ai.pools import PoolClient
re-exports the same implementation. Research-only installations do not import
this optional dependency. Development candidates must install the exact pinned
containers wheel; an unpublished candidate extra is not a release claim.
CLI
synth-ai --help
synth-ai index --help # Synth Index Search and research intake
synth-ai research --help # Swarms and Research projects
Synth Index
Index Search returns a cited response plus the exact Contribution revisions it
cites. There are two routes, chosen explicitly by the client you use:
| Public route | Keyed route | |
|---|---|---|
| Caller | Anonymous only: no API key or session is sent | SYNTH_API_KEY (or a Clerk session) |
| Python | PublicIndexClient().public_search(...) |
SynthClient().index.search(...) |
| CLI | synth-ai index search --public (0.21.1+) |
synth-ai index search --keyed |
MCP index_search |
No SYNTH_API_KEY in the server env |
SYNTH_API_KEY set; runs only after the org turns on wallet payments |
| Corpus | Published public Contributions | Public, or authorized private collections |
| Price | Free to the caller | Paid: Fast is 5 cents per delivered Search; Deep is 5 cents plus measured model cost, capped by your max_charge_cents and at $1 per Search. The backend publishes the current price. |
| Funding | None | Index promo credit, then the wallet with explicit consent (allow_wallet, max_charge_cents) |
| Limits | Per-caller and platform-wide per-minute/per-day limits, a daily service budget and a Deep concurrency cap, published in capabilities().public_search |
Your organization's mode grants, monthly caps and per-mode concurrency |
| Retention | Published in capabilities().public_search (retention, privacy_copy) |
Your organization's terms; public terms do not describe keyed Search |
The public route exists only where the backend enables it (public_search.enabled
in capabilities); otherwise it fails closed with PublicSearchDisabledError.
The public route refuses any credential (409, PublicSearchAuthenticatedError),
so a key never turns a public request into a free keyed one, and the SDK and CLI
never switch routes on their own.
from synth_ai.sdk.index import PublicIndexClient
with PublicIndexClient() as index: # anonymous: sends no key
print(index.public_search_terms().lines) # price, limits, privacy from capabilities
result = index.public_search("RLVR verifier design", mode="fast", max_results=5)
print(result.response, [item.citation for item in result.citations])
Keyed (paid) Search:
from uuid import uuid4
from synth_ai import SynthClient
from synth_ai.sdk.index import SearchBillingConstraints
request_key = str(uuid4()) # Persist this before sending; reuse it on uncertain retry.
with SynthClient() as synth: # Reads SYNTH_API_KEY.
result = synth.index.search(
query="What evidence supports the retrieval design?",
mode="fast",
billing=SearchBillingConstraints(allow_wallet=True, max_charge_cents=5),
idempotency_key=request_key,
)
print(result.response, result.usage)
CLI:
synth-ai index search "RLVR verifier design" --public
synth-ai index search "RLVR verifier design" --keyed --allow-wallet --max-charge-cents 5
With no key and no route flag the CLI refuses and asks for one. With an inherited
SYNTH_API_KEY, --public still sends no key; without a flag the CLI uses the
keyed route and says so on stderr.
- MCP:
synth-ai-index-mcpis an Index-only stdio server, read-only by default. Setup and per-configuration economics are in the Index SDK guide. - Errors: public-route refusals have their own types (rate limit, budget exhausted, disabled route, credential conflict); see the Index SDK guide.
These calls require a deployed Index API; installing the SDK alone does not make a Search available.
Public Surface
Use SynthClient as the front door:
| Surface | Client namespace | Use it for |
|---|---|---|
| Index | client.index, PublicIndexClient |
Keyed (paid) and anonymous public (free) Search, exact contents. |
| Swarms | client.research.swarms |
Hosted research runs, events, usage and evidence. |
| Research projects | client.research.projects |
Reusable Swarm configuration. |
| CLI / MCP | synth-ai, synth-ai-index-mcp |
Terminal commands and an Index-only coding-agent server. |
Swarms run on Synth's hosted research workers; see the Managed Research docs for repo runs, evidence, checkpoints and final reports.
Swarms Billing
Swarms and other Managed Research work draw from the same org-level allowance and flex-credit wallet. Free, Standard ($20/month), and Max ($200/month) expose premium and value usage windows with reset times, then use explicit flex credits after included usage is exhausted. Premium models consume allowance faster; value models stretch the same allowance further. Promo, make-good, banked, and override grants are manual audit events rather than automatic resets.
The canonical backend surfaces are GET /smr/billing/catalog,
GET /smr/billing/plan, GET /smr/billing/runs/{run_id}/drawdown, and
GET /smr/billing/factory-efforts/{factory_effort_id}/drawdown. In the Python
SDK, use client.research.advanced.economics for authoritative billing reads
while the economics contract remains advanced. Do not infer
allowance from legacy Autumn balances or local spend summaries, and do not
recompute discounts in the client.
Links
Local Development
Use uv run for Python tools:
uv sync --group dev
uv run ruff format --check .
uv run ruff check .
uv run ty check
make docs-gen # generate Blume SDK reference into docs/
make docs-dev # preview at http://localhost:3000/overview
Optional: install Lefthook and run
lefthook install to run formatting, linting, and type checks on staged Python
files.
Metadata
Release files for synth-ai 0.22.2.dev682
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| synth_ai-0.22.2.dev682.tar.gz | 949.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| synth_ai-0.22.2.dev682-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.1 MB
Release files / synth_ai-0.22.2.dev682.tar.gz
| Download URL | synth_ai-0.22.2.dev682.tar.gz |
|---|---|
| Size | 949.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1e2e3452ae8c2d48cde0d2ce5190b329e877ffcd2c9602417948f42ae8e22900
|
|
BLAKE2b-256 checksum How to use checksums |
603dd602ac77e04660d92b36d4b83f1c22f2bcb6ff8d2867b769ab9141a12d9f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / synth_ai-0.22.2.dev682-py3-none-any.whl
| Download URL | synth_ai-0.22.2.dev682-py3-none-any.whl |
|---|---|
| Size | 1.1 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6e754e0f4ddf3120d3c7c544fec31839d06b993b41ee0dfa3e01e31f31edeffc
|
|
BLAKE2b-256 checksum How to use checksums |
ada8052e3f5350b701bd8ac57b379cdc874168950427e1d5bb93b8ebd833ddf1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency log