# Mute messages

Keep internal or unrelated LLM calls out of the captured conversation, so Brizz shows exactly what your users saw.

Brizz auto-captures your agent's LLM calls and renders them as the conversation your user had. But not every call belongs in that conversation — agents make **internal or unrelated** calls the user never sees: session summarization, title generation, classification or routing, guardrail checks. Captured as-is, those show up as extra turns and drift from what the user actually experienced.

Muting tells Brizz to leave a call's content out of the conversation, so what you see matches what the user saw. The session, its spans, latency, and token/cost are still recorded — only the **content** of the muted call is dropped: the user prompt, the assistant reply, and the tool calls, each of which you can control separately. It also works for sensitive content you'd rather not store, but its main job is keeping the captured conversation faithful to the real one.

:::info
**Telemetry stays on.** Muting only removes conversation content items — the session and its spans are still recorded, so session counts, latency, and cost are unaffected. Errors, custom events, and system messages are never dropped.
:::

## Mute a block

Wrap the call you want left out of the conversation. Every span created inside the block is marked, and the backend drops the matching conversation items. By default everything is dropped — the user prompt, the assistant reply, and any tool calls.

:::tabs
:::tab[Python]
```python
import brizz

# A session-summarization call the user never sees — keep it out of the conversation.
with brizz.mute():
    summary = agent.run("Summarize this conversation for internal logging.")
```
:::tab[Node.js]
```typescript
import { callWithMute } from '@brizz/sdk';

// A session-summarization call the user never sees — keep it out of the conversation.
await callWithMute({}, () => agent.run('Summarize this conversation for internal logging.'));
```
:::

## Mute one side

By default everything is muted. Disable `input` to keep the user prompt visible, or `output` to keep the assistant reply.

:::tabs
:::tab[Python]
```python
import brizz

# Mute just the input — keep the assistant reply, drop the prompt.
with brizz.mute(output=False):
    reply = agent.run("…a long internal prompt the user never wrote…")

# Mute just the output — keep the user prompt, drop the reply.
with brizz.mute(input=False):
    reply = agent.run("the question the user asked")
```
:::tab[Node.js]
```typescript
import { callWithMute } from '@brizz/sdk';

// Mute just the input — keep the assistant reply, drop the prompt.
await callWithMute({ output: false }, () => agent.run('…a long internal prompt the user never wrote…'));

// Mute just the output — keep the user prompt, drop the reply.
await callWithMute({ input: false }, () => agent.run('the question the user asked'));
```
:::

## Mute tool calls separately

Tool arguments and results often carry the sensitive payload — CRM records, file contents, internal API responses — while the user and assistant turns are exactly what you want analytics on. `tools` controls that side on its own. It follows `output` unless you set it.

:::tabs
:::tab[Python]
```python
import brizz

# Keep the conversation, drop every tool call and result.
with brizz.mute(input=False, output=False, tools=True):
    reply = agent.run("Look up this customer's account.")

# The inverse — hide the conversation, keep tool telemetry for debugging.
with brizz.mute(tools=False):
    reply = agent.run("…a prompt you'd rather not store…")
```
:::tab[Node.js]
```typescript
import { callWithMute } from '@brizz/sdk';

// Keep the conversation, drop every tool call and result.
await callWithMute({ input: false, output: false, tools: true }, () =>
  agent.run("Look up this customer's account."),
);

// The inverse — hide the conversation, keep tool telemetry for debugging.
await callWithMute({ tools: false }, () => agent.run('…a prompt you’d rather not store…'));
```
:::

:::warning
**Tool inputs can echo a muted prompt.** Keeping tool calls while muting `input` (for example `mute(tools=False)`) drops the user's turn but keeps tool arguments — and agents frequently pass the user's wording straight through to a tool. If you are muting for privacy rather than for a faithful conversation, mute the tools too.
:::

:::info
**One turn goes with `output` regardless.** When a single assistant turn both replies and calls a tool, Brizz treats it as assistant text, so muting `output` drops it even with `tools` kept. You'll notice it viewing a session with **Show tools** on — that turn's tool call won't be there. Turns where the tool call arrives on its own are unaffected.
:::

## Reuse and async

In Python, use `amute` for `async with` blocks. In Node.js, pre-wrap a function with `withMute` to reuse the same muting (and bind `this`).

:::tabs
:::tab[Python]
```python
import brizz

async with brizz.amute():
    summary = await agent.arun("Summarize this conversation for internal logging.")
```
:::tab[Node.js]
```typescript
import { withMute } from '@brizz/sdk';

const muteTitle = withMute({}, agent.run, agent);
await muteTitle('Generate a short title for this conversation.');
```
:::

## What gets dropped

- **`input`** — the user side: user prompt turns.
- **`output`** — the assistant side: assistant reply text.
- **`tools`** — tool calls and their results. Follows `output` unless you set it. One exception: a combined assistant-message-with-tool-call turn counts as assistant text, so muting `output` drops it even with `tools` kept. If you view a session with **Show tools** on, that turn is the one you won't see.
- Everything else — errors, custom events, system messages — is always kept.
- The session, spans, latency, and token/cost metrics are unaffected; only conversation content items are removed.

Muting applies to the spans created **inside** the block, so place the call around the LLM or agent work whose content you want hidden. It also applies at ingest time only — muting a block affects data sent from that point on, not conversations already captured.

## See also

- [PII & privacy](/docs/instrument/pii-and-privacy.md) — mask or redact fields when you want to keep the turn but hide parts of it.
- [Sessions](/docs/instrument/sessions.md) — the session a muted block belongs to is still captured.
