Skip to content
Tracon

AgentExtensionContext

Namespace Tracon · Assembly Tracon.Core.dll

The agent an IAgentExtension is configuring: the definition, the tenant, the one options object the compiler is about to build the agent from, and the wrappers and chat client rings the extension adds.

public sealed class AgentExtensionContext
Inheritance
object ← AgentExtensionContext
Inherited Members
object.GetType(), object.ToString(), object.Equals(object?), object.Equals(object?, object?), object.ReferenceEquals(object?, object?), object.GetHashCode()

Exactly one of AgentExtensionContext.ChatAgentOptions and AgentExtensionContext.HarnessAgentOptions is set. It is the one the agent’s kind selects: a definition with AgentDefinition.Harness is a harness agent. Change the options object in place; do not keep it. The compiler reads it once after the last extension has run.

Gets the options of a chat agent, or null when the agent is a harness agent.

public ChatClientAgentOptions? ChatAgentOptions { get; }

ChatClientAgentOptions?

Gets the definition the agent is compiled from. Changing a copy of it has no effect.

public AgentDefinition Definition { get; }

AgentDefinition

Gets the options of a harness agent, or null when the agent is a chat agent.

public HarnessAgentOptions? HarnessAgentOptions { get; }

HarnessAgentOptions?

Gets the application’s root service provider. A scoped service is not available here: the compiled agent outlives the request that compiled it.

public IServiceProvider Services { get; }

IServiceProvider

Gets the tenant the agent is compiled for.

public string TenantId { get; }

string

Adds a wrapper that is put around the compiled agent. A Microsoft Agent Framework middleware (AIAgentBuilder.Use) belongs here.

public void Use(Func<AIAgent, AIAgent> wrap)

wrap Func<AIAgent, AIAgent>

Receives the agent and returns the agent that replaces it.

A wrapper sits innermost: Tracon’s own wrappers and the catalog’s decorators (run recording, budget, tool approval) stay outside it. With several wrappers the first one added is the innermost.

A wrapper is not checked. It sees what the model call sees and can change it; that is what a middleware is for.

ArgumentNullException

wrap is null.

UseChatClient(ChatClientSlot, Func<IChatClient, IChatClient>)

Section titled “ UseChatClient(ChatClientSlot, Func<IChatClient, IChatClient>)”

Adds a ring to the agent’s model pipeline in the given slot. A Microsoft.Extensions.AI AI.DelegatingChatClient belongs here, for example a client that the framework documents as one that sees every model call.

public void UseChatClient(ChatClientSlot slot, Func<IChatClient, IChatClient> ring)

slot ChatClientSlot

Where the ring sits in the pipeline.

ring Func<IChatClient, IChatClient>

Receives the client below the ring and returns the ring.

The agent keeps every Tracon ring around the one you add: the content guard, the run budget, the response cache and the chat span stay below it, and the circuit breaker, the fallback chain and error normalization stay above it. A fallback link that answers in place of the agent’s model gets the same ring. The compaction summarizer and the judge of a loop criterion do not.

With several rings in one slot the first one added is the innermost, as with AgentExtensionContext.Use. A ring is not checked. It sees what the model call sees and can change it. The content guard still inspects the user, assistant and tool messages that it sends. The guard does not inspect a system message or ChatOptions.Instructions, and the ring receives the response after the guard has inspected it.

ring runs each time the pipeline is built: when the agent is compiled, and when a fallback link is first used. Keep it cheap and keep state that belongs to one run out of it. Derive the ring from AI.DelegatingChatClient: a ChatClientSlot.Turn ring that hides the tool-call loop below it from IChatClient.GetService fails the compilation.

An exception that the ring throws while it serves a call is the host’s own. It is not counted by the circuit breaker and not masked as a provider failure, as with a wrapper added by AgentExtensionContext.Use. A provider failure that passes up through the ring is still both.

builder.AddTracon()
.AddAgentExtension(
"model-call-log",
context => context.UseChatClient(
ChatClientSlot.ModelCall,
inner => new ModelCallLogChatClient(inner)));

ArgumentNullException

ring is null.

ArgumentOutOfRangeException

slot is not a defined value.