# TraconBuilderExtensions

> 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.traconbuilderextensions/
> Summary: TraconBuilderExtensions: The registration methods of the Tracon configuration chain that AddTracon returns.

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

The registration methods of the Tracon configuration chain that
`AddTracon` returns.

```csharp
public static class TraconBuilderExtensions
```

<dl class="api-relations"><dt>Inheritance</dt><dd><a href="https://learn.microsoft.com/dotnet/api/system.object">object</a> ← <a href="/api/tracon.traconbuilderextensions/">TraconBuilderExtensions</a></dd><dt>Inherited Members</dt><dd><a href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object?, object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object?, object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a></dd></dl>

## Remarks

Every registration capability is an extension method on
[ITraconBuilder](/api/tracon.itraconbuilder/), so a new capability never changes the
interface. Provider and storage packages follow the same shape with their
own extensions (`UsePostgreSql`, `UseOpenAI`, and so on).

A chain only has to supply [ITraconBuilder.Services](/api/tracon.itraconbuilder/#Tracon_ITraconBuilder_Services): these
methods write to that collection and nothing else.

## Methods

### <a id="Tracon_TraconBuilderExtensions_AddAgent_Tracon_ITraconBuilder_Tracon_AgentDefinition_"></a> AddAgent\(ITraconBuilder, AgentDefinition\)

Defines a declarative agent in code. The definition passes through the
Tracon compiler; model and tool validation is applied.

```csharp
public static ITraconBuilder AddAgent(this ITraconBuilder builder, AgentDefinition definition)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`definition` [AgentDefinition](/api/tracon.agentdefinition/)

The agent definition.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

```csharp
builder.AddTracon()
       .AddAgent(new AgentDefinition
       {
           Name = "support",
           Instructions = "Answer support questions from the order data.",
           Model = new ModelBinding { Provider = "openai", Model = "gpt-4o-mini" },
           ToolNames = ["get_order_status"],
       });
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddAgent_Tracon_ITraconBuilder_System_String_System_Func_System_IServiceProvider_Microsoft_Agents_AI_AIAgent__System_String_"></a> AddAgent\(ITraconBuilder, string, Func<IServiceProvider, AIAgent\>, string?\)

Defines a factory-based agent in code. How the agent is built is
entirely up to the caller.

```csharp
public static ITraconBuilder AddAgent(this ITraconBuilder builder, string name, Func<IServiceProvider, AIAgent> factory, string? description = null)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`name` [string](https://learn.microsoft.com/dotnet/api/system.string)

The agent name.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[IServiceProvider](https://learn.microsoft.com/dotnet/api/system.iserviceprovider), AIAgent\>

The factory that produces the agent.

`description` [string](https://learn.microsoft.com/dotnet/api/system.string)?

A short description.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddAgentDecorator__1_Tracon_ITraconBuilder_"></a> AddAgentDecorator<TDecorator\>\(ITraconBuilder\)

Registers a custom agent decorator as a singleton.

```csharp
public static ITraconBuilder AddAgentDecorator<TDecorator>(this ITraconBuilder builder) where TDecorator : class, IAgentDecorator
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Type Parameters

`TDecorator` 

The decorator implementation type.

#### Remarks

Calling this method more than once for the same decorator type has no
effect. The decorator joins the pipeline alongside Tracon's own
(run recording, telemetry, tool approval); see
[IAgentDecorator.Order](/api/tracon.iagentdecorator/#Tracon_IAgentDecorator_Order) for where it lands. It must be
thread-safe because the catalog can decorate agents concurrently.

```csharp
builder.AddTracon()
       .AddAgentDecorator<AuditingAgentDecorator>();
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddAgentDecorator_Tracon_ITraconBuilder_Tracon_IAgentDecorator_"></a> AddAgentDecorator\(ITraconBuilder, IAgentDecorator\)

Registers a configured custom agent decorator as a singleton.

```csharp
public static ITraconBuilder AddAgentDecorator(this ITraconBuilder builder, IAgentDecorator decorator)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`decorator` [IAgentDecorator](/api/tracon.iagentdecorator/)

The decorator instance.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddAgentDecorator_Tracon_ITraconBuilder_System_Func_System_IServiceProvider_Tracon_IAgentDecorator__"></a> AddAgentDecorator\(ITraconBuilder, Func<IServiceProvider, IAgentDecorator\>\)

Registers a custom agent-decorator factory as a singleton.

```csharp
public static ITraconBuilder AddAgentDecorator(this ITraconBuilder builder, Func<IServiceProvider, IAgentDecorator> factory)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[IServiceProvider](https://learn.microsoft.com/dotnet/api/system.iserviceprovider), [IAgentDecorator](/api/tracon.iagentdecorator/)\>

The factory that creates the decorator.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddAgentExtension__1_Tracon_ITraconBuilder_"></a> AddAgentExtension<TExtension\>\(ITraconBuilder\)

Registers an agent extension as a singleton.

```csharp
public static ITraconBuilder AddAgentExtension<TExtension>(this ITraconBuilder builder) where TExtension : class, IAgentExtension
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Type Parameters

`TExtension` 

The extension implementation type.

#### Remarks

A definition selects the extension by [IAgentExtension.Name](/api/tracon.iagentextension/#Tracon_IAgentExtension_Name) in
[AgentDefinition.ExtensionNames](/api/tracon.agentdefinition/#Tracon_AgentDefinition_ExtensionNames). Calling this method more than
once for the same type has no effect; two types that report the same name are
rejected when the compiler is first used.

```csharp
builder.AddTracon()
       .AddAgentExtension<PolicyContextExtension>();
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddAgentExtension_Tracon_ITraconBuilder_Tracon_IAgentExtension_"></a> AddAgentExtension\(ITraconBuilder, IAgentExtension\)

Registers a configured agent extension.

```csharp
public static ITraconBuilder AddAgentExtension(this ITraconBuilder builder, IAgentExtension extension)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`extension` [IAgentExtension](/api/tracon.iagentextension/)

The extension instance.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` or `extension` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddAgentExtension_Tracon_ITraconBuilder_System_String_System_Action_Tracon_AgentExtensionContext__System_String_"></a> AddAgentExtension\(ITraconBuilder, string, Action<AgentExtensionContext\>, string?\)

Registers an agent extension from a delegate. A definition selects it by
`name` in [AgentDefinition.ExtensionNames](/api/tracon.agentdefinition/#Tracon_AgentDefinition_ExtensionNames).

```csharp
public static ITraconBuilder AddAgentExtension(this ITraconBuilder builder, string name, Action<AgentExtensionContext> configure, string? description = null)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`name` [string](https://learn.microsoft.com/dotnet/api/system.string)

The extension name: 1 to 128 characters of lowercase ASCII letters, digits, `.`,
`_` or `-`, unique among the registered extensions.

`configure` [Action](https://learn.microsoft.com/dotnet/api/system.action\-1)<[AgentExtensionContext](/api/tracon.agentextensioncontext/)\>

Changes the options of the agent that is being compiled, or adds a wrapper. It runs
when an agent that names the extension is compiled, not on every run.

`description` [string](https://learn.microsoft.com/dotnet/api/system.string)?

What the extension does, in one sentence. The console shows it next to the name and
`GET /api/agent-extensions` returns it to every reader, so it must not carry a
secret. [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null) shows the name alone.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

The escape door for a Microsoft Agent Framework option Tracon does not model.
A hand-built agent in `AddAgent(name, factory)` bypasses the model ring, the
tenant's provider credential, egress and cost; an extension keeps all of them
because the agent still goes through the compiler. The compiler refuses a change
to a member the definition or a tenant and security decision owns (the tool chain,
the tool approval settings, the chat history provider, file access, the
working-directory skill scan and the model parameters among them). It does not look
inside a provider or a wrapper the extension adds.

Adds your own context provider to the agents that select it:

```csharp
builder.AddTracon()
       .AddAgentExtension(
           "house-policy",
           context =>
           {
               if (context.ChatAgentOptions is { } options)
               {
                   options.AIContextProviders = [.. options.AIContextProviders ?? [], new HousePolicyProvider()];
               }
           },
           description: "Adds the house policy to the instructions of every model call.");
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` or `configure` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [ArgumentException](https://learn.microsoft.com/dotnet/api/system.argumentexception)

`name` is empty.

### <a id="Tracon_TraconBuilderExtensions_AddAgentSource__1_Tracon_ITraconBuilder_"></a> AddAgentSource<TSource\>\(ITraconBuilder\)

Registers a custom agent source as a singleton.

```csharp
public static ITraconBuilder AddAgentSource<TSource>(this ITraconBuilder builder) where TSource : class, IAgentSource
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Type Parameters

`TSource` 

The source implementation type.

#### Remarks

Calling this method more than once for the same source type has no effect.
The source can serve global or tenant-aware agents. It must be thread-safe
because the catalog calls its methods concurrently.

```csharp
builder.AddTracon()
       .AddAgentSource<GitAgentSource>();
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddAgentSource_Tracon_ITraconBuilder_Tracon_IAgentSource_"></a> AddAgentSource\(ITraconBuilder, IAgentSource\)

Registers a configured custom agent source as a singleton.

```csharp
public static ITraconBuilder AddAgentSource(this ITraconBuilder builder, IAgentSource source)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`source` [IAgentSource](/api/tracon.iagentsource/)

The source instance.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddAgentSource_Tracon_ITraconBuilder_System_Func_System_IServiceProvider_Tracon_IAgentSource__"></a> AddAgentSource\(ITraconBuilder, Func<IServiceProvider, IAgentSource\>\)

Registers a custom agent-source factory as a singleton.

```csharp
public static ITraconBuilder AddAgentSource(this ITraconBuilder builder, Func<IServiceProvider, IAgentSource> factory)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[IServiceProvider](https://learn.microsoft.com/dotnet/api/system.iserviceprovider), [IAgentSource](/api/tracon.iagentsource/)\>

The factory that creates the source.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddEvalCheck_Tracon_ITraconBuilder_System_String_Microsoft_Agents_AI_EvalCheck_"></a> AddEvalCheck\(ITraconBuilder, string, EvalCheck\)

Registers a custom eval check. Eval suites can reference it by
this `kind` name in their `checks` field.

```csharp
public static ITraconBuilder AddEvalCheck(this ITraconBuilder builder, string kind, EvalCheck check)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`kind` [string](https://learn.microsoft.com/dotnet/api/system.string)

The check type name. Must not collide with a built-in type (for example `nonEmpty`).

`check` EvalCheck

A code-written check that does not call the model.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

An `EvalCheck` produced with
`Microsoft.Agents.AI.FunctionEvaluator.Create(...)` is expected.
Same reason as tools: custom logic is only defined in code, and a
free-form expression cannot be written from the interface.

```csharp
builder.AddTracon()
       .AddEvalCheck("mentionsOrderId", FunctionEvaluator.Create(
           "mentionsOrderId",
           response => response.Contains("order", StringComparison.OrdinalIgnoreCase)));
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddHostedTool_Tracon_ITraconBuilder_System_String_Tracon_HostedToolKind_System_Func_Tracon_HostedToolContext_Microsoft_Extensions_AI_AITool__System_String_"></a> AddHostedTool\(ITraconBuilder, string, HostedToolKind, Func<HostedToolContext, AITool\>, string?\)

Registers a tool the model provider runs on its own side: a web search, a code interpreter or a file search.

```csharp
public static ITraconBuilder AddHostedTool(this ITraconBuilder builder, string name, HostedToolKind kind, Func<HostedToolContext, AITool> factory, string? description = null)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`name` [string](https://learn.microsoft.com/dotnet/api/system.string)

The name an agent definition selects the tool by in [AgentDefinition.ToolNames](/api/tracon.agentdefinition/#Tracon_AgentDefinition_ToolNames).
It is unique among function tools and hosted tools.

`kind` [HostedToolKind](/api/tracon.hostedtoolkind/)

The kind of tool the factory builds.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[HostedToolContext](/api/tracon.hostedtoolcontext/), AITool\>

Builds the tool for the agent being compiled. It must return the type that matches
`kind` (`HostedWebSearchTool`, `HostedCodeInterpreterTool` or
`HostedFileSearchTool`) and a new instance on every call.

`description` [string](https://learn.microsoft.com/dotnet/api/system.string)?

The description the agent editor shows, or [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

A hosted tool is code, as every tool is: the definition selects it by name, and its default is
off. The provider runs the tool inside the model call, so Tracon puts no timeout, approval or
permission in front of it, and what the tool reads (the web, a vector store, the data a code
interpreter is given) goes to the provider the model call already goes to. Each call is billed by the
provider: set `Tracon:Pricing:HostedTools:{provider}:{kind}:PerCall` so the cost reaches the run's
budget, the tenant's quota and the `run.completed` webhook.

The provider's API surface decides whether the kind runs. A definition that selects a kind the
surface drops does not compile; the agent validation names the tool and the provider.
An agent selects at most one hosted tool of each kind.

The factory runs on every run of an agent that selects the tool, for the tenant of the run; keep it cheap.
A value that belongs to the tenant, such as the identifier of the tenant's own vector store, is read
there. An identifier is not a `secret`; never put a credential into a hosted tool.

```csharp
builder.AddTracon()
       .AddHostedTool(
           "docs_search",
           HostedToolKind.FileSearch,
           context => new HostedFileSearchTool
           {
               Inputs = [new HostedVectorStoreContent(
                   context.Services.GetRequiredService<IConfiguration>()["VectorStores:Docs"]!)],
           },
           description: "Searches the product documentation.");
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder`, `name` or `factory` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [ArgumentOutOfRangeException](https://learn.microsoft.com/dotnet/api/system.argumentoutofrangeexception)

`kind` is not a defined kind.

 [TraconException](/api/tracon.traconexception/)

The tool name does not follow the tool naming rules.

### <a id="Tracon_TraconBuilderExtensions_AddLoopEvaluator_Tracon_ITraconBuilder_System_String_Microsoft_Agents_AI_LoopEvaluator_"></a> AddLoopEvaluator\(ITraconBuilder, string, LoopEvaluator\)

Registers a code-defined loop stop criterion with no description. A
definition's [LoopSettings.Criteria](/api/tracon.loopsettings/#Tracon_LoopSettings_Criteria) can then reference it by
this `kind` name.

```csharp
public static ITraconBuilder AddLoopEvaluator(this ITraconBuilder builder, string kind, LoopEvaluator evaluator)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`kind` [string](https://learn.microsoft.com/dotnet/api/system.string)

The criterion name. It must not be one of the built-in kinds
(`completionMarker`, `todoCompletion`, `aiJudge`,
`backgroundTaskCompletion`, `agentReview`); shadowing one is rejected, so the same
definition cannot mean different things in two applications.

`evaluator` LoopEvaluator

The criterion. One instance serves every agent and every run that names
the kind, so it must be thread-safe and keep no state of one run in its fields.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

The same registration as the overload that takes a description; the
console then shows the kind name alone.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddLoopEvaluator_Tracon_ITraconBuilder_System_String_Microsoft_Agents_AI_LoopEvaluator_System_String_"></a> AddLoopEvaluator\(ITraconBuilder, string, LoopEvaluator, string?\)

Registers a code-defined loop stop criterion. A definition's
[LoopSettings.Criteria](/api/tracon.loopsettings/#Tracon_LoopSettings_Criteria) can then reference it by this
`kind` name.

```csharp
public static ITraconBuilder AddLoopEvaluator(this ITraconBuilder builder, string kind, LoopEvaluator evaluator, string? description)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`kind` [string](https://learn.microsoft.com/dotnet/api/system.string)

The criterion name. It must not be one of the built-in kinds
(`completionMarker`, `todoCompletion`, `aiJudge`,
`backgroundTaskCompletion`, `agentReview`); shadowing one is rejected, so the same
definition cannot mean different things in two applications.

`evaluator` LoopEvaluator

The criterion. `Microsoft.Agents.AI.DelegateLoopEvaluator` wraps a
plain function; a subclass of `LoopEvaluator` covers anything larger.
One instance serves every agent and every run that names the kind, so it
must be thread-safe and keep no state of one run in its fields.

`description` [string](https://learn.microsoft.com/dotnet/api/system.string)?

What the criterion checks, in one sentence. The console shows it next to
the kind and `GET /api/loop-criteria` returns it to every reader, so
it must not carry a secret. [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null) shows the kind alone.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

Same reason as tools and eval checks: a stop criterion whose logic is
code is only ever defined in code. A definition arriving from the
management API names the criterion, it never writes it. A criterion that
needs an application service takes the factory overload instead.

The loop types are marked for evaluation only by Microsoft Agent
Framework, so naming one in your own code needs the suppression below:

```csharp
#pragma warning disable MAAI001
builder.AddTracon()
       .AddLoopEvaluator("hasCitations", new DelegateLoopEvaluator((context, ct) =>
           new ValueTask<LoopEvaluation>(
               context.LastResponse?.Text?.Contains("[1]", StringComparison.Ordinal) == true
                   ? LoopEvaluation.Stop()
                   : LoopEvaluation.Continue("Add a numbered citation for every claim."))));
#pragma warning restore MAAI001
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddLoopEvaluator_Tracon_ITraconBuilder_System_String_System_Func_System_IServiceProvider_Microsoft_Agents_AI_LoopEvaluator__"></a> AddLoopEvaluator\(ITraconBuilder, string, Func<IServiceProvider, LoopEvaluator\>\)

Registers a code-defined loop stop criterion that is created from the
application's services. A definition's [LoopSettings.Criteria](/api/tracon.loopsettings/#Tracon_LoopSettings_Criteria)
can then reference it by this `kind` name.

```csharp
public static ITraconBuilder AddLoopEvaluator(this ITraconBuilder builder, string kind, Func<IServiceProvider, LoopEvaluator> factory)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`kind` [string](https://learn.microsoft.com/dotnet/api/system.string)

The criterion name. It must not be one of the built-in kinds
(`completionMarker`, `todoCompletion`, `aiJudge`,
`backgroundTaskCompletion`, `agentReview`); shadowing one, or registering the same
name twice, is rejected before any factory runs.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[IServiceProvider](https://learn.microsoft.com/dotnet/api/system.iserviceprovider), LoopEvaluator\>

Creates the criterion from the application's root service provider. It
runs once, on the first compilation of an agent whose loop names
`kind`, and its result serves every agent, every run and
every tenant from then on.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

The same registration as the overload that takes a description; the
console then shows the kind name alone. That overload's remarks say when
the factory runs and how a criterion reads the tenant.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` or `factory` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddLoopEvaluator_Tracon_ITraconBuilder_System_String_System_Func_System_IServiceProvider_Microsoft_Agents_AI_LoopEvaluator__System_String_"></a> AddLoopEvaluator\(ITraconBuilder, string, Func<IServiceProvider, LoopEvaluator\>, string?\)

Registers a code-defined loop stop criterion that is created from the
application's services. A definition's [LoopSettings.Criteria](/api/tracon.loopsettings/#Tracon_LoopSettings_Criteria)
can then reference it by this `kind` name.

```csharp
public static ITraconBuilder AddLoopEvaluator(this ITraconBuilder builder, string kind, Func<IServiceProvider, LoopEvaluator> factory, string? description)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`kind` [string](https://learn.microsoft.com/dotnet/api/system.string)

The criterion name. It must not be one of the built-in kinds
(`completionMarker`, `todoCompletion`, `aiJudge`,
`backgroundTaskCompletion`, `agentReview`); shadowing one, or registering the same
name twice, is rejected before any factory runs.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[IServiceProvider](https://learn.microsoft.com/dotnet/api/system.iserviceprovider), LoopEvaluator\>

Creates the criterion from the application's root service provider. It
runs once, on the first compilation of an agent whose loop names
`kind`, and its result serves every agent, every run and
every tenant from then on.

`description` [string](https://learn.microsoft.com/dotnet/api/system.string)?

What the criterion checks, in one sentence. The console shows it next to
the kind and `GET /api/loop-criteria` returns it to every reader, so
it must not carry a secret. [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null) shows the kind alone.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

A criterion cannot take a service from `LoopContext`, which carries
none; the factory is where it takes them. The factory runs at the first
compilation rather than at setup, so a criterion may take the agent
catalog ([IAgentCatalog](/api/tracon.iagentcatalog/)): at setup the catalog is still being
built. When the factory throws, that compilation fails with a
[TraconCompilationException](/api/tracon.traconcompilationexception/) naming the kind, and the next
compilation calls the factory again; a successful result is kept.

The provider is the root one. Take singletons from it; a scoped service
would outlive its scope. The tenant is not known when the factory runs:
read [ITenantContext.TenantId](/api/tracon.itenantcontext/#Tracon_ITenantContext_TenantId) inside
`EvaluateAsync`, never in the factory or the constructor, or every
tenant would see the first tenant's value.

**A reviewer agent as the criterion.** The criterion below
computes a check in code, hands it to a reviewer agent from the catalog
with the draft, and reads the reviewer's own JSON verdict. The reviewer
runs as a child of the run being evaluated: it appears under that run in
the run tree, spends from the same tree budget, and its tokens are its
own run's usage. Per-run state, such as the round number, lives in
`LoopContext.AdditionalProperties`, which belongs to one loop run.
The draft is the last message of the turn: a harness turn can write a
plan or an earlier version first, and `LastResponse.Text` joins
every message of the turn.

```csharp
#pragma warning disable MAAI001
builder.AddTracon()
       .AddLoopEvaluator(
           "reviewed",
           services =>
           {
               var catalog = services.GetRequiredService<IAgentCatalog>();

               return new DelegateLoopEvaluator(async (context, cancellationToken) =>
               {
                   var messages = context.LastResponse?.Messages;
                   var draft = messages is { Count: > 0 } ? messages[messages.Count - 1].Text : string.Empty;
                   var words = draft.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
                   var round = context.AdditionalProperties.TryGetValue("reviewed.round", out var r) ? (int)r! + 1 : 1;
                   context.AdditionalProperties["reviewed.round"] = round;

                   var scope = TraconRunContext.Current;
                   if (scope?.Budget is { } budget && (scope.Depth + 1 > budget.MaxDepth || !budget.TryReserveRun()))
                   {
                       throw new InvalidOperationException("The run tree has no room for the reviewer.");
                   }

                   var reviewer = await catalog.ResolveAsync("reviewer", culture: null, cancellationToken)
                       ?? throw new InvalidOperationException("No agent named 'reviewer'.");
                   var options = scope is null ? null : new TraconRunOptions
                   {
                       ParentRunId = scope.RunId,
                       RootRunId = scope.RootRunId,
                       Depth = scope.Depth + 1,
                       Budget = scope.Budget,
                       SessionId = scope.SessionId,
                   };

                   var review = await reviewer.RunAsync(
                       $"Round {round}. Word count: {words}. Review this draft:\n{draft}",
                       session: null, options, cancellationToken);

                   // The reviewer's ResponseFormat is a JSON schema: {"pass": bool, "feedback": string}.
                   using var verdict = JsonDocument.Parse(review.Text);
                   return verdict.RootElement.GetProperty("pass").GetBoolean()
                       ? LoopEvaluation.Stop()
                       : LoopEvaluation.Continue(verdict.RootElement.GetProperty("feedback").GetString() ?? "Revise the draft.");
               });
           },
           description: "The reviewer agent approves the draft.");
#pragma warning restore MAAI001
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` or `factory` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddModelProvider__1_Tracon_ITraconBuilder_"></a> AddModelProvider<TProvider\>\(ITraconBuilder\)

Registers a custom model provider as a singleton.

```csharp
public static ITraconBuilder AddModelProvider<TProvider>(this ITraconBuilder builder) where TProvider : class, IModelProvider
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Type Parameters

`TProvider` 

The provider implementation type.

#### Remarks

Calling this method more than once for the same provider type has no
effect. Prefer this overload when the provider has no state to
configure by hand; use [TraconBuilderExtensions.AddModelProvider](/api/tracon.traconbuilderextensions/)
or the factory overload when it does.

```csharp
builder.AddTracon()
       .AddModelProvider<OnPremiseModelProvider>();
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddModelProvider_Tracon_ITraconBuilder_Tracon_IModelProvider_"></a> AddModelProvider\(ITraconBuilder, IModelProvider\)

Registers a model provider.

```csharp
public static ITraconBuilder AddModelProvider(this ITraconBuilder builder, IModelProvider provider)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`provider` [IModelProvider](/api/tracon.imodelprovider/)

The provider.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

The shipped provider packages (`UseOpenAI`, `UseAnthropic`,
and the rest) call this method. Register your own provider here when the
model sits behind an endpoint none of them describes.

```csharp
builder.AddTracon()
       .AddModelProvider(new OnPremiseModelProvider(endpoint));
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddModelProvider_Tracon_ITraconBuilder_System_Func_System_IServiceProvider_Tracon_IModelProvider__"></a> AddModelProvider\(ITraconBuilder, Func<IServiceProvider, IModelProvider\>\)

Registers a model provider through a factory.

```csharp
public static ITraconBuilder AddModelProvider(this ITraconBuilder builder, Func<IServiceProvider, IModelProvider> factory)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[IServiceProvider](https://learn.microsoft.com/dotnet/api/system.iserviceprovider), [IModelProvider](/api/tracon.imodelprovider/)\>

The factory that produces the provider.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddRunJudge__1_Tracon_ITraconBuilder_"></a> AddRunJudge<TJudge\>\(ITraconBuilder\)

Registers a custom run judge as a singleton.

```csharp
public static ITraconBuilder AddRunJudge<TJudge>(this ITraconBuilder builder) where TJudge : class, IRunJudge
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Type Parameters

`TJudge` 

The judge implementation type.

#### Remarks

Repeating this overload for the same implementation type has no effect.
The container creates and owns the singleton. The judge must be
thread-safe because evaluations can overlap, including when a timed-out
call finishes after a retry starts.

```csharp
builder.AddTracon()
       .AddRunJudge<ResponseQualityJudge>();
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddRunJudge_Tracon_ITraconBuilder_Tracon_IRunJudge_"></a> AddRunJudge\(ITraconBuilder, IRunJudge\)

Registers a configured run-judge instance as a singleton.

```csharp
public static ITraconBuilder AddRunJudge(this ITraconBuilder builder, IRunJudge judge)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`judge` [IRunJudge](/api/tracon.irunjudge/)

The judge instance.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

The caller owns the instance and any resources it holds. Different
configured instances of the same CLR type are preserved. Their
[IRunJudge.Name](/api/tracon.irunjudge/#Tracon_IRunJudge_Name) values must still be unique.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddRunJudge_Tracon_ITraconBuilder_System_Func_System_IServiceProvider_Tracon_IRunJudge__"></a> AddRunJudge\(ITraconBuilder, Func<IServiceProvider, IRunJudge\>\)

Registers a run-judge factory as a singleton.

```csharp
public static ITraconBuilder AddRunJudge(this ITraconBuilder builder, Func<IServiceProvider, IRunJudge> factory)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[IServiceProvider](https://learn.microsoft.com/dotnet/api/system.iserviceprovider), [IRunJudge](/api/tracon.irunjudge/)\>

The factory that creates the judge.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

The container owns the produced singleton. The factory must not capture
a scoped dependency because the result outlives that scope. Different
factories and configured results are preserved.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddScopedTool_Tracon_ITraconBuilder_Microsoft_Extensions_AI_AIFunction_System_Action_Tracon_ToolRegistrationOptions__"></a> AddScopedTool\(ITraconBuilder, AIFunction, Action<ToolRegistrationOptions\>\)

Registers a tool that runs inside its own dependency-injection scope on every call.

```csharp
public static ITraconBuilder AddScopedTool(this ITraconBuilder builder, AIFunction tool, Action<ToolRegistrationOptions> configure)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`tool` AIFunction

The tool to register.

`configure` [Action](https://learn.microsoft.com/dotnet/api/system.action\-1)<[ToolRegistrationOptions](/api/tracon.toolregistrationoptions/)\>

Configures the tool metadata.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

Identical in shape to [TraconBuilderExtensions.AddTool](/api/tracon.traconbuilderextensions/) —
the one difference is the word "scoped", and its meaning is exactly
this: every call opens a fresh `DependencyInjection.IServiceScope`, exposes it
through `AIFunctionArguments.Services`, and closes it as
soon as the call finishes. Microsoft Agent Framework otherwise passes
an empty provider there — a dependency resolved from
`AIFunctionArguments.Services` without this method throws or
returns nothing, it is never silently wrong.

Use this for a tool that needs a repository, a `DbContext`, or
any other per-call dependency. Two concurrent calls never share a
scope.

```csharp
builder.AddTracon()
       .AddScopedTool(AIFunctionFactory.Create(
           async (string orderId, AIFunctionArguments arguments) =>
           {
               var orders = arguments.Services!.GetRequiredService<IOrderRepository>();
               return await orders.GetAsync(orderId);
           },
           "get_order"),
           options => options.RequiredPermission = "orders.read");
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddScopedTool_Tracon_ITraconBuilder_Microsoft_Extensions_AI_AIFunction_"></a> AddScopedTool\(ITraconBuilder, AIFunction\)

Registers a tool that runs inside its own dependency-injection scope on every call, with default metadata.

```csharp
public static ITraconBuilder AddScopedTool(this ITraconBuilder builder, AIFunction tool)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`tool` AIFunction

The tool to register.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddSkill_Tracon_ITraconBuilder_Tracon_AgentSkillDefinition_"></a> AddSkill\(ITraconBuilder, AgentSkillDefinition\)

Defines a skill in code. A skill defined in code takes precedence over a
runtime skill with the same name.

```csharp
public static ITraconBuilder AddSkill(this ITraconBuilder builder, AgentSkillDefinition skill)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`skill` [AgentSkillDefinition](/api/tracon.agentskilldefinition/)

The skill to register.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

A skill is instruction text an agent loads by name. When it carries
[AgentSkillDefinition.Scripts](/api/tracon.agentskilldefinition/#Tracon_AgentSkillDefinition_Scripts), those scripts run on the
server like stored ones: they need `AllowStoredScripts`, an
allow-listed interpreter, and a grant pinned to their content. The hash
to grant is read from `GET /api/skills/{name}`, which resolves a code
skill first. A deployment that changes a script changes its hash, so the
script needs a new grant before it runs again.

```csharp
builder.AddTracon()
       .AddSkill(new AgentSkillDefinition
       {
           TenantId = "default",
           Name = "refund-policy",
           Description = "How a refund decision is made.",
           Instructions = "A refund under 100 USD is approved without review.",
       });
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddSpeechSynthesizer_Tracon_ITraconBuilder_System_String_System_Func_System_IServiceProvider_Tracon_ISpeechSynthesizer__"></a> AddSpeechSynthesizer\(ITraconBuilder, string, Func<IServiceProvider, ISpeechSynthesizer\>\)

Registers a named speech synthesizer as a singleton.

```csharp
public static ITraconBuilder AddSpeechSynthesizer(this ITraconBuilder builder, string name, Func<IServiceProvider, ISpeechSynthesizer> factory)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`name` [string](https://learn.microsoft.com/dotnet/api/system.string)

The registration name: 1 to 64 characters of `a-z`, `0-9`, `.`,
`_` or `-`, compared in lower case.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[IServiceProvider](https://learn.microsoft.com/dotnet/api/system.iserviceprovider), [ISpeechSynthesizer](/api/tracon.ispeechsynthesizer/)\>

Creates the synthesizer once, the first time the name is resolved.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

A caller selects the synthesizer by name through
[ISpeechProviderResolver.GetSynthesizerAsync](/api/tracon.ispeechproviderresolver/#Tracon_ISpeechProviderResolver_GetSynthesizerAsync_System_String_System_Threading_CancellationToken_): a workflow function
node, or `POST /api/voice/speak` with `provider`. The unnamed default
(`UseVoice`, or your own [ISpeechSynthesizer](/api/tracon.ispeechsynthesizer/) registration)
is not affected, and the call can come before or after `UseVoice`.

The tenant's egress policy applies to the synthesizer's
[ISpeechSynthesizer.ProviderName](/api/tracon.ispeechsynthesizer/#Tracon_ISpeechSynthesizer_ProviderName), not to `name`:
two names for one service are one provider to the policy. A factory that
returns the same instance for two names shares that instance, and its
concurrency limit, between them.

A synthesizer that can call the service with a tenant's own key sets
[ISpeechSynthesizer.SupportsTenantCredentials](/api/tracon.ispeechsynthesizer/#Tracon_ISpeechSynthesizer_SupportsTenantCredentials) and reads
[SpeechRequest.Credential](/api/tracon.speechrequest/#Tracon_SpeechRequest_Credential). One that cannot is refused for a tenant
that has its own binding for its provider name.

```csharp
builder.AddTracon()
       .AddSpeechSynthesizer("studio", provider => new StudioSpeechSynthesizer(
           provider.GetRequiredService<IConfiguration>()["Studio:ApiKey"]));
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` or `factory` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [ArgumentException](https://learn.microsoft.com/dotnet/api/system.argumentexception)

`name` is not a valid speech provider name.

 [InvalidOperationException](https://learn.microsoft.com/dotnet/api/system.invalidoperationexception)

A synthesizer with the same name is already registered.

### <a id="Tracon_TraconBuilderExtensions_AddSpeechSynthesizer_Tracon_ITraconBuilder_System_String_Tracon_TextToSpeechClientBinding_"></a> AddSpeechSynthesizer\(ITraconBuilder, string, TextToSpeechClientBinding\)

Registers a named speech synthesizer that serves a Microsoft.Extensions.AI text-to-speech client.

```csharp
public static ITraconBuilder AddSpeechSynthesizer(this ITraconBuilder builder, string name, TextToSpeechClientBinding binding)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`name` [string](https://learn.microsoft.com/dotnet/api/system.string)

The registration name: 1 to 64 characters of `a-z`, `0-9`, `.`,
`_` or `-`, compared in lower case.

`binding` [TextToSpeechClientBinding](/api/tracon.texttospeechclientbinding/)

Which client in the container serves the name, and what the client cannot say about itself.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

The result is an ordinary named synthesizer: the rules of
[TraconBuilderExtensions.AddSpeechSynthesizer](/api/tracon.traconbuilderextensions/)
apply. Every call passes the tenant's egress policy against the provider name, and a
tenant that has its own key for that provider is refused: a bridged client was built
with the setup credential and cannot use another.

The host does not start when the client is not registered or has no provider name.
Billing is an estimate: the client reports no billed characters, so Tracon records the
length of the text and labels it [SpeechUsageSource.Estimated](/api/tracon.speechusagesource/). A request
for character timing ([SpeechRequest.IncludeTimestamps](/api/tracon.speechrequest/#Tracon_SpeechRequest_IncludeTimestamps)) is refused, and the
synthesizer cannot voice a dialogue.

Do not put a `secret` in [SpeechRequest.ProviderSettings](/api/tracon.speechrequest/#Tracon_SpeechRequest_ProviderSettings): the values reach
the client unchanged, and a client wrapped in `LoggingTextToSpeechClient` logs its
options at Trace level.

```csharp
#pragma warning disable MEAI001 // Microsoft.Extensions.AI marks its speech clients experimental
builder.Services.AddKeyedTextToSpeechClient("studio", provider => new StudioTextToSpeechClient(
    provider.GetRequiredService<IConfiguration>()["Studio:ApiKey"]));

builder.AddTracon()
       .AddSpeechSynthesizer("studio", new TextToSpeechClientBinding
       {
           ServiceKey = "studio",
           ProviderName = "studio",
           MaxCharactersPerRequest = 4000,
       });
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` or `binding` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [ArgumentException](https://learn.microsoft.com/dotnet/api/system.argumentexception)

`name` is not a valid speech provider name, or
[TextToSpeechClientBinding.MaxCharactersPerRequest](/api/tracon.texttospeechclientbinding/#Tracon_TextToSpeechClientBinding_MaxCharactersPerRequest) is not greater than zero.

 [InvalidOperationException](https://learn.microsoft.com/dotnet/api/system.invalidoperationexception)

A synthesizer with the same name is already registered.

### <a id="Tracon_TraconBuilderExtensions_AddSpeechTranscriber_Tracon_ITraconBuilder_System_String_System_Func_System_IServiceProvider_Tracon_ISpeechTranscriber__"></a> AddSpeechTranscriber\(ITraconBuilder, string, Func<IServiceProvider, ISpeechTranscriber\>\)

Registers a named speech transcriber as a singleton.

```csharp
public static ITraconBuilder AddSpeechTranscriber(this ITraconBuilder builder, string name, Func<IServiceProvider, ISpeechTranscriber> factory)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`name` [string](https://learn.microsoft.com/dotnet/api/system.string)

The registration name: 1 to 64 characters of `a-z`, `0-9`, `.`,
`_` or `-`, compared in lower case. Transcriber names are separate
from synthesizer names.

`factory` [Func](https://learn.microsoft.com/dotnet/api/system.func\-2)<[IServiceProvider](https://learn.microsoft.com/dotnet/api/system.iserviceprovider), [ISpeechTranscriber](/api/tracon.ispeechtranscriber/)\>

Creates the transcriber once, the first time the name is resolved.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

A caller selects the transcriber by name through
[ISpeechProviderResolver.GetTranscriberAsync](/api/tracon.ispeechproviderresolver/#Tracon_ISpeechProviderResolver_GetTranscriberAsync_System_String_System_Threading_CancellationToken_). The rules of
[TraconBuilderExtensions.AddSpeechSynthesizer](/api/tracon.traconbuilderextensions/) apply: the tenant's policy reads
[ISpeechTranscriber.ProviderName](/api/tracon.ispeechtranscriber/#Tracon_ISpeechTranscriber_ProviderName), and a tenant credential reaches
the transcriber only in [SpeechTranscriptionOptions.Credential](/api/tracon.speechtranscriptionoptions/#Tracon_SpeechTranscriptionOptions_Credential).

```csharp
builder.AddTracon()
       .AddSpeechTranscriber("on-prem", provider => new OnPremiseTranscriber(
           new Uri("http://gpu-01:9000/")));
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` or `factory` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [ArgumentException](https://learn.microsoft.com/dotnet/api/system.argumentexception)

`name` is not a valid speech provider name.

 [InvalidOperationException](https://learn.microsoft.com/dotnet/api/system.invalidoperationexception)

A transcriber with the same name is already registered.

### <a id="Tracon_TraconBuilderExtensions_AddSpeechTranscriber_Tracon_ITraconBuilder_System_String_Tracon_SpeechToTextClientBinding_"></a> AddSpeechTranscriber\(ITraconBuilder, string, SpeechToTextClientBinding\)

Registers a named speech transcriber that serves a Microsoft.Extensions.AI speech-to-text client.

```csharp
public static ITraconBuilder AddSpeechTranscriber(this ITraconBuilder builder, string name, SpeechToTextClientBinding binding)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`name` [string](https://learn.microsoft.com/dotnet/api/system.string)

The registration name: 1 to 64 characters of `a-z`, `0-9`, `.`,
`_` or `-`, compared in lower case. Transcriber names are separate
from synthesizer names.

`binding` [SpeechToTextClientBinding](/api/tracon.speechtotextclientbinding/)

Which client in the container serves the name, and what the client cannot say about itself.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

The rules of [TraconBuilderExtensions.AddSpeechSynthesizer](/api/tracon.traconbuilderextensions/)
apply: the tenant's egress policy and provider bindings read the provider name, and the
host does not start when the client is missing or has no name.

The client's contract takes the audio stream and no media type, so
`mediaType` is not passed on. The transcript has no duration unless the client
reports a start and an end time, and a transcription without a duration has no cost.

```csharp
#pragma warning disable MEAI001 // Microsoft.Extensions.AI marks its speech clients experimental
builder.Services.AddKeyedSpeechToTextClient("studio", provider => new StudioSpeechToTextClient(
    provider.GetRequiredService<IConfiguration>()["Studio:ApiKey"]));

builder.AddTracon()
       .AddSpeechTranscriber("studio", new SpeechToTextClientBinding
       {
           ServiceKey = "studio",
           ProviderName = "studio",
       });
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` or `binding` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [ArgumentException](https://learn.microsoft.com/dotnet/api/system.argumentexception)

`name` is not a valid speech provider name.

 [InvalidOperationException](https://learn.microsoft.com/dotnet/api/system.invalidoperationexception)

A transcriber with the same name is already registered.

### <a id="Tracon_TraconBuilderExtensions_AddTool_Tracon_ITraconBuilder_Microsoft_Extensions_AI_AIFunction_System_Action_Tracon_ToolRegistrationOptions__"></a> AddTool\(ITraconBuilder, AIFunction, Action<ToolRegistrationOptions\>\)

Registers a tool.

```csharp
public static ITraconBuilder AddTool(this ITraconBuilder builder, AIFunction tool, Action<ToolRegistrationOptions> configure)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`tool` AIFunction

The tool to register.

`configure` [Action](https://learn.microsoft.com/dotnet/api/system.action\-1)<[ToolRegistrationOptions](/api/tracon.toolregistrationoptions/)\>

Configures the tool metadata.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

The AOT-safe overload: the caller supplies the built
`AI.AIFunction`, so no reflection is involved.

```csharp
builder.AddTracon()
       .AddTool(refundTool, options => options.RequiresApproval = true);
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddTool_Tracon_ITraconBuilder_Microsoft_Extensions_AI_AIFunction_"></a> AddTool\(ITraconBuilder, AIFunction\)

Registers a tool with default metadata.

```csharp
public static ITraconBuilder AddTool(this ITraconBuilder builder, AIFunction tool)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`tool` AIFunction

The tool to register.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddTool_Tracon_ITraconBuilder_System_Delegate_System_String_System_String_System_Action_Tracon_ToolRegistrationOptions__"></a> AddTool\(ITraconBuilder, Delegate, string?, string?, Action<ToolRegistrationOptions\>?\)

Builds and registers a tool from a method.

```csharp
[RequiresUnreferencedCode("Building a tool from a method uses reflection; type information may be lost in trimmed applications.")]
[RequiresDynamicCode("Building a tool from a method may require code generation at runtime.")]
public static ITraconBuilder AddTool(this ITraconBuilder builder, Delegate method, string? name = null, string? description = null, Action<ToolRegistrationOptions>? configure = null)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`method` [Delegate](https://learn.microsoft.com/dotnet/api/system.delegate)

The method to expose as a tool.

`name` [string](https://learn.microsoft.com/dotnet/api/system.string)?

The tool name.

`description` [string](https://learn.microsoft.com/dotnet/api/system.string)?

The tool description.

`configure` [Action](https://learn.microsoft.com/dotnet/api/system.action\-1)<[ToolRegistrationOptions](/api/tracon.toolregistrationoptions/)\>?

Configures the tool metadata.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_AddToolsFrom__1_Tracon_ITraconBuilder_"></a> AddToolsFrom<T\>\(ITraconBuilder\)

Registers, as tools, the methods on a type that are marked with
[TraconToolAttribute](/api/tracon.tracontoolattribute/).

```csharp
[RequiresUnreferencedCode("Tool scanning uses reflection; method information may be lost in trimmed applications.")]
[RequiresDynamicCode("Tool scanning may require code generation at runtime.")]
public static ITraconBuilder AddToolsFrom<T>(this ITraconBuilder builder)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Type Parameters

`T` 

The type to scan.

#### Remarks

Marking is an explicit choice: every new method added to the class is
not automatically exposed to agents. Static methods bind directly; for
instance methods, the owning object is resolved from the service
provider at call time.

**A static class cannot be a type argument** (a C# rule).
If your tools live in a `static class`, use the
[TraconBuilderExtensions.AddToolsFrom](/api/tracon.traconbuilderextensions/) overload instead.

This method uses reflection and is not safe under trimming or native AOT
scenarios. Applications targeting AOT should use the
[TraconBuilderExtensions.AddTool](/api/tracon.traconbuilderextensions/) overload instead.

```csharp
builder.AddTracon()
       .AddToolsFrom<OrderTools>();
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [TraconException](/api/tracon.traconexception/)

`T` has no marked method, or a marked method cannot
be converted to a tool.

### <a id="Tracon_TraconBuilderExtensions_AddToolsFrom_Tracon_ITraconBuilder_System_Type_"></a> AddToolsFrom\(ITraconBuilder, Type\)

Registers, as tools, the methods on a type that are marked with
[TraconToolAttribute](/api/tracon.tracontoolattribute/).

```csharp
[RequiresUnreferencedCode("Tool scanning uses reflection; method information may be lost in trimmed applications.")]
[RequiresDynamicCode("Tool scanning may require code generation at runtime.")]
public static ITraconBuilder AddToolsFrom(this ITraconBuilder builder, Type type)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`type` [Type](https://learn.microsoft.com/dotnet/api/system.type)

The type to scan. May be a `static class`.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

A static class cannot be a type argument under C# rules; this overload
makes the `AddToolsFrom(typeof(OrderTools))` form possible.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` or `type` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [TraconException](/api/tracon.traconexception/)

`type` has no marked method, or a marked method cannot
be converted to a tool.

### <a id="Tracon_TraconBuilderExtensions_Configure_Tracon_ITraconBuilder_System_Action_Tracon_TraconOptions__"></a> Configure\(ITraconBuilder, Action<TraconOptions\>\)

Modifies the runtime settings.

```csharp
public static ITraconBuilder Configure(this ITraconBuilder builder, Action<TraconOptions> configure)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`configure` [Action](https://learn.microsoft.com/dotnet/api/system.action\-1)<[TraconOptions](/api/tracon.traconoptions/)\>

The settings modifier.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

Runs after the configuration section is bound, so a value set here wins
over `appsettings.json`.

```csharp
builder.AddTracon()
       .Configure(options => options.Tools.DefaultTimeout = TimeSpan.FromSeconds(60));
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_RequireCustomBinding__1_Tracon_ITraconBuilder_"></a> RequireCustomBinding<T\>\(ITraconBuilder\)

Declares that `T` must resolve to the application's
own registration. The host does not start when Tracon's built-in
default is what resolves.

```csharp
public static ITraconBuilder RequireCustomBinding<T>(this ITraconBuilder builder) where T : class
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Type Parameters

`T` 

One of the seven embedding points: [ITenantContext](/api/tracon.itenantcontext/),
[IRunAttributionContext](/api/tracon.irunattributioncontext/), [IToolAuthorizationHandler](/api/tracon.itoolauthorizationhandler/),
[IRunAuthorizationHandler](/api/tracon.irunauthorizationhandler/), [IRunEventSink](/api/tracon.iruneventsink/),
[IAttachmentStorage](/api/tracon.iattachmentstorage/), or [IToolApprovalPresenter](/api/tracon.itoolapprovalpresenter/);
or a contract Tracon registers a built-in default for: a store interface,
or [ISkillScriptExecutor](/api/tracon.iskillscriptexecutor/) once `UseSkillScripts` is called.
Any other type stops the host from starting, with a message naming the seven.

#### Remarks

Off by default: an application that never calls this behaves exactly as
before. Every extension point is registered with `TryAdd`, so a host
that binds nothing runs on the built-in default and starts silently. That
suits a first run; it does not suit a deployment whose module order can
leave an authorization handler on the permissive default without anyone
noticing until the first unauthorized request.

The check runs while the host starts, not when endpoints are mapped, so
an embedded host with no HTTP surface gets the same guarantee. Register
the implementation BEFORE `AddTracon`: a `TryAdd`
registration made afterwards is dropped, and the built-in default stays.

This is a composition gate. It proves which implementation is bound; it
proves nothing about whether that implementation decides correctly.

```csharp
builder.Services.AddSingleton<IRunAuthorizationHandler, OrderDeskAuthorization>();

builder.AddTracon()
       .RequireCustomBinding<IRunAuthorizationHandler>()
       .RequireCustomBinding<IToolAuthorizationHandler>();
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_TraconBuilderExtensions_RequireProductionProfile_Tracon_ITraconBuilder_System_Action_Tracon_TraconProductionProfileOptions__"></a> RequireProductionProfile\(ITraconBuilder, Action<TraconProductionProfileOptions\>?\)

Refuses to start the host while a security-sensitive decision is still
on its permissive default and the deployment has not accepted the risk
by name.

```csharp
public static ITraconBuilder RequireProductionProfile(this ITraconBuilder builder, Action<TraconProductionProfileOptions>? configure = null)
```

#### Parameters

`builder` [ITraconBuilder](/api/tracon.itraconbuilder/)

The Tracon configuration chain.

`configure` [Action](https://learn.microsoft.com/dotnet/api/system.action\-1)<[TraconProductionProfileOptions](/api/tracon.traconproductionprofileoptions/)\>?

The risks this deployment has deliberately decided to carry. Omit it to
accept none, which is the strictest form.

#### Returns

 [ITraconBuilder](/api/tracon.itraconbuilder/)

The chain, for further configuration.

#### Remarks

**This does not make anything secure and changes no setting.**
It sets no value, chooses no policy and turns nothing on. The only thing
it does is turn a skipped decision into a startup failure - which is the
one thing a permissive default cannot do for itself.

Off by default: an application that never calls this behaves exactly as
before. `AddTracon` brings every security-sensitive switch up
permissive on purpose, so a first run surprises nobody. A production
deployment wants the opposite, and today it can reach production having
never separated tenants, never decided who owns a session and never
registered a content guard, in complete silence.

Six decisions are asked about: tenant separation, session ownership,
at-rest content protection, content inspection, request rate limiting
and retention. Each one is either answered by turning the feature on, or
accepted by name. Acceptance is per item and there is no way to accept
them all at once.

**The set of decisions is a versioned contract.** A later
release that adds one stops a host that calls this method until the new
decision is answered or accepted. Read that cost before adopting the
method: it is the method working, not failing.

This is a composition gate, not a security proof. It proves a feature is
switched on; it proves nothing about whether the policy behind it is
right.

```csharp
builder.AddTracon()
       .RequireProductionProfile(profile => profile
           .Accept(TraconProductionRisk.SingleTenant)
           .Accept(TraconProductionRisk.UnboundedRetention));
```

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`builder` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).
