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

# Outcomes

> Attach user-defined success signals to your agent runs so AgentVista can track what actually matters to your business.

An **outcome** is your definition of what a successful run looks like. AgentVista records the mechanics of every run automatically — tokens, latency, cost, errors. Outcomes let you layer in the business signal: did this run actually do what it was supposed to do?

## The two outcome fields

Every trace has two optional outcome fields:

| Field     | Type    | Description                                      |
| --------- | ------- | ------------------------------------------------ |
| `success` | boolean | Was this run successful by your definition?      |
| `outcome` | string  | An optional label describing the specific result |

These fields are intentionally open-ended. You decide what "success" means. For a customer support bot, success might mean the ticket was resolved without human escalation. For a lead qualifier, it might mean the lead was correctly categorized. For a code reviewer, it might mean the PR was approved without feedback.

`outcome` gives you a more granular label beyond the binary `success`/`failure` distinction. A run can be `success=False` with `outcome="escalated"` (the agent correctly recognized it couldn't handle this one) or `success=False` with `outcome="hallucinated"` (the agent produced an incorrect answer). Those two failure modes call for very different responses.

<Tip>
  Choose outcome labels that map to actions your team can take. "resolved", "escalated", "qualified", "unqualified", "approved", "flagged" — these labels should mean something specific to the people reading the dashboard.
</Tip>

## Setting outcomes

### Context manager

The most common pattern is to set the outcome at the end of a `with agentvista.run(...)` block:

```python theme={null}
import agentvista

agentvista.init(api_key="av_xxxxx")

def handle_support_ticket(ticket_id: str):
    with agentvista.run("support-bot") as r:
        response = process_ticket(ticket_id)

        if response.resolved_automatically:
            r.set_outcome(success=True, outcome="resolved")
        elif response.needs_human:
            r.set_outcome(success=False, outcome="escalated")
        else:
            r.set_outcome(success=False, outcome="unclear")
```

`r.set_outcome(success, outcome)` accepts `outcome` as an optional keyword argument. If you only care about the boolean signal, you can omit it:

```python theme={null}
r.set_outcome(success=True)
```

### Record (v1 API)

If you're using `agentvista.record()` for simple single-span tracing, pass `success` and `outcome` directly:

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

### Via the API

You can also update an outcome after the run has completed — useful when success is determined by a downstream process (for example, a human reviewing the agent's output hours later):

```
PATCH /api/v1/dashboard/traces/{trace_id}/outcome
Content-Type: application/json

{
  "success": true,
  "outcome": "approved"
}
```

This is handy for workflows where the ground truth arrives asynchronously, such as:

* A sales team confirming whether a qualified lead converted
* A support manager reviewing whether auto-resolved tickets stayed closed
* An automated test suite validating agent outputs offline

## What the dashboard shows you

When you set outcomes, the AgentVista dashboard unlocks a set of views that go beyond raw trace data:

**Success rate chart** — success rate over time for each agent. Drop after a prompt change? You'll see it immediately.

**Outcome breakdown** — a breakdown of how often each `outcome` label appears. If `"escalated"` is climbing while `"resolved"` is flat, something in your agent's logic has changed.

**Outcome-to-cost linking** — the dashboard surfaces the average cost per run for each outcome. This answers questions like: "Are we spending more on runs that end up failing anyway?" or "Our success rate improved — but did our cost per resolved ticket also go up?"

## Use case examples

<Tabs>
  <Tab title="Customer support bot">
    ```python theme={null}
    with agentvista.run("support-bot") as r:
        result = resolve_ticket(ticket)

        if result.status == "auto_resolved":
            r.set_outcome(success=True, outcome="resolved")
        elif result.status == "escalated_to_human":
            r.set_outcome(success=False, outcome="escalated")
        elif result.status == "csat_failed":
            r.set_outcome(success=False, outcome="unsatisfied")
    ```
  </Tab>

  <Tab title="Lead qualifier">
    ```python theme={null}
    with agentvista.run("lead-qualifier") as r:
        score = qualify(lead_data)

        if score.tier == "hot":
            r.set_outcome(success=True, outcome="qualified")
        elif score.tier == "nurture":
            r.set_outcome(success=True, outcome="nurture")
        else:
            r.set_outcome(success=False, outcome="unqualified")
    ```
  </Tab>

  <Tab title="Code reviewer">
    ```python theme={null}
    with agentvista.run("code-reviewer") as r:
        review = analyze_pr(diff)

        if review.decision == "approve":
            r.set_outcome(success=True, outcome="approved")
        elif review.decision == "changes_requested":
            r.set_outcome(success=True, outcome="flagged")
        else:
            r.set_outcome(success=False, outcome="inconclusive")
    ```
  </Tab>
</Tabs>

## Outcomes without the decorator

If you use `@agentvista.trace_agent` (the decorator pattern), you don't get a handle to call `set_outcome()` on. In that case, switch to the context manager pattern for any agent where outcomes matter:

```python theme={null}
# Decorator — no outcome support
@agentvista.trace_agent("lead-qualifier")
def qualify_lead(data):
    return run_pipeline(data)  # outcome fields will be blank

# Context manager — full outcome support
def qualify_lead(data):
    with agentvista.run("lead-qualifier") as r:
        result = run_pipeline(data)
        r.set_outcome(success=result.success, outcome=result.category)
        return result
```

<Note>
  Outcomes are optional on every run. Traces without `success` or `outcome` still appear in the dashboard — they just won't contribute to success rate charts or outcome breakdowns until those fields are populated.
</Note>
