Skip to main content
Use synth-ai[research] for scripts, CI jobs, notebooks, or typed Python workflows. Entry point: SynthClient().research. Full method list: SDK Reference.

Install and authenticate

uv add "synth-ai[research]==0.13.0"
export SYNTH_API_KEY="sk_..."
from synth_ai import SynthClient

research = SynthClient().research
limits = research.limits.get()

Create a project and preflight

project = research.projects.create(
    {"name": "Improve my eval runner", "work_mode": "directed_effort"}
)
project_id = project.project_id

research.projects.setup.prepare(project_id)

preflight = research.runs.check_preflight(
    project_id=project_id,
    host_kind="daytona",
    work_mode="directed_effort",
    providers=[{"provider": "openrouter"}],
    runbook="lite",
)

if not preflight.get("allowed", preflight.get("clear_to_trigger")):
    raise RuntimeError(preflight)
See runs.check_preflight and projects.setup.

Start a run

handle = research.runs.create(
    project_id,
    objective="Inspect the eval runner, fix the highest-leverage issue, and explain the evidence.",
    host_kind="daytona",
    work_mode="directed_effort",
    providers=[{"provider": "openrouter"}],
    runbook="lite",
)

print("project:", handle.project_id)
print("run:", handle.run_id)

Wait and inspect evidence

final = research.runs.wait(project_id, handle.run_id, timeout=60 * 60, poll_interval=15)

print("state:", final.state)
print("progress:", handle.progress.get())
print("usage:", handle.usage.get())

for message in handle.message_queue.messages.list(limit=20):
    print(message)

print("artifacts:", handle.artifacts.list())
print("logs page:", research.runs.logs_page(project_id, handle.run_id))
Readout reference: Run readouts.

Factory Tag (optional)

For one-off factory ops, use Tag under factories:
session = research.factories.tag.sessions.create("Summarize the failing test output")
research.factories.tag.sessions.messages.send(session.session_id, "Focus on the root cause.")
See Factories.

Errors and denials

The SDK raises typed exceptions for launch-time failures. Use check_preflight before spending runtime.
HTTPTypical meaningWhat to do
402Insufficient credits or spend headroomCheck Usage and Budgets
429Rate, capacity, or concurrent-run limitRetry later or inspect research.limits.get()
See Errors and Preflight and Errors.