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

# Quickstart

> Ship a Voyage-instrumented agent in 60 seconds

This guide gets you from zero to a working Voyage in under a minute of
reading. For the conceptual overview, see [Voyages](./voyages).

Working through this with a coding agent? Point it at the
[Sail skills package](https://github.com/sailresearchco/sail-skills) and ask:

```text theme={null}
Build a small background agent on Sail with Voyage telemetry. Keep the
agent harness simple, use the sail package, wrap the run with
sail.voyage.run(..., version=1), use @sail.agent and @sail.span for
attribution, make the dashboard trace show model calls, and attribute Sailbox
execs only if the workload already uses a Sailbox.
```

## Prerequisites

* Python 3.9+
* A Sail API key
* The Sail SDK: `pip install sail`

## Step 1: install + auth

```bash theme={null}
pip install sail
export SAIL_API_KEY=sk_your_key_here
```

`SAIL_API_KEY` always wins. When it is unset, the SDK uses the credential
stored by `sail auth login` under `~/.sail`.

## Step 2: write the minimal Voyage

```python theme={null}
# voyage_hello.py
import sail

@sail.agent("Researcher")
@sail.span("say hello")
def say_hello():
    sail.voyage.event("hello.fired", payload={"message": "hi from sail"})
    response = sail.inference.responses.create(
        model="zai-org/GLM-5.2-FP8",
        input="In one sentence, say hello.",
        background=False,
    )
    sail.voyage.event("inference.done", payload={"response_id": response["id"]})


with sail.voyage.run(
    name="hello-voyage",
    version=1,
    metadata={"example": "quickstart"},
):
    say_hello()

print(f"Open: {sail.voyage.dashboard_url()}")
```

`run()` emits `voyage.completed` when the block exits cleanly. If the block
raises, it emits `voyage.failed` and re-raises. No try/except needed.

## Step 3: run it

```bash theme={null}
python voyage_hello.py
```

You should see one line printed:

```
Open: https://app.sailresearch.com/prod/voyages/voy_...
```

## Step 4: verify in the dashboard

Open the printed URL. You should see:

* **Status:** `voyage completed`
* **Agents:** 1 (`Researcher`)
* **Events:** 2 (`hello.fired`, `inference.done`)
* **Model calls:** 1 (`zai-org/GLM-5.2-FP8`, status `completed`)
* **Execution Trace:** one agent block with one span, two events nested
  underneath, one model row.

You now have a Voyage: a dashboard trace for a background agent run, including
events, model-call attribution, and terminal status.

## Decorators

For function-shaped work, decorate instead of nesting context managers. You get
the same events, spans, and attribution:

```python theme={null}
import sail

@sail.agent("Researcher")
@sail.span()
def say_hello():
    sail.voyage.event("greeting.sent", payload={"channel": "stdout"})

with sail.voyage.run(name="hello-voyage", version=1):
    say_hello()
```

Calls you do not wrap are still captured. Sail inference and Sailbox execs made
inside a Voyage get automatic, timed spans named after your calling code and
marked "auto" in the dashboard.

## What to do next

* Add a Sailbox: see the [Sailboxes guide](./sailboxes) for creating a
  long-running sandboxed VM, then pass `sailbox_id=sb.sailbox_id` to
  `sail.voyage.create()` so the Voyage is bound to that Sailbox.
* Prefer an agent-guided setup? Use the
  [Sail skills package](https://github.com/sailresearchco/sail-skills) and ask
  your coding agent to build or instrument a background agent with Voyage
  telemetry.
* Add a second agent: see [Voyages Patterns → Multi-agent](./voyages-patterns#multi-agent).
* Something looking wrong? Install the
  [Sail skills](https://github.com/sailresearchco/sail-skills) and use the
  `sail-voyage-debugging` skill.

## Common first-run gotchas

* **Voyage doesn't appear in dashboard.** Make sure `SAIL_API_KEY` is set to
  a valid Sail API key (`sk_...`). Events are recorded against the key's
  org, so a missing or wrong-org key means nothing shows up.
* **Process exits without a terminal event.** The Voyage stays
  "in progress" forever (a bounded best-effort flush at exit delivers
  trailing events, but can still drop them if the network is down. It also
  never marks the Voyage terminal). Use `with sail.voyage.run(...)` so the
  terminal state is emitted for you, or call `voyage.complete()` /
  `voyage.fail()` yourself.
* **Unexpected "auto" spans.** If a Sail inference call or Sailbox exec runs
  inside a Voyage with no active span, the SDK creates a timed span for it
  automatically. That is expected. Add `@sail.span(...)` only when you want to
  choose the step name yourself.
* **`CERTIFICATE_VERIFY_FAILED` on macOS Python.** Some python.org installs do
  not have a usable root CA bundle. Install `certifi` and point Python at it:
  `python -m pip install certifi`, then
  `export SSL_CERT_FILE="$(python -c 'import certifi; print(certifi.where())')"`.
* **Unsupported model.** Use a model id from Sail, not necessarily the model
  your coding agent is using. Start with `zai-org/GLM-5.2-FP8`; to list your
  account's available models, call `GET https://api.sailresearch.com/v1/models`
  with your `SAIL_API_KEY`.
