Skip to main content

Bystro Think Python API

The Think SDK is a synchronous, typed client for durable Bystro agent workloads. It intentionally exposes a small surface: authenticate, upload artifacts, compose context, submit work, observe progress, answer pauses, and resume by run ID.

Install

Bystro 2.1 supports CPython 3.11 and 3.12. Activate the environment you want to use, confirm it with python --version, and install from PyPI:

python -m pip install "bystro>=2.1.0,<2.2"

Production endpoints use publicly trusted HTTPS certificates, so no custom CA bundle or TLS override is required. A private CA bundle is only needed for a local development deployment that uses its own certificate authority.

Authenticate

auth.login uses the same bystro.cloud dashboard account as the browser and caches its JWT in ~/.bystro/bystro_authentication_token.json. The directory is mode 0700, the file is atomically replaced at mode 0600, and tokens are never printed.

from bystro.api import auth
from bystro.think import ThinkClient

auth.login("you@example.com", "your-password")
client = ThinkClient.from_cached_login()

For short scripts, login and construction can be one call:

client = ThinkClient.login("you@example.com", "your-password")

If the deployment keeps Bystro's shared site-access gate enabled, present its code during the same login. The SDK establishes the gate cookie and performs dashboard login in one private session; the code is never written to the auth cache:

import os

client = ThinkClient.login(
    "you@example.com",
    "your-password",
    site_access_code=os.environ["BYSTRO_SITE_ACCESS_CODE"],
)

New accounts must explicitly provide the dashboard's signed legal assertions:

from bystro.api.auth import LegalConsent, signup

signup(
    "you@example.com",
    "your-password",
    "Your Name",
    legal_consent=LegalConsent.accepted("Your Name"),
    site_access_code=os.environ["BYSTRO_SITE_ACCESS_CODE"],
)

site_access_code is the Bystro application gate, not a Cloudflare credential. Cloudflare must still allow non-browser traffic to the dashboard authentication and Think API routes while retaining its challenge on browser pages.

The SDK exchanges that dashboard session through Think's existing cookie-auth admission endpoint. The application credential created by Think remains on the server; it is not copied into local code or exposed as a second API key.

Upload files and submit them with a question

Passing paths to submit uploads each file to personal input artifacts first, then attaches the resulting artifact records to the same user message:

run = client.submit(
    "Find variants associated with the case phenotype.",
    files=["cohort.vcf.gz", "phenotypes.tsv"],
)

Uploads use the production resumable protocol: bounded 10 MiB chunks, per-chunk SHA-256 checksums, idempotent retries with exponential backoff, and polling for asynchronous server finalization. The chunk size and retry policy can be configured on ThinkClient. An artifact_path is relative, has at most 64 components, and must end in the local file's exact name; invalid paths fail locally before authentication or upload begins.

Use upload_artifact when the artifact should be created before the question:

def report_upload(progress):
    print(progress.phase.value, f"{progress.fraction:.0%}")

artifact = client.upload_artifact(
    "cohort.vcf.gz",
    artifact_path="study/cohort.vcf.gz",
    on_progress=report_upload,
)
run = client.submit("Run QC on this cohort", files=[artifact])

upload is an equivalent shorter alias.

Compose genetic, conversation, and artifact context

Context helpers accept either a plain string or an immutable MessageWithContext, so calls compose naturally:

from bystro.think import (
    add_artifact_context,
    add_genetic_context,
    add_previous_conversation_context,
)

message = "Compare the strongest signals"
message = add_genetic_context(
    "annotation-job-id",
    message,
    name="Case cohort",
    assembly="hg38",
)
message = add_previous_conversation_context(
    "prior-thread-id",
    message,
    name="Earlier analysis",
)
message = add_artifact_context(artifact, message)

run = client.submit(message)

Reusable higher-order transforms are also available:

from bystro.think import (
    artifact_context,
    compose_context,
    genetic_context,
    previous_conversation_context,
)

study_context = compose_context(
    genetic_context("annotation-job-id", name="Case cohort", assembly="hg38"),
    previous_conversation_context("prior-thread-id"),
    artifact_context("existing-artifact-id"),
)

run = client.submit(study_context("Re-evaluate the phenotype association"))

message.to_xml() returns a safely escaped preview of the semantic context. On the wire, references remain structured metadata. Think resolves artifacts against the authenticated user before creating canonical input-file context; dataset and conversation retrieval tools independently enforce ownership before returning referenced data. Raw user-authored XML is never treated as an ownership boundary.

Handle needs_input

wait() returns exactly one of two values: RunResult or NeedsInput. Clarifications and plan review are durable checkpoint states, not transient socket prompts.

from bystro.think import InputKind, NeedsInput

outcome = run.wait(timeout=3600)
if isinstance(outcome, NeedsInput):
    if outcome.kind is InputKind.PLAN_REVIEW:
        run.respond("accept")
    else:
        run.respond("Use case_control as the phenotype column")
    outcome = run.wait(timeout=3600)

The first live pause notification can arrive just before its checkpoint is committed, so checkpoint_id may initially be None. run.respond() requests the durable replay automatically and will not upload attachments or dispatch the response until the checkpoint is present. Once answered, replays of that same or an older checkpoint are ignored, preventing reconnect races from reopening a stale question. If synchronization fails, the pause remains intact and RunProtocolError asks you to call run.refresh() and retry. A billing pause is also represented as NeedsInput, but must be resolved through the billing action in the dashboard; then call run.refresh().

Progress and reconnects

Pass a callback to the client for all runs, or to wait for one wait cycle:

def progress(event):
    print(event.sequence, event.kind.value, event.message or "")

client = ThinkClient(on_event=progress)
run = client.submit("Perform a GWAS", files=["cohort.vcf.gz"])
result = run.wait()

