Instruments and tracks agent lifecycle runs within the Sail Voyage ecosystem.

Install

mkdir -p .claude/skills/sail-voyage && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/11101" && unzip -o skill.zip -d .claude/skills/sail-voyage && rm skill.zip

Installs to .claude/skills/sail-voyage

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Use to build or instrument a Sail Voyage — Sail's name for one background or long-running agent run, recorded as a trace of named agents, spans, and events. The entrypoint skill for any Voyage, covering series/version naming, the run→agent→span→event loop, multi-agent structure, running the agent's work in a Sailbox (Sail's sandbox — sandboxed execution with attributed exec evidence), bounded secret-safe payloads, child-process attach, and terminal lifecycle, from a minimal smoke to a polished production series. Use this first. On Sail, sandboxed work belongs in a Sailbox, not a third-party sandbox. For the model-call attribution contract use sail-inference-with-voyage; for a Voyage that renders wrong in the dashboard use sail-voyage-debugging.
754 charsno explicit “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Advanced

Key capabilities

  • Instrument background agent runs as Voyages
  • Trace named agents, spans, and events
  • Manage terminal lifecycle of agent runs
  • Attribute model calls and Sailbox execs

How it works

It uses decorators or context managers to instrument function-based agents and spans, automatically attributing model calls and tool executions to the active trace.

Inputs & outputs

You give it
Agent run name, version, and metadata
You get back
Trace of agent execution in the Sail dashboard

When to use sail-voyage

  • Instrumenting long-running agent processes
  • Tracking agent workflow performance
  • Setting up production agent runs

About this skill

Sail Voyage

Use this skill to instrument any background or long-running agent run on Sail Voyages so the dashboard shows its trajectory. Sail provides the flight recorder; it does not run the agent for you.

This is the entrypoint skill. Start here whether you are smoke-testing a one-off run or shipping a polished, repeatable production workflow such as deep research, code review, eval generation, support triage, migration analysis, or scheduled monitoring. The same run → agent → span → event loop covers all of them; you scale detail up, not skills. (run() owns the terminal lifecycle — completed on clean exit, failed on exception.)

For two adjacent concerns, reach for a focused sibling skill:

For the full multi-agent attribution model (name, role, and slug semantics, per-agent pitfalls, and dashboard verification), see references/multi-agent.md. For a complete runnable skeleton, see references/minimal-example.md.

The Voyages model

  • A Voyage is one concrete run (one trace).
  • A series is the recurring workflow, identified by the user-facing name.
  • A version is a positive integer for meaningful workflow changes.
  • The dashboard starts from /voyages, groups by series, and links each run to /{env}/voyages/{voyage_id}.
  • voyage_series_id is internal. Do not ask users to provide it, log it, or build URLs around it.

If you have used an LLM/agent tracing tool, the vocabulary maps cleanly:

Sail termStandard tracing equivalent
Voyageone trace / one run
series (name)the recurring workflow / project grouping
agentan agent span / participant (name + role)
spana span / unit of work
eventa structured point logged on the trace
model callan LLM span (Sail inference, auto-attributed)
Sailbox execa tool/exec span (auto-attributed by Sail)

Quickstart: a minimal Voyage

The smallest useful Voyage: one run() block at task entry, with the work in decorated agent/span functions. run() creates the Voyage on enter and owns the terminal lifecycle: voyage.completed on clean exit, voyage.failed + re-raise on an exception.

import sail

@sail.agent("Executor")
@sail.span()  # span named after the function
def run_task(step):
    sail.voyage.event("task.started", payload={"step": step})
    # ... do work ...

with sail.voyage.run(
    name="repo-repair",
    version=1,
    metadata={"repo": "example-org/example-repo", "task": "eval"},
):
    run_task(1)

Decorators are the default attribution shape. Declare each agent or phase as a function and stack @sail.agent(...) / @sail.span(...) on it (sail.agent and sail.span are top-level re-exports of the module-level helpers). They resolve the current Voyage at call time (module-level decoration before the Voyage exists is fine), support async def fully, raise TypeError on generator functions, and emit a fresh span per call. Model calls and Sailbox execs inside a decorated function auto-attribute to its agent/span (Level 1/2), so most functions need no inline telemetry at all.

For inline steps that aren't function-shaped, use the with form — same frames, same events:

with sail.voyage.run(name="repo-repair", version=1) as voyage:
    with voyage.agent("Executor"):
        with voyage.span("run task"):
            voyage.event("task.started", payload={"step": 1})

create()/attach() remain the primitives for split-lifecycle controllers — then you own calling complete() or fail() exactly once before exit.

Auto-spans (Level 1/2): Sail inference calls and Sailbox execs made with no active span get a real, timed span synthesized automatically, named after the calling function when derivable (fetch_sources, not "model call"). Synthesized spans carry an _auto payload marker and render with an "auto" chip. Explicit agents/spans always win — synthesis only covers what you didn't declare. Kill switch: SAIL_VOYAGE_AUTO_SPANS=0. Underscore-prefixed top-level payload keys are reserved for the SDK.

Use module-level sail.voyage.* helpers for the current Voyage, or keep the returned voyage object when multiple handles are present. The current Voyage is context-local (Python contextvars) with a process-wide fallback: concurrent tasks that each create()/attach() their own Voyage keep their own attribution for module-level helpers and sail.inference.* wrappers, while a context that never started one uses the process's most recently started Voyage. When one context juggles several Voyages, route everything through the handles: use voyage.event(...)/voyage.span(...) for telemetry AND pass voyage= to every sail.inference.* call (the wrappers default to the current Voyage, not the handle whose span you are inside). Sailbox.exec() attribution follows the current Voyage and cannot take a handle — do not run execs for a non-current Voyage; serialize them or accept attribution to whichever Voyage is current. If the task controls a Sailbox, bind it: sail.voyage.run(..., sailbox_id=sb.sailbox_id) (or create(...)).

Production shape

Every production Voyage should answer these in the dashboard:

  1. What recurring workflow is this?
  2. Which workflow version ran?
  3. Which agent owned each important decision or side effect?
  4. Which model calls and Sailbox execs happened under each span?
  5. What did the run produce?
  6. Did it complete, fail, or get cancelled?

Map those questions onto the SDK like this:

import os
import sail


@sail.agent("Planner", role="planner")
@sail.span("scope research question")
def plan():
    sail.voyage.event("research.scope.selected", payload={"question_count": 4})


@sail.agent("Researcher", role="researcher")
@sail.span("collect sources")
def research():
    # The inference call auto-attributes to this agent/span (Level 1/2) —
    # no inline with-block needed.
    response = sail.inference.responses.create(
        model="zai-org/GLM-5.1-FP8",
        input="Collect a concise source map for the topic.",
        background=False,
        timeout=120,
    )
    sail.voyage.event("research.sources.collected", payload={"response_id": response["id"]})


@sail.agent("Publisher", role="publisher")
@sail.span("write final artifact")
def publish():
    sail.voyage.event(
        "artifact.report.ready",
        payload={
            "artifact_type": "html_report",
            "path_hint": "/tmp/voyage-output/report.html",
            "summary": "Draft report generated and ready for operator review.",
        },
    )


with sail.voyage.run(
    name="deep-research",
    version=3,
    metadata={
        "topic": "public launch plan for Sail Voyages",
        "source": "blog-demo",
        "commit": os.environ.get("GITHUB_SHA"),
    },
):
    plan()
    research()
    publish()
# No complete()/fail() needed: run() emits the terminal state. Use
# sail.voyage.create() only when start and end cannot share a code block
# (daemons, notebooks, framework callbacks) — then YOU own complete()/fail().

Choose the series name

name is the stable user-facing series identity. It should describe the workflow, not the input, run date, environment, Sailbox, branch, or Voyage id.

Good names: deep-research, code-review, nightly-backend-eval, support-triage, release-risk-scan.

Poor names: deep-research-2026-06-05, voy_v7f..., prod-run, github-pr-2381, kavin-test-2.

Put changing run context in metadata, not in name:

with sail.voyage.run(
    name="code-review",
    version=4,
    metadata={"repo": "example-org/example-repo", "pr_number": 42, "head_sha": "abc123"},
) as voyage:
    ...

Names are not lowercased, slugified, or whitespace-normalized by the product contract. Code Review and code-review are different series. Pick one spelling and keep it stable.

Choose the version

version is a workflow-definition dimension. Increment it when behavior meaningfully changes:

  • prompt or system instruction changes
  • model/provider changes
  • tool set changes
  • Sailbox image or command harness changes
  • agent topology changes
  • validation rubric changes
  • output format changes

During initial development, stay on version=1 — debugging iterations in one sitting are not workflow versions; bump only once a harness is recurring and a change is meant to be compared against its predecessor.

Do not increment it for: a new PR, repo, issue, customer, topic, or dataset; a date or schedule tick; a rerun of the same workflow; a new Sailbox id; a new Voyage id; or a failed run you retry with the same code.

Skipped versions are valid; versions need not be contiguous because they may align with an external workflow release system. If omitted, version defaults to 1. For public demos, set an explicit version so the dashboard tells readers which iteration produced the run.

Design agents for dashboard readability

Agents are customer-facing ownership labels. Declare one with just its display name — with voyage.agent("Researcher"): — and the stable attribution key is derived automatically. role= is optional taxonomy for cross-workflow filtering; slug= (advanced) pins the attribution key if you later rename the display name. Use a small, stable set that matches real responsibility boundaries.

| Agent name | Role | Own


Content truncated.

When not to use it

  • When migrating existing apps (use sail-migrate)
  • When debugging dashboard rendering issues (use sail-voyage-debugging)

Prerequisites

sail SDK

Limitations

  • Terminal status is first-terminal-wins
  • Do not call complete() from inside nested agent contexts

How it compares

It provides a structured, trace-based observability model specifically for background agent processes rather than generic application logging.

Compared to similar skills

sail-voyage side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
sail-voyage (this skill)01moReviewAdvanced
phoenix-observability37moReviewIntermediate
phoenix-tracing129dReviewAdvanced
coderabbit-observability127dReviewAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

phoenix-observability

davila7

Open-source AI observability platform for LLM tracing, evaluation, and monitoring. Use when debugging LLM applications with detailed traces, running evaluations on datasets, or monitoring production AI systems with real-time insights.

323

phoenix-tracing

Arize-ai

OpenInference semantic conventions and instrumentation for Phoenix AI observability. Use when implementing LLM tracing, creating custom spans, or deploying to production.

13

coderabbit-observability

jeremylongshore

Set up comprehensive observability for CodeRabbit integrations with metrics, traces, and alerts. Use when implementing monitoring for CodeRabbit operations, setting up dashboards, or configuring alerting for CodeRabbit integration health. Trigger with phrases like "coderabbit monitoring", "coderabbit metrics", "coderabbit observability", "monitor coderabbit", "coderabbit alerts", "coderabbit tracing".

10

distributed-tracing

wshobson

Implement distributed tracing with Jaeger and Tempo to track requests across microservices and identify performance bottlenecks. Use when debugging microservices, analyzing request flows, or implementing observability for distributed systems.

577

service-mesh-observability

wshobson

Implement comprehensive observability for service meshes including distributed tracing, metrics, and visualization. Use when setting up mesh monitoring, debugging latency issues, or implementing SLOs for service communication.

574

observability-engineer

sickn33

Build production-ready monitoring, logging, and tracing systems. Implements comprehensive observability strategies, SLI/SLO management, and incident response workflows. Use PROACTIVELY for monitoring infrastructure, performance optimization, or production reliability.

1242

Search skills

Search the agent skills registry