# FakeModelProvider

> 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.testing.fakemodelprovider/
> Summary: FakeModelProvider: Configurable, non-networked fake model provider.

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

Configurable, non-networked fake model provider.

```csharp
public sealed class FakeModelProvider : ITenantCredentialModelProvider, IModelProvider, ISamplingSupport, IHostedToolSupport, IDisposable
```

<dl class="api-relations"><dt>Inheritance</dt><dd><a href="https://learn.microsoft.com/dotnet/api/system.object">object</a> ← <a href="/api/tracon.testing.fakemodelprovider/">FakeModelProvider</a></dd><dt>Implements</dt><dd><a href="/api/tracon.itenantcredentialmodelprovider/">ITenantCredentialModelProvider</a>, <a href="/api/tracon.imodelprovider/">IModelProvider</a>, <a href="/api/tracon.isamplingsupport/">ISamplingSupport</a>, <a href="/api/tracon.ihostedtoolsupport/">IHostedToolSupport</a>, <a href="https://learn.microsoft.com/dotnet/api/system.idisposable">IDisposable</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.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>

## Examples

```csharp
var provider = new FakeModelProvider().
CallsTool("get_order_status", new { orderId = "ORD-7" }).
EchoesUserMessage();
```

## Remarks

Five fluent methods ([FakeModelProvider.RespondsWith](/api/tracon.testing.fakemodelprovider/), [FakeModelProvider.EchoesUserMessage](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_EchoesUserMessage),
[FakeModelProvider.CallsTool](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_CallsTool_System_String_System_Object_), [FakeModelProvider.ForModel](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_ForModel_System_String_System_Action_Tracon_Testing_FakeModelProvider__), [FakeModelProvider.WithModel](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_WithModel_Tracon_ModelDescriptor_)) cover
all the fake provider behavior that is today duplicated across five separate
files in Tracon's test suites.

Each model has its own **ordered response queue** (selected with
[FakeModelProvider.ForModel](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_ForModel_System_String_System_Action_Tracon_Testing_FakeModelProvider__); the default queue is used when none is selected). A
call pops the next step in the queue; once the queue is drained, every
subsequent call returns either the echo set with [FakeModelProvider.EchoesUserMessage](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_EchoesUserMessage)
or a fixed response. This behavior is lasting for the provider's lifetime —
it does not infer "which tool was already called" by scanning message history.

## Constructors

### <a id="Tracon_Testing_FakeModelProvider__ctor_System_String_"></a> FakeModelProvider\(string\)

Creates a new fake provider.

```csharp
public FakeModelProvider(string name = "fake")
```

#### Parameters

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

## Properties

### <a id="Tracon_Testing_FakeModelProvider_Models"></a> Models

The models this provider offers.

```csharp
public IReadOnlyList<ModelDescriptor> Models { get; }
```