Alternatively, omit the client-level callback and pass on_event=progress to one wait() call. Do not pass the same callback at both levels unless duplicate delivery is intentional.

The durable run ID is available immediately after admission:

print(run.id)

Another process can attach to it later:

client = ThinkClient()
run = client.resume("run-or-thread-id")
outcome = run.wait()

run.messages provides the hydrated transcript and run.history provides bounded SDK progress history. Socket reconnects automatically replay the current overlay state. When a replayed needs_input overlay arrives before its transcript, wait() holds the outcome until transcript hydration restores the clarification or plan-review prompt.

Follow-up turns and errors

After a successful result, start another turn in the same conversation:

run.follow_up("Now stratify the result by ancestry")
next_result = run.wait()

Transport, HTTP, billing, admission, timeout, and protocol failures have typed exceptions under bystro.think. A ThinkClient owns one foreground run at a time; use separate clients for concurrently controlled conversations. Closing a client disconnects local transports but does not cancel durable server work.

Download files

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

Source Distribution

bystro-2.1.0.tar.gz (22.0 MB view details)

Uploaded Source

Built Distributions

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

bystro-2.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (22.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

bystro-2.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (22.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

bystro-2.1.0-cp312-cp312-macosx_11_0_arm64.whl (22.3 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

bystro-2.1.0-cp312-cp312-macosx_10_12_x86_64.whl (22.3 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

bystro-2.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (22.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

bystro-2.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (22.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

bystro-2.1.0-cp311-cp311-macosx_11_0_arm64.whl (22.3 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

bystro-2.1.0-cp311-cp311-macosx_10_12_x86_64.whl (22.3 MB view details)

Uploaded CPython 3.11macOS 10.12+ x86-64

File details

Details for the file bystro-2.1.0.tar.gz.

File metadata

  • Download URL: bystro-2.1.0.tar.gz
  • Upload date:
  • Size: 22.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.14.1

File hashes

Hashes for bystro-2.1.0.tar.gz
Algorithm Hash digest
SHA256 682f2e2837b242c990dcaf39deef3444fc4d44ba287c091f6febff0370facc1f
MD5 ebceeb02030683fc9bf2ef7d6d272c5a
BLAKE2b-256 f3425d6de1fc207f2c526d35c1f8a592b8d038dffc86d574b240f2813d37e11b

See more details on using hashes here.

File details

Details for the file bystro-2.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for bystro-2.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c002317552a438fcfcdd2e3a7b29a2823b4a7f19c79e85b1acc44b9589064e5f
MD5 69d8d91e9fcbbecfe913be26c6025850
BLAKE2b-256 1008b491f2dfa1b3b1a89666db1b21484b820a42bb21239d3a9bccdee740d864

See more details on using hashes here.

File details

Details for the file bystro-2.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for bystro-2.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5343e2d5b5663755b01f0d9025fbd5a87bfe7e9919a8d789e5da1552d63be71a
MD5 437296efbd3fa12635148c799c14659b
BLAKE2b-256 c9b3a05b0d0a4d22a5ebadef0d79c2db0e189302e7ad84792b61ac197bb3d08e

See more details on using hashes here.

File details

Details for the file bystro-2.1.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bystro-2.1.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ce654df6e7d8cfac2c556527276fac5442837614300a6867bf3af0c3a496d24b
MD5 2f8daa34565adae2e436cadfe9e502eb
BLAKE2b-256 208033e9f8dd3d5251d122d8c34625928fc21eb703d4c44abf599a83765136d1

See more details on using hashes here.

File details

Details for the file bystro-2.1.0-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for bystro-2.1.0-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d9d6ac14252181be331a51926f74fe748cb47daac58e363223544733f5e15f99
MD5 6a76d677f17e32de0aae600dd456bcb1
BLAKE2b-256 e2c3ba535972fc831f638537dd3abf77eca48b943fdf298d9ba3b34133230cf2

See more details on using hashes here.

File details

Details for the file bystro-2.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for bystro-2.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c5843aa84fc91d992c5f32b63fda35c331000d0784640470959f8a098ed4f89a
MD5 f4ec015305060a0816f5e8fa334ea0ff
BLAKE2b-256 c7eabf6c4d8fda2d88c9e4a785d544428d5c001e5351cc7d489e636e1f288550

See more details on using hashes here.

File details

Details for the file bystro-2.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for bystro-2.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5d437749549d1bed17610255fe30d2090782f591700e0bd53ccca6a04fd1a6a8
MD5 237f10c9210797b6d599a595431fa11b
BLAKE2b-256 eec1955b20f265c37f5fe7cede6e5e8342969d0e89f9ea23dfb607d5cc92e833

See more details on using hashes here.

File details

Details for the file bystro-2.1.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bystro-2.1.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5c85e6d44f81e3a81bd0918c55b0b1017e54cd052d3ee7ac7964c29054595955
MD5 8c9f13cc7cc03e4f459ed65b2211854f
BLAKE2b-256 dfa619f7b6112a19d89e77ef18c887c8e5be25b3e61e1940f1c20a9877a34c3e

See more details on using hashes here.

File details

Details for the file bystro-2.1.0-cp311-cp311-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for bystro-2.1.0-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 c8512030982f62aa04b0db68f22c0f4ab25706f0053fba8dc374bdb926ceca2b
MD5 6c23544bb108a0990d56ed686e176135
BLAKE2b-256 f7d73a149875ea76124f0ab538bd1468d93a3eba6e707d663e315e18c95444ae

See more details on using hashes here.

Release history Release notifications | RSS feed

2.1.3

9 files

2.1.2

9 files

2.1.1

9 files

This release

2.1.0 This release

9 files

2.0.0

8 files

1.0.4

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