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

# Traces & Spans

> Understand how AgentVista models a complete agent run as a trace and every individual step within it as a span.

A **trace** represents one complete execution of your agent or request flow. A **span** is a single step inside that trace. Together, they give you an end-to-end picture of what happened, how long each step took, and where things went wrong.

## What is a trace?

Every time your agent runs, AgentVista records it as a trace. A trace captures the top-level facts about that execution:

| Field            | Type     | Description                                                |
| ---------------- | -------- | ---------------------------------------------------------- |
| `trace_id`       | UUID     | Unique identifier for this execution, generated by the SDK |
| `agent_name`     | string   | The agent that produced this trace                         |
| `status`         | string   | `running`, `completed`, `failed`, or `timed_out`           |
| `started_at`     | datetime | When the run began                                         |
| `ended_at`       | datetime | When the run finished                                      |
| `duration_ms`    | integer  | Total wall-clock time in milliseconds                      |
| `success`        | boolean  | Optional user-defined success signal                       |
| `outcome`        | string   | Optional outcome label (e.g. `"qualified"`, `"resolved"`)  |
| `total_tokens`   | integer  | Sum of tokens across all LLM spans in this trace           |
| `total_cost_usd` | decimal  | Sum of LLM costs across all spans                          |

<Note>
  `success` and `outcome` are not set automatically — you define what success means for your agent. See [Outcomes](/concepts/outcomes) for how to attach these signals.
</Note>

## What is a span?

A span represents one step within a trace — an LLM call, a tool invocation, a database query, or any other unit of work. Spans form a tree: every span (except the root) has a `parent_span_id` pointing to the span that created it.

| Field            | Type     | Description                                       |
| ---------------- | -------- | ------------------------------------------------- |
| `span_id`        | UUID     | Unique identifier for this span                   |
| `trace_id`       | UUID     | The trace this span belongs to                    |
| `parent_span_id` | UUID     | The parent span, or `null` for the root span      |
| `type`           | string   | The kind of work this span represents (see below) |
| `name`           | string   | A human-readable label you assign                 |
| `status`         | string   | `running`, `completed`, `failed`, or `timed_out`  |
| `started_at`     | datetime | When this step began                              |
| `ended_at`       | datetime | When this step finished                           |
| `duration_ms`    | integer  | Time spent in this step                           |

LLM spans carry additional fields:

| Field           | Type    | Description                                        |
| --------------- | ------- | -------------------------------------------------- |
| `model`         | string  | The model used (e.g. `"claude-sonnet-4-20250514"`) |
| `input_tokens`  | integer | Tokens in the prompt                               |
| `output_tokens` | integer | Tokens in the completion                           |
| `total_tokens`  | integer | Sum of input and output                            |
| `cost_usd`      | decimal | Cost for this call                                 |

All span types can carry `input_data`, `output_data`, `error_message`, and `metadata` as JSON payloads.

## Span types

AgentVista recognizes six span types. Each type tells the dashboard how to display the span and which fields are relevant.

<CardGroup cols={2}>
  <Card title="agent" icon="robot">
    The root span of a trace. Created automatically when you use `@trace_agent` or `with agentvista.run(...)`. Represents the full lifetime of your agent's execution.
  </Card>

  <Card title="llm" icon="microchip">
    An individual LLM call. Captures the model, token counts, cost, and latency for each completion request.
  </Card>

  <Card title="tool" icon="wrench">
    A tool invocation — any external function, API call, or service your agent calls as part of its reasoning. Use this to track web searches, code execution, database lookups triggered by the agent, and so on.
  </Card>

  <Card title="http" icon="globe">
    An outbound HTTP request to an external service. Useful for tracking calls to third-party APIs, webhooks, or downstream microservices.
  </Card>

  <Card title="db" icon="database">
    A database query or write operation. Helps you see whether slow agent runs are caused by the model or by database latency.
  </Card>

  <Card title="custom" icon="sliders">
    Any step that doesn't fit the above categories. Use `custom` spans for arbitrary business logic, caching layers, queue operations, or anything else you want to time and observe.
  </Card>
