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

# Agents & Runs

> Learn how AgentVista organizes your observability data around named agents and individual runs.

AgentVista organizes all observability data around two core entities: **agents** and **runs**. An agent is the named entity you track; a run is one execution of that agent.

## What is an agent?

An agent is a named entity in AgentVista that groups all traces produced by a particular piece of logic. It might be a customer support bot, a lead qualification pipeline, a code review assistant, or any other automated workflow you want to observe independently.

Agents are **created automatically**. The first time you send a trace with a new `agent_name`, AgentVista registers that agent in your account. There is nothing to provision or configure in advance — just start sending data.

```python theme={null}
import agentvista

agentvista.init(api_key="av_xxxxx")

# The agent "lead-qualifier" is created on first run if it doesn't exist yet
@agentvista.trace_agent("lead-qualifier")
def qualify_lead(data):
    ...
```

Each agent is scoped to your account. Two accounts can both have an agent named `"support-bot"` without any conflict. Within your account, agent names are unique — sending traces with the same `agent_name` always groups them under the same agent.

<Info>
  The `agent_name` you pass to `@trace_agent` or `agentvista.run()` is the agent's display name in the dashboard. Choose a name that describes what the agent does, not how it's implemented.
</Info>

## What is a run?

A run is synonymous with a **trace** — one complete execution of your agent from start to finish. Every time your decorated function is called, or every time a `with agentvista.run(...)` block executes, AgentVista records a new run.

Each run captures:

* When it started and ended
* How long it took (`duration_ms`)
* Whether it succeeded (`success`)
* What the outcome was (`outcome`)
* Every span (LLM calls, tool calls, DB queries) inside it
* Total token usage and cost across all LLM spans

## Agent statistics

The dashboard computes the following statistics across all runs for each agent:

| Metric               | Description                                            |
| -------------------- | ------------------------------------------------------ |
| Total runs           | Count of all traces recorded for this agent            |
| Success rate         | Percentage of runs where `success = true`              |
| Average cost per run | Mean of `total_cost_usd` across completed runs         |
| Total cost           | Sum of `total_cost_usd` across all runs                |
| p95 latency          | 95th percentile of `duration_ms` across completed runs |

These statistics update as new runs arrive. You can filter by time range to see how your agent is performing over a specific period.

## Creating runs

You have two ways to create a run, depending on how much control you need.

### Decorator

Use `@agentvista.trace_agent` when you want zero-friction instrumentation. Wrap your agent function and every call becomes a run automatically.

```python theme={null}
import agentvista

agentvista.init(api_key="av_xxxxx")

@agentvista.trace_agent("support-bot")
def handle_ticket(ticket_id: str) -> dict:
    # Every call to handle_ticket() is recorded as a run under "support-bot"
    response = process_ticket(ticket_id)
    return response
```

You can also use `@agentvista.trace_agent` without a name — the agent name defaults to the function name:

```python theme={null}
@agentvista.trace_agent
def support_bot(ticket_id: str) -> dict:
    # Agent name becomes "support_bot"
    ...
```

The decorator records the run as `failed` automatically if an unhandled exception propagates out of the function.

### Context manager

Use `with agentvista.run(...)` when you need to set an outcome or control the run's lifecycle explicitly:

```python theme={null}
import agentvista

agentvista.init(api_key="av_xxxxx")

def qualify_lead(lead_data: dict) -> str:
    with agentvista.run("lead-qualifier") as r:
        result = run_qualification_pipeline(lead_data)

        if result.score > 0.8:
            r.set_outcome(success=True, outcome="qualified")
        else:
            r.set_outcome(success=False, outcome="unqualified")

        return result.recommendation
```

`r.set_outcome()` attaches `success` and `outcome` to the trace when the context manager exits. If you don't call `set_outcome()`, those fields are left blank on the trace.

### Record (v1 API)

For simple cases where you don't need span-level detail, `agentvista.record()` creates a minimal single-span trace in one call:

```python theme={null}
agentvista.record(
    agent="lead-qualifier",
    success=True,
    outcome="qualified",
    cost=0.043,
    duration_ms=1200,
)
```

## Multiple agents

You can track as many agents as you need — there is no limit on the number of agents per account. Each agent appears as a separate entry in the dashboard and is tracked independently.

```python theme={null}
@agentvista.trace_agent("support-bot")
def handle_support(ticket): ...

@agentvista.trace_agent("lead-qualifier")
def qualify_lead(lead): ...

@agentvista.trace_agent("code-reviewer")
def review_pr(diff): ...
```

## Agent comparison

The dashboard lets you place two agents side-by-side to compare:

* **Success rate** — which agent is more reliable?
* **Average cost per run** — which is more efficient?
* **p95 latency** — which is faster?

This is useful when you're evaluating a new prompt version, a different model, or a redesigned workflow against your current production agent.

<Tip>
  Use distinct, descriptive agent names when running A/B experiments — for example `"support-bot-v1"` and `"support-bot-v2"`. This keeps the comparison clean and lets you retire the old agent once you've validated the new one.
</Tip>
