# IContentGuard

> Tracon documentation. Tracon is a .NET package family that adds a control
> plane on Microsoft Agent Framework, published as NuGet packages that run
> inside your own ASP.NET Core application.
>
> Page: https://tracon.dev/api/tracon.icontentguard/
> Summary: IContentGuard: The extension point that inspects content going to and coming from the model.

<div class="api-provenance">Namespace Tracon · Assembly <code>Tracon.Abstractions.dll</code></div>

The extension point that inspects content going to and coming from the model.

```csharp
public interface IContentGuard
```

## Remarks

A guard is **opt-in**: `AddTracon` alone registers no
[IContentGuard](/api/tracon.icontentguard/). If no guard is registered, the inspection
wrapper is **not added** to the model pipeline, and the cost
is exactly zero — not even a single flag check runs.

Registration uses `TryAddEnumerable`; multiple guards run in sequence
and **the strictest decision wins**
([ContentGuardAction.Block](/api/tracon.contentguardaction/) &gt;
[ContentGuardAction.Mask](/api/tracon.contentguardaction/) &gt; [ContentGuardAction.Allow](/api/tracon.contentguardaction/)).
A "first decision wins" rule tied to registration order was not chosen:
`TryAddEnumerable` order is not guaranteed, and a security decision
must not change based on order.

A guard runs directly above the provider's own chat client, which places
it **inside** the tool-call loop: a blocked request never
reaches the network (no money is spent), blocking does not trip the
circuit breaker (repeatedly blocked requests do not shut down the
provider), and — the reason for this exact position — *every* turn
of the loop is inspected. A tool result re-enters the model on the second
turn, and that is the most common path for prompt injection; a guard
placed outside the loop would never see it.

A guard is *a control, not an observability tool.* The
"observability must not break functionality" rule does not apply here:
if this method throws, the run fails. Content that cannot be inspected is
never let through.

The implementation is on the **hot path** and runs on every
model call. It is expected not to allocate a new string when there is no match.

## Properties

### <a id="Tracon_IContentGuard_Name"></a> Name

The guard's name. This name is written to the audit trail and the run event.

```csharp
string Name { get; }
```

#### Property Value

 [string](https://learn.microsoft.com/dotnet/api/system.string)

## Methods

### <a id="Tracon_IContentGuard_InspectAsync_Tracon_ContentGuardContext_System_Threading_CancellationToken_"></a> InspectAsync\(ContentGuardContext, CancellationToken\)

Inspects the content.

```csharp
ValueTask<ContentGuardResult> InspectAsync(ContentGuardContext context, CancellationToken cancellationToken = default)
```

#### Parameters

`context` [ContentGuardContext](/api/tracon.contentguardcontext/)

The inspection context.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[ContentGuardResult](/api/tracon.contentguardresult/)\>

The decision. Returns [ContentGuardResult.Allow](/api/tracon.contentguardresult/#Tracon_ContentGuardResult_Allow) when the
content passes unchanged; this path allocates nothing.