#### Property Value

 [IReadOnlyList](https://learn.microsoft.com/dotnet/api/system.collections.generic.ireadonlylist\-1)<[ModelDescriptor](/api/tracon.modeldescriptor/)\>

#### Remarks

Metadata, not an allow list — see the remarks on
[IModelProvider](/api/tracon.imodelprovider/). This is read on the compile path and may
be read concurrently; return a stable, immutable collection rather than
one that is mutated after construction.

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

The provider name. [ModelBinding.Provider](/api/tracon.modelbinding/#Tracon_ModelBinding_Provider) matches this
value. Comparison is case-insensitive.

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

 [string](https://learn.microsoft.com/dotnet/api/system.string)

### <a id="Tracon_Testing_FakeModelProvider_Requests"></a> Requests

Requests that reached this provider; the newest is last.

```csharp
public IReadOnlyList<FakeModelRequest> Requests { get; }
```

#### Property Value

 [IReadOnlyList](https://learn.microsoft.com/dotnet/api/system.collections.generic.ireadonlylist\-1)<[FakeModelRequest](/api/tracon.testing.fakemodelrequest/)\>

### <a id="Tracon_Testing_FakeModelProvider_SupportedHostedTools"></a> SupportedHostedTools

Gets every kind: the fake runs no tool, so it accepts what a definition selects and
[FakeModelProvider.Requests](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_Requests) shows the tools that reached it.

```csharp
public HostedToolKinds SupportedHostedTools { get; }
```

#### Property Value

 [HostedToolKinds](/api/tracon.hostedtoolkinds/)

### <a id="Tracon_Testing_FakeModelProvider_SupportedSamplingFields"></a> SupportedSamplingFields

Gets every field: the fake sends no request, so it accepts what a definition sets and
[FakeModelProvider.Requests](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_Requests) shows it.

```csharp
public SamplingFields SupportedSamplingFields { get; }
```

#### Property Value

 [SamplingFields](/api/tracon.samplingfields/)

## Methods

### <a id="Tracon_Testing_FakeModelProvider_CallsTool_System_String_System_Object_"></a> CallsTool\(string, object?\)

Enqueues a tool call.

```csharp
public FakeModelProvider CallsTool(string toolName, object? arguments = null)
```

#### Parameters

`toolName` [string](https://learn.microsoft.com/dotnet/api/system.string)

Name of the tool to call.

`arguments` [object](https://learn.microsoft.com/dotnet/api/system.object)?

Call arguments. If not an [IDictionary](https://learn.microsoft.com/dotnet/api/system.collections.generic.idictionary-2), its
properties are read through reflection (works for anonymous types).

#### Returns

 [FakeModelProvider](/api/tracon.testing.fakemodelprovider/)

The chain, for continued configuration.

### <a id="Tracon_Testing_FakeModelProvider_CallsTools_System_ValueTuple_System_String_System_Object____"></a> CallsTools\(params \(string ToolName, object? Arguments\)\[\]\)

Enqueues a SINGLE turn that calls every given tool at once.

```csharp
public FakeModelProvider CallsTools(params (string ToolName, object? Arguments)[] calls)
```

#### Parameters

`calls` \([string](https://learn.microsoft.com/dotnet/api/system.string) [ToolName](https://learn.microsoft.com/dotnet/api/system.valuetuple\-system.string,system.object\-.toolname), [object](https://learn.microsoft.com/dotnet/api/system.object)? [Arguments](https://learn.microsoft.com/dotnet/api/system.valuetuple\-system.string,system.object\-.arguments)\)\[\]

The tool name and arguments for each call.

#### Returns

 [FakeModelProvider](/api/tracon.testing.fakemodelprovider/)

The chain, for continued configuration.

#### Remarks

[FakeModelProvider.CallsTool](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_CallsTool_System_String_System_Object_) enqueues one call per turn and can never
produce more than one `FunctionCallContent` in the same response;
exercising a REAL concurrent tool-call loop
(`FunctionInvokingChatClient.AllowConcurrentInvocation`) needs
several independent calls to arrive together, in one turn.

### <a id="Tracon_Testing_FakeModelProvider_CreateChatClient_Tracon_ModelBinding_"></a> CreateChatClient\(ModelBinding\)

Produces a **raw** chat client for the given binding.

```csharp
public IChatClient CreateChatClient(ModelBinding binding)
```

#### Parameters

`binding` [ModelBinding](/api/tracon.modelbinding/)

The model binding.

#### Returns

 IChatClient

The provider-specific client. Decorators *specific* to the
provider (example: Anthropic's settings decorator) may be added here.

#### Remarks

**Do not build the common pipeline here.**
`UseFunctionInvocation`, `UseOpenTelemetry`, the content
guard, the circuit breaker, the per-provider concurrency limiter,
attachment resolution, response caching, the fallback chain and
content-filter detection are all added by
`ModelProviderRegistry.CreateChatClient`. Before that shared pipeline, every
provider package built the tool-call loop inside itself; the result
was that no ring the registry wraps around could see the loop's turns
— a tool result entered the model uninspected.

If the loop is also built here, two nested `FunctionInvokingChatClient`
instances form: the inner one resolves tools, the outer one never sees
any call. This is **not** merely cosmetic. The registry
places the content guard directly above the client this method returns,
so that every turn of the tool-call loop is inspected. With an inner
loop, the turn that carries a tool result back into the model runs
*beneath* the guard: measured on a single-tool run, the guard
sees the tool result only on its way out
(`ContentGuardDirection.Output`) and never on its way in
(`ContentGuardDirection.Input`) — which is the exact path prompt
injection takes. The reply text and the tool-call count are unchanged,
so nothing else reveals the mistake.

**Lifetime of the returned client.** Tracon does
**not** dispose it. The client is built once per compiled
agent and stored in it; the compiled agent
(`Microsoft.Agents.AI.ChatClientAgent`) implements neither
[IDisposable](https://learn.microsoft.com/dotnet/api/system.idisposable) nor [IAsyncDisposable](https://learn.microsoft.com/dotnet/api/system.iasyncdisposable), and
evicting an agent from the compile cache drops the reference without
disposing. An implementation therefore owns the lifetime of whatever it
returns, and what it returns must tolerate never being disposed. This
is why the shipped providers return clients backed by a long-lived,
shared SDK client rather than a per-call one: returning a client that
holds a resource needing release would leak it.

### <a id="Tracon_Testing_FakeModelProvider_CreateChatClient_Tracon_ModelBinding_Tracon_ModelProviderCredential_"></a> CreateChatClient\(ModelBinding, ModelProviderCredential\)

Produces a raw chat client using a resolved tenant credential.

```csharp
public IChatClient CreateChatClient(ModelBinding binding, ModelProviderCredential credential)
```

#### Parameters

`binding` [ModelBinding](/api/tracon.modelbinding/)

The model binding.

`credential` [ModelProviderCredential](/api/tracon.modelprovidercredential/)

The non-null tenant credential.

#### Returns

 IChatClient

The provider-specific raw chat client.

#### Remarks

The implementation uses [ModelProviderCredential.ApiKey](/api/tracon.modelprovidercredential/#Tracon_ModelProviderCredential_ApiKey)
and, when present, [ModelProviderCredential.Endpoint](/api/tracon.modelprovidercredential/#Tracon_ModelProviderCredential_Endpoint).
The API key must never fall back to the setup-time key. An endpoint may
fall back to a setup-time endpoint when only the key is overridden.

### <a id="Tracon_Testing_FakeModelProvider_Dispose"></a> Dispose\(\)

```csharp
public void Dispose()
```

### <a id="Tracon_Testing_FakeModelProvider_EchoesLastToolResult_System_String_System_Nullable_System_Int32__System_Nullable_System_Int32__"></a> EchoesLastToolResult\(string, int?, int?\)

Starts echoing the LAST tool result in history once the queue is drained.

```csharp
public FakeModelProvider EchoesLastToolResult(string prefix = "", int? inputTokens = null, int? outputTokens = null)
```

#### Parameters

`prefix` [string](https://learn.microsoft.com/dotnet/api/system.string)

Text prepended to the result.

`inputTokens` [int](https://learn.microsoft.com/dotnet/api/system.int32)?

If given, the input token count reported with every response.

`outputTokens` [int](https://learn.microsoft.com/dotnet/api/system.int32)?

If given, the output token count reported with every response.

#### Returns

 [FakeModelProvider](/api/tracon.testing.fakemodelprovider/)

The chain, for continued configuration.

#### Remarks

For the last step of a tool chain (set up with [FakeModelProvider.CallsTool](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_CallsTool_System_String_System_Object_)),
where the final response must genuinely depend on the result the tool
returned — e.g. a hand-off result to a sub-agent.

### <a id="Tracon_Testing_FakeModelProvider_EchoesUserMessage"></a> EchoesUserMessage\(\)

Starts echoing the last incoming user message once the queue is drained.

```csharp
public FakeModelProvider EchoesUserMessage()
```

#### Returns

 [FakeModelProvider](/api/tracon.testing.fakemodelprovider/)

The chain, for continued configuration.

### <a id="Tracon_Testing_FakeModelProvider_ForModel_System_String_System_Action_Tracon_Testing_FakeModelProvider__"></a> ForModel\(string, Action<FakeModelProvider\>\)

Defines a separate response queue for a specific model name. Calls to
[FakeModelProvider.RespondsWith](/api/tracon.testing.fakemodelprovider/)/[FakeModelProvider.EchoesUserMessage](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_EchoesUserMessage)/[FakeModelProvider.CallsTool](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_CallsTool_System_String_System_Object_)
inside the `configure` body affect only that model's queue.

```csharp
public FakeModelProvider ForModel(string modelId, Action<FakeModelProvider> configure)
```

#### Parameters

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

`configure` [Action](https://learn.microsoft.com/dotnet/api/system.action\-1)<[FakeModelProvider](/api/tracon.testing.fakemodelprovider/)\>

Configuration that fills this model's queue.

#### Returns

 [FakeModelProvider](/api/tracon.testing.fakemodelprovider/)

The chain, for continued configuration.

### <a id="Tracon_Testing_FakeModelProvider_RespondsWith_System_String___"></a> RespondsWith\(params string\[\]\)

Enqueues responses to return in order. Once the queue is drained, a fixed
response is returned unless [FakeModelProvider.EchoesUserMessage](/api/tracon.testing.fakemodelprovider/#Tracon_Testing_FakeModelProvider_EchoesUserMessage) was set.

```csharp
public FakeModelProvider RespondsWith(params string[] responses)
```

#### Parameters

`responses` [string](https://learn.microsoft.com/dotnet/api/system.string)\[\]

Texts to return in order.

#### Returns

 [FakeModelProvider](/api/tracon.testing.fakemodelprovider/)

The chain, for continued configuration.

### <a id="Tracon_Testing_FakeModelProvider_RespondsWith_System_String_System_Int32_System_Int32_"></a> RespondsWith\(string, int, int\)

Enqueues a single text response that reports a specific token usage.

```csharp
public FakeModelProvider RespondsWith(string response, int inputTokens, int outputTokens)
```

#### Parameters

`response` [string](https://learn.microsoft.com/dotnet/api/system.string)

Text to return.

`inputTokens` [int](https://learn.microsoft.com/dotnet/api/system.int32)

Input token count to report.

`outputTokens` [int](https://learn.microsoft.com/dotnet/api/system.int32)

Output token count to report.

#### Returns

 [FakeModelProvider](/api/tracon.testing.fakemodelprovider/)

The chain, for continued configuration.

#### Remarks

For scenarios that test cost/usage metrics end to end.

### <a id="Tracon_Testing_FakeModelProvider_WithModel_Tracon_ModelDescriptor_"></a> WithModel\(ModelDescriptor\)

Registers a model on this provider.

```csharp
public FakeModelProvider WithModel(ModelDescriptor descriptor)
```

#### Parameters

`descriptor` [ModelDescriptor](/api/tracon.modeldescriptor/)

Model descriptor.

#### Returns

 [FakeModelProvider](/api/tracon.testing.fakemodelprovider/)

The chain, for continued configuration.
