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

# Python SDK

> The official autumn-sdk package for Python.

The Python SDK is a thin wrapper around the [Task API](/docs/api-routes). Every endpoint is
a method on `client.tasks`; `client.run()` is the high-level helper that starts a task,
polls until it finishes, and returns the output.

## Install

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
pip install autumn-sdk
pip install "autumn-sdk[pydantic]"   # for output_schema
```

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
export AUTUMN_API_KEY=your_key
```

## Clients

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from autumn_sdk import AutumnClient, AsyncAutumnClient

client = AutumnClient()                       # reads AUTUMN_API_KEY
client = AutumnClient(api_key="...", base_url="https://api.autumn.ai")
```

Both clients support context managers (`with AutumnClient() as client:` /
`async with AsyncAutumnClient() as client:`).

## High-level

| Method                                                                                            | Description                                                              |
| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| `client.run(prompt, *, clarify=False, output_schema=None, poll_seconds=2, timeout=14400, **body)` | Start a task, wait to completion, return a `RunResult`.                  |
| `client.stream(prompt, ...)`                                                                      | Start a task and return a `RunHandle` you can iterate for live messages. |

In the async client, `client.run(...)` returns an `AsyncRunHandle` that is both awaitable
(`await client.run(...)` → `RunResult`) and async-iterable (`async for msg in run`).

### RunResult

| Field            | Description                                                                                 |
| ---------------- | ------------------------------------------------------------------------------------------- |
| `result.task_id` | Durable task id.                                                                            |
| `result.status`  | Final status.                                                                               |
| `result.output`  | Flattened output rows (`{field: value}`), or validated objects when `output_schema` is set. |
| `result.rows`    | Raw rows as returned by the API, including sources and metadata.                            |
| `result.task`    | The full terminal `Task` record.                                                            |

Output rows come back as "cell" objects: each field is `{"value": ..., "source_id": ...}`
plus metadata like `_sources` and `_validation`. `result.output` flattens these to plain
`{field: value}` dicts for you; use `result.rows` when you need the sources and provenance.

## Resources

All map one-to-one to Task API routes:

| Method                                                                | Route                                               |
| --------------------------------------------------------------------- | --------------------------------------------------- |
| `client.tasks.create(prompt, *, clarify=False, **body)`               | `POST /task`                                        |
| `client.tasks.start(task, *, prompt="", **body)`                      | `POST /task/start`                                  |
| `client.tasks.get(task_id)`                                           | `GET /task/{task_id}`                               |
| `client.tasks.list()`                                                 | `GET /task`                                         |
| `client.tasks.output(task_id, *, limit=100, output=None)`             | `GET /task/{task_id}/output`                        |
| `client.tasks.outputs(task_id)`                                       | `GET /task/{task_id}/outputs`                       |
| `client.tasks.continue_(task_id, message, **body)`                    | `POST /task/{task_id}/continue`                     |
| `client.tasks.execute(task_id, **body)`                               | `POST /task/{task_id}/execute`                      |
| `client.tasks.stop(task_id)`                                          | `POST /task/{task_id}/stop`                         |
| `client.credits()`                                                    | `GET /credits`                                      |
| `client.workflow()`                                                   | `GET /task/workflow`                                |
| `client.metaprompt()`                                                 | `GET /task/metaprompt`                              |
| `client.files.upload(path, *, task_id="", filename="", content=None)` | `/tasks/draft` + `/upload-url` + `/validate-upload` |

## Attach a CSV

`files.upload()` runs the whole three-call upload for you: it creates a task if you do not
pass `task_id`, presigns, PUTs the bytes without your API key attached, and validates.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from autumn_sdk import AutumnClient

client = AutumnClient()

attached = client.files.upload("leads.csv")
result = client.run(
    "Enrich every row with the company domain",
    task_id=attached["task_id"],
    input_files=[attached["filename"]],
)
```

`attached` carries the validated shape — `filename`, `rows`, `fields`, `renamed`,
`delimiter`, and `extra_columns`. Pass `content=` with `filename=` instead of `path` to
upload from memory. Accepts `.csv`, `.txt`, `.md`, `.markdown` up to 10 MB / 10,000 rows.
The async client exposes the same method as `await client.files.upload(...)`.

## Errors

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from autumn_sdk import (
    AutumnAPIError, AuthenticationError, OutOfCreditsError,
    TaskExecutingError, TaskNotFoundError, RunTimeoutError,
)
```

`OutOfCreditsError` maps to HTTP 402, `TaskExecutingError` to 409, `AuthenticationError` to
401, `TaskNotFoundError` to 404. `RunTimeoutError` is raised if `run()` exceeds its timeout.

## Terminal state

A finished task returns to `status: "plan"` with `activity: "idle"`. Use
`autumn_sdk.types.is_terminal(task)` rather than checking `status` directly. `run()` and
`stream()` already do.

## See also

<CardGroup cols={2}>
  <Card title="Structured output" icon="braces" href="/docs/guides/structured-output" />

  <Card title="Live messages" icon="radio" href="/docs/guides/streaming" />
</CardGroup>