</CardGroup>

## How spans form a tree

Spans are linked by `parent_span_id`. The root span (type `agent`) has no parent. Every span created inside the root becomes its child, and so on recursively.

```
trace_id: a1b2c3d4
│
└── [agent] "lead-qualifier"          parent_span_id: null
    │
    ├── [llm] "classify-intent"       parent_span_id: <agent span_id>
    │
    ├── [tool] "search-crm"           parent_span_id: <agent span_id>
    │   │
    │   └── [db] "contacts-lookup"    parent_span_id: <tool span_id>
    │
    └── [llm] "generate-response"     parent_span_id: <agent span_id>
```

The AgentVista dashboard renders this tree as a **waterfall timeline** — each span appears as a horizontal bar positioned by its `started_at` time, indented by its depth in the tree. You can see at a glance which steps ran in parallel, which were sequential, and where time was spent.

## Unified traces

A single trace can contain both AI spans (`agent`, `llm`, `tool`) and infrastructure spans (`http`, `db`, `custom`) — this is AgentVista's core differentiator. When your agent makes a tool call that triggers a database query, those spans appear in the same waterfall, so you can see whether a slow run was caused by the model, a downstream API, or the database.

```
[agent] "support-bot"                        0ms ─────────────────── 2400ms
  [llm] "extract-intent"                     10ms ──── 340ms
  [tool] "fetch-ticket"                             400ms ─────── 900ms
    [http] "GET /api/tickets/8821"                  400ms ─── 700ms
    [db] "SELECT * FROM tickets WHERE id=..."               700ms ── 880ms
  [llm] "generate-reply"                                        920ms ──────── 2350ms
```

## Distributed tracing across services

If your agent calls downstream services that are also instrumented, you can stitch their spans into the same trace using W3C `traceparent` headers. The upstream service injects the header; the downstream service reads it and continues the same `trace_id`.

```python theme={null}
import agentvista

# Upstream service: inject the traceparent into outgoing headers
headers = {}
agentvista.inject_traceparent(headers)
response = requests.get("https://my-service.example.com/run", headers=headers)

# Downstream service: continue the same trace
incoming_tp = request.headers.get("traceparent")
with agentvista.run("downstream-service", incoming_traceparent=incoming_tp) as r:
    # Spans created here share the same trace_id as the upstream call
    ...
```

## Creating spans in your code

Use `agentvista.span(name, span_type)` as a context manager inside any active trace. The SDK automatically links spans to the correct parent and records timing.

<CodeGroup>
  ```python Decorator pattern theme={null}
  import agentvista

  agentvista.init(api_key="av_xxxxx")

  @agentvista.trace_agent("lead-qualifier")
  def qualify_lead(lead_data):
      with agentvista.span("classify-intent", span_type="llm"):
          intent = call_llm(lead_data["message"])

      with agentvista.span("search-crm", span_type="tool"):
          with agentvista.span("contacts-lookup", span_type="db"):
              contact = db.query("SELECT * FROM contacts WHERE email = ?", lead_data["email"])

      with agentvista.span("generate-response", span_type="llm"):
          return call_llm(f"Respond to this lead: {intent}")
  ```

  ```python Context manager pattern theme={null}
  import agentvista

  agentvista.init(api_key="av_xxxxx")

  with agentvista.run("lead-qualifier") as r:
      with agentvista.span("classify-intent", span_type="llm"):
          intent = call_llm(lead_data["message"])

      with agentvista.span("search-crm", span_type="tool"):
          contact = search_crm(lead_data["email"])

      r.set_outcome(success=True, outcome="qualified")
  ```
</CodeGroup>

<Tip>
  `agentvista.span()` is a no-op when called outside an active trace. You can safely add spans to library code without worrying about whether a trace is running.
</Tip>

If an exception is raised inside a `span()` block, the span is automatically marked `failed` and the exception message is recorded in `error_message`. The exception still propagates normally — AgentVista never suppresses errors.
