> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usesynth.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK Quickstart

> Use SynthClient().research to start runs, preflight projects, and inspect evidence.

Use **`synth-ai[research]`** for scripts, CI jobs, notebooks, or typed Python workflows.

Entry point: **`SynthClient().research`**. Full method list: [SDK Reference](/reference/sdk/index).

## Install and authenticate

```bash theme={null}
uv add "synth-ai[research]==0.13.0"
export SYNTH_API_KEY="sk_..."
```

```python theme={null}
from synth_ai import SynthClient

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

## Create a project and preflight

```python theme={null}
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`](/reference/sdk/research/synth_ai-research-runs) and [`projects.setup`](/reference/sdk/research/synth_ai-research-project_namespaces).

## Start a run

```python theme={null}
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

```python theme={null}
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](/reference/sdk/research/synth_ai-research-run_readouts).

## Factory Tag (optional)

For one-off factory ops, use Tag under factories:

```python theme={null}
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](/reference/sdk/research/synth_ai-research-factories).

## Errors and denials

The SDK raises typed exceptions for launch-time failures. Use `check_preflight` before spending runtime.

| HTTP    | Typical meaning                         | What to do                                         |
| ------- | --------------------------------------- | -------------------------------------------------- |
| **402** | Insufficient credits or spend headroom  | Check [Usage and Budgets](/managed-research/usage) |
| **429** | Rate, capacity, or concurrent-run limit | Retry later or inspect `research.limits.get()`     |

See [Errors](/reference/sdk/research/synth_ai-research-errors) and [Preflight and Errors](/managed-research/preflight-and-errors).
