> ## 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.

# Introduction

> Observability and timeline for long-running background agents on Sail

Voyages are Sail's telemetry layer for long-running background-agent tasks.
Add a few SDK calls to your existing agent harness. Sail records the run as a
trace of named agents, spans, events, Sail inference calls, and Sailbox execs.
Every Voyage gets its own page in the dashboard at `app.sailresearch.com`,
showing the full trajectory. The SDK returns the link from
`sail.voyage.dashboard_url()`, and the API returns it as `dashboard_url`.

You keep control of the agent loop. Sail provides the runtime pieces
(Sailbox and inference) plus the Voyage timeline.

Voyages are not an agent framework. They do not own your planner, memory,
orchestration, tool abstractions, prompts, or retry policy. Use them with your
own Python scripts, LangGraph, CrewAI, job runners, subprocesses, or any custom
loop where you want visibility into what happened.

<Note>
  **Using a coding agent?** Start with the public [Sail skills
  package](https://github.com/sailresearchco/sail-skills). Tell your agent: "Use
  Sail Voyages to add automatic telemetry to my background agent workload. Keep
  my harness, use the `sail` package, wrap the run with `sail.voyage.run(...,
      version=1)`, add `@sail.agent` and `@sail.span` where they fit naturally, and
  attribute Sail inference calls plus any Sailbox execs the workload already
  uses." You do not need to know the individual skill names. The package gives
  your coding agent the right Voyage instructions when they are relevant.
</Note>

## Install

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

Both paths authenticate SDK processes: the SDK reads `SAIL_API_KEY` first and
falls back to the credential `sail auth login` stores under `~/.sail`. Use
`SAIL_API_KEY` for CI and deployments; logging in once is enough for local
scripts.

## When to use a Voyage

Use a Voyage when:

* An agent task runs for more than a few seconds and you want to see its
  trajectory in real time.
* Multiple cooperating agents (Reviewer, TestRunner, GitHub-poster, etc.)
  contribute to one logical task.
* You need a customer-visible record of what an agent did: events, model calls,
  Sailbox execs, terminal status, and other evidence for debugging or auditing.

Do not use a Voyage for one-shot API calls. A single
`sail.inference.responses.create()` outside a Voyage works fine and shows up
in your inference dashboard without extra instrumentation.

## Mental model

```python theme={null}
with sail.voyage.run(name="research-agent", version=1):
    researcher_step()
```

* A **Voyage** is one task.
* An **agent** is a named participant within the task (e.g., "Reviewer").
* A **span** is a logical step the agent performs (e.g., "draft-response").
* An **event** is a timestamped marker within a span.
* A **model call** is automatically recorded when you call Sail inference
  inside a Voyage. If no span is active, the SDK creates an auto-span.
* A **Sailbox exec** is automatically recorded when you call `sb.exec()`
  inside a Voyage. If no span is active, the SDK creates an auto-span.

## Minimal example

```python theme={null}
import sail

@sail.agent("Researcher")
@sail.span("draft answer")
def draft_answer(topic: str):
    sail.voyage.event("research.started", payload={"topic": topic})
    response = sail.inference.responses.create(
        model="zai-org/GLM-5.2-FP8",
        input=f"Give one concise research note about: {topic}",
        background=False,
    )
    sail.voyage.event("research.finished", payload={"response_id": response["id"]})


with sail.voyage.run(name="research-demo", version=1):
    draft_answer("long-term health benefits of running")

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

Run this, then open the printed URL. You should see one Voyage with one
`Researcher` agent, one explicit span, two events, one attributed model call,
and terminal status `voyage completed`.

## What gets attributed automatically

When you call Sail inference inside a Voyage, the SDK attaches active Voyage,
agent, and span context so the model call appears in the dashboard. Decorators
are the most direct way to attribute function-shaped work:

```python theme={null}
@sail.agent("Reviewer")
@sail.span("draft")
def draft_review():
    return sail.inference.responses.create(
        model="zai-org/GLM-5.2-FP8",
        input="Summarize this diff: ...",
        background=False,
        timeout=120,
    )
```

When you call `sb.exec()` inside a Voyage, the SDK also carries the active
Voyage, agent, and span context into the Sailbox command. `sb.exec(...)` returns
a request handle. Call `.wait()` for foreground commands so your program
observes completion, return code, stdout/stderr tails, and the attributed exec
row:

```python theme={null}
@sail.agent("TestRunner")
@sail.span("unit-tests")
def run_tests():
    req = sb.exec("pytest -q", timeout=600)
    req.wait()
```

You do not need to pass IDs by hand. If no span is active, Sail inference and
Sailbox execs still get a timed auto-span named from the calling code when
possible. Auto-spans do not invent agents, so declare an agent when the
dashboard should show ownership.

## Explicit vs auto spans

Use an explicit span when the step name matters to humans:

```python theme={null}
@sail.agent("Researcher")
@sail.span("score evidence")
def score_evidence():
    sail.inference.responses.create(model="zai-org/GLM-5.2-FP8", input="...")
```

If you leave the span out, Sail still captures SDK-owned work. The model call
below is recorded under the `Researcher` agent and wrapped in a timed auto-span:

```python theme={null}
@sail.agent("Researcher")
def score_evidence():
    sail.inference.responses.create(model="zai-org/GLM-5.2-FP8", input="...")
```

Auto-spans are useful when you are adding telemetry to an existing agent
harness. Add `@sail.span(...)` when you want a specific step name, payload, or
parent/child shape.

## Multiple agents in one Voyage

A real code-review agent has at least three distinct participants. A `GitHub`
agent clones the repository, a `TestRunner` runs the suite in a Sailbox, and a
`Reviewer` drafts the summary with inference. Declare each one with
`@sail.agent(...)`, and the dashboard shows three named agents under one
Voyage, each with its own spans and events. See the
[Voyages Patterns](./voyages-patterns) guide for the full multi-agent example.

## Terminal status

Every Voyage needs exactly one terminal event before the controller process
exits. `with sail.voyage.run(...)` handles it: clean exit emits
`voyage.completed`. An exception emits `voyage.failed` and re-raises.
Terminal status is first-terminal-wins. Events after the terminal are
best-effort delivery only.

```python theme={null}
with sail.voyage.run(name="task"):
    do_work()
```

Controllers whose create and terminal sites live in different places use
the `create()` primitive and call `voyage.complete()` / `voyage.fail()`
themselves.

## Stop recording and delete

Use `voyage.cancel()` or `sail.voyage.cancel()` to stop recording a running
Voyage:

```python theme={null}
voyage = sail.voyage.create(name="overnight-eval")
...
voyage.cancel()
```

Cancel marks the server-side Voyage `cancelled` and stops this SDK instance
from recording further events. The server does not reject late events from
other sources, and cancel does **not** terminate external or non-Sailbox agent
code. If you own that process, stop it separately.

You can delete a finished Voyage from its dashboard detail page; this removes
its history and content from the dashboard and API. Security audit records are
retained. There is no API or SDK delete yet.

## What to read next

* [Voyages Quickstart](./voyages-quickstart): copy-paste-ready 60-second
  example.
* [Voyages Patterns](./voyages-patterns): multi-agent and child-attach
  for subprocesses.
* [Sail skills package](https://github.com/sailresearchco/sail-skills):
  agent-ready playbooks for building, instrumenting, and debugging Voyage runs.
* [Building Agents](./agents): Sail's Responses API and tool calling.
* [Sailboxes](./sailboxes): the runtime substrate.
