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

> ## Agent Instructions
> Unmute compiles to exactly three targets. Pipecat and LiveKit are code targets: compile writes a Python project you run. SLNG is a hosted target: compile writes a deployment body and SLNG runs the agent, so it has no `unmute dev`. Those three are the only values `provider` accepts in `targets.yaml`. Deepgram and ElevenLabs appear in these docs as model vendors, which is not the same thing as a target, and `slng` is both.
> The Go structs in `internal/spec` and `internal/ir` are the schema truth. Check a field against them, or run `unmute validate`, rather than against what you remember.

# Checking what the agent did

> A transcript tells you what the caller heard. It does not tell you what the agent recorded, and the two disagree more often than you would expect.

Checking an agent means reading what the call actually did: which steps
finished, which tools ran, and which saved values each prompt received.

An agent can hold a good conversation and record nothing. It can also record
correctly and sound broken. The transcript only shows you one of those, so
reading it is not checking.

On this page:

* [Read the trace, not the transcript](#read-the-trace-not-the-transcript) - what a transcript hides
* [Check scoping by reading the prompt](#check-scoping-by-reading-the-prompt-that-was-sent) - verifying a negative
* [Read requests in time order](#read-requests-in-time-order) - when a value was saved
* [Count tool spans, not call rows](#count-tool-spans-not-call-rows) - what ran, not what was asked
* [Find the layer the defect lives in](#find-the-layer-the-defect-lives-in) - the smallest layer that shows it
* [Do not conclude from one call](#do-not-conclude-from-one-call) - three calls, or one
* [Read the call back yourself](#read-the-call-back-yourself) - not somebody's description

## Read the trace, not the transcript

A call that reads well can still have written nothing to declared state. The
case that shows why: an agent booked two appointments, and when the caller asked
for a recap it named both correctly. That looked like proof the state was right.
It was not. The agent could have read either an explicit saved-value
placeholder or the conversation, and from the transcript alone there is no way
to tell which.

What settles it is the rendered prompt. With tracing enabled, each model request
shows which saved values its authored placeholders rendered:

```text theme={null}
Review these appointments with the caller:
[{"scheduled_date":"2026-09-05","scheduled_time":"15:00", ...},
 {"scheduled_date":"2026-09-06","scheduled_time":"09:00", ...}]
```

Now you know. Two appointments, distinct, and nothing recorded against
complaints on a call where a complaint was discussed, which is a defect the
transcript hid completely.

## Check scoping by reading the prompt that was sent

The same technique is the only real check on context scoping and on `confirm:`.
Both are promises about what a given prompt does not contain, and the only place
to verify a negative is the prompt itself.

Read each complete model request and compare it. A candidate marked `confirm:`
should render only in the confirming task's prompt until that task saves
agreement. It should be absent from other prompt and router payloads.

## Read requests in time order

Do not collapse repeated model requests. A saved value may be absent before a
task finishes and present afterwards. Listing each request in order shows when
the value was saved and exactly which prompt received it through a placeholder.

## Count tool spans, not call rows

A trace shows both what the model asked for and what ran, and they are not the
same number. A model can emit the same tool call twice in one turn, and the
framework may execute it once.

Count the spans named after the tool. Two call rows and one tool span is one
execution. Two of each is two, and if both wrote something you have a duplicate
to explain.

The step's finish is the useful one. A step that never reaches its finish never
wrote to declared state, whatever else it did, so a missing finish span explains
an empty variable immediately.

## Find the layer the defect lives in

Reproduce a defect in the smallest layer that shows it. A provider rejecting a
schema is one HTTP request, so it needs no audio, no tunnel and no caller. A
prompt that reads badly needs a conversation. A carrier problem needs a real
phone.

Working in the wrong layer is what makes debugging slow. Half an hour of calls
to diagnose something a single request would have shown in seconds is a common
way to spend an afternoon.

## Do not conclude from one call

Two identical builds produce noticeably different calls. Timing, wording, and
which of several valid routes the model takes all vary run to run.

For anything about latency or about how often a behaviour happens, run three
calls before you believe a number. For a defect that is a hard failure, such as
a refused schema or a step that never runs, one call is enough, because the
mechanism is the evidence and not the frequency.

## Read the call back yourself

After somebody talks to the agent, read the call back rather than working from
what they tell you. What was said, which tools ran, which steps finished, and
where the time went are all in the trace, and a description of a call leaves out
the parts nobody heard.

<Tip>
  The two questions worth asking of every call: did every step that should have
  run reach its finish, and did each explicit placeholder render the saved value
  the caller was told. A gap in either one is a defect the conversation did not
  reveal.
</Tip>

## Where the mechanics live

<CardGroup cols={2}>
  <Card title="Talking to the agent locally" icon="microphone" href="/dev/overview">
    Running a package in the browser, and seeding a call source.
  </Card>

  <Card title="Tracing" icon="chart-line" href="/tracing/overview">
    Turning on tracing, and what each provider gives you.
  </Card>
</CardGroup>
