diff --git a/dotnet/samples/02-agents/Harness/Harness_Step01_Research/Program.cs b/dotnet/samples/02-agents/Harness/Harness_Step01_Research/Program.cs
index 4c4010f0c0..a1d8aca1b8 100644
--- a/dotnet/samples/02-agents/Harness/Harness_Step01_Research/Program.cs
+++ b/dotnet/samples/02-agents/Harness/Harness_Step01_Research/Program.cs
@@ -79,8 +79,10 @@ AIAgent agent =
.GetProjectOpenAIClient()
.GetResponsesClient()
.AsIChatClient(deploymentName)
- .AsHarnessAgent(MaxContextWindowTokens, MaxOutputTokens, new HarnessAgentOptions
+ .AsHarnessAgent(new HarnessAgentOptions
{
+ MaxContextWindowTokens = MaxContextWindowTokens,
+ MaxOutputTokens = MaxOutputTokens,
Name = "ResearchAgent",
Description = "A research assistant that plans and executes research tasks.",
DisableFileAccess = true, // If enabled, this would allow the agent to read/write files in a working directory
diff --git a/dotnet/samples/02-agents/Harness/Harness_Step02_Research_WithBackgroundAgents/Program.cs b/dotnet/samples/02-agents/Harness/Harness_Step02_Research_WithBackgroundAgents/Program.cs
index e8e10a3620..654c169850 100644
--- a/dotnet/samples/02-agents/Harness/Harness_Step02_Research_WithBackgroundAgents/Program.cs
+++ b/dotnet/samples/02-agents/Harness/Harness_Step02_Research_WithBackgroundAgents/Program.cs
@@ -44,8 +44,10 @@ AIAgent webSearchAgent =
.GetProjectOpenAIClient()
.GetResponsesClient()
.AsIChatClient(deploymentName)
- .AsHarnessAgent(MaxContextWindowTokens, MaxOutputTokens, new HarnessAgentOptions
+ .AsHarnessAgent(new HarnessAgentOptions
{
+ MaxContextWindowTokens = MaxContextWindowTokens,
+ MaxOutputTokens = MaxOutputTokens,
Name = "WebSearchAgent",
Description = "An agent that can search the web to find information.",
OpenTelemetrySourceName = TracingSourceName,
@@ -92,8 +94,10 @@ AIAgent parentAgent =
.GetProjectOpenAIClient()
.GetResponsesClient()
.AsIChatClient(deploymentName)
- .AsHarnessAgent(MaxContextWindowTokens, MaxOutputTokens, new HarnessAgentOptions
+ .AsHarnessAgent(new HarnessAgentOptions
{
+ MaxContextWindowTokens = MaxContextWindowTokens,
+ MaxOutputTokens = MaxOutputTokens,
Name = "StockPriceResearcher",
Description = "An agent that researches stock prices using background agents.",
OpenTelemetrySourceName = TracingSourceName,
diff --git a/dotnet/samples/02-agents/Harness/Harness_Step03_DataProcessing/Program.cs b/dotnet/samples/02-agents/Harness/Harness_Step03_DataProcessing/Program.cs
index 5b8d388dc8..6b88d708f2 100644
--- a/dotnet/samples/02-agents/Harness/Harness_Step03_DataProcessing/Program.cs
+++ b/dotnet/samples/02-agents/Harness/Harness_Step03_DataProcessing/Program.cs
@@ -68,8 +68,10 @@ AIAgent agent =
.GetProjectOpenAIClient()
.GetResponsesClient()
.AsIChatClient(deploymentName)
- .AsHarnessAgent(MaxContextWindowTokens, MaxOutputTokens, new HarnessAgentOptions
+ .AsHarnessAgent(new HarnessAgentOptions
{
+ MaxContextWindowTokens = MaxContextWindowTokens,
+ MaxOutputTokens = MaxOutputTokens,
Name = "DataAnalyst",
Description = "A data analyst assistant that reads, analyzes, and processes data files.",
OpenTelemetrySourceName = TracingSourceName,
diff --git a/dotnet/samples/02-agents/Harness/Harness_Step04_CodeExecution/Program.cs b/dotnet/samples/02-agents/Harness/Harness_Step04_CodeExecution/Program.cs
index af53443c63..908e43abd7 100644
--- a/dotnet/samples/02-agents/Harness/Harness_Step04_CodeExecution/Program.cs
+++ b/dotnet/samples/02-agents/Harness/Harness_Step04_CodeExecution/Program.cs
@@ -89,8 +89,10 @@ AIAgent agent =
.GetProjectOpenAIClient()
.GetResponsesClient()
.AsIChatClient(deploymentName)
- .AsHarnessAgent(MaxContextWindowTokens, MaxOutputTokens, new HarnessAgentOptions
+ .AsHarnessAgent(new HarnessAgentOptions
{
+ MaxContextWindowTokens = MaxContextWindowTokens,
+ MaxOutputTokens = MaxOutputTokens,
Name = "CodeExecutionAgent",
Description = "A technical assistant with sandboxed code execution and skill-based workflows.",
OpenTelemetrySourceName = TracingSourceName,
diff --git a/dotnet/src/Microsoft.Agents.AI.Harness/ChatClientHarnessExtensions.cs b/dotnet/src/Microsoft.Agents.AI.Harness/ChatClientHarnessExtensions.cs
index be66e9e635..3d5f037b2f 100644
--- a/dotnet/src/Microsoft.Agents.AI.Harness/ChatClientHarnessExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Harness/ChatClientHarnessExtensions.cs
@@ -16,23 +16,16 @@ public static class ChatClientHarnessExtensions
{
///
/// Creates a new that wraps this with a pre-configured
- /// pipeline including function invocation, per-service-call chat history persistence, and in-loop compaction.
+ /// pipeline including function invocation, per-service-call chat history persistence, optional in-loop compaction, and a rich set
+ /// of default context providers and agent decorators.
///
///
/// The that provides access to the underlying AI model.
///
- ///
- /// The maximum number of tokens the model's context window supports (e.g., 1,050,000 for gpt-5.4).
- /// Used to configure the compaction strategy.
- ///
- ///
- /// The maximum number of output tokens the model can generate per response (e.g., 128,000 for gpt-5.4).
- /// Used to configure the compaction strategy.
- ///
///
/// Optional configuration options for the agent, including instructions override, tools,
- /// additional context providers, and chat history provider.
- /// When , the agent uses built-in default settings.
+ /// additional context providers, chat history provider, and compaction settings.
+ /// When , the agent uses built-in default settings with compaction disabled.
///
///
/// Optional logger factory for creating loggers used by the agent and its components.
@@ -43,10 +36,8 @@ public static class ChatClientHarnessExtensions
/// A new instance.
public static HarnessAgent AsHarnessAgent(
this IChatClient chatClient,
- int maxContextWindowTokens,
- int maxOutputTokens,
HarnessAgentOptions? options = null,
ILoggerFactory? loggerFactory = null,
IServiceProvider? services = null) =>
- new(chatClient, maxContextWindowTokens, maxOutputTokens, options, loggerFactory, services);
+ new(chatClient, options, loggerFactory, services);
}
diff --git a/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgent.cs b/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgent.cs
index 6960b755ec..d6bc16d354 100644
--- a/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgent.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgent.cs
@@ -18,50 +18,65 @@ namespace Microsoft.Agents.AI;
///
/// A pre-configured that wraps a with
-/// function invocation, per-service-call chat history persistence, in-loop compaction, and a rich set
+/// function invocation, per-service-call chat history persistence, optional in-loop compaction, and a rich set
/// of default context providers and agent decorators.
///
///
///
-/// assembles the following pipeline from a caller-supplied :
+/// provides an opinionated, batteries-included agent suitable for
+/// interactive agentic scenarios such as research, coding, data analysis, and general task automation.
+/// It assembles a full pipeline from a caller-supplied so that callers
+/// only need to configure the parts they want to customize.
+///
+///
+/// Chat client pipeline (inner to outer):
///
-/// - — automatic function/tool invocation.
-/// - — allows external code to inject messages into the conversation mid-stream.
-/// - — persists chat history after every individual service call within a function-invocation loop.
-/// - with a — applies context-window compaction before each call so long function-invocation loops do not overflow the context window.
+/// - — automatic function/tool invocation with configurable iteration limits.
+/// - — allows external code to inject messages into the conversation mid-stream (e.g., for user interrupts).
+/// - — persists chat history after every individual service call within a function-invocation loop, enabling crash recovery and history inspection.
+/// - with a — applies context-window compaction before each call so long function-invocation loops do not overflow the context window. Only included when and are both provided.
///
///
///
-/// By default, the following context providers are included (each can be disabled via ):
+/// Context providers (each enabled by default, individually disableable via ):
///
-/// - — todo list management.
-/// - — agent mode tracking (plan/execute).
-/// - — file-based session memory.
-/// - — shared file access.
-/// - — skill discovery and loading.
+/// - — persistent todo list that the agent uses to track multi-step plans. Disable with .
+/// - — mode tracking (e.g., "plan" vs "execute") that the agent uses to structure its work. Disable with .
+/// - — file-based session memory allowing the agent to persist notes and artifacts across turns. Disable with .
+/// - — shared file access providing read/write tools for a working directory. Disable with .
+/// - — discovers and loads skill definitions from the file system, enabling dynamic tool sets. Disable with .
///
///
///
-/// The agent is also wrapped with the following decorators by default (each can be disabled):
+/// Optional context providers (enabled via ):
///
-/// - — "don't ask again" tool approval rules.
-/// - — OpenTelemetry instrumentation.
+/// - — enables delegation to background agents for parallel work. Enable by setting .
+/// - ShellEnvironmentProvider — injects OS/shell/CWD information and a shell execution tool. Enable by setting HarnessAgentOptions.ShellExecutor (.NET only).
///
///
///
-/// A is added to the chat options by default (can be disabled via
-/// ).
+/// Agent decorators (each enabled by default, individually disableable):
+///
+/// - — "don't ask again" tool approval rules enabling safe unattended execution. Disable with .
+/// - — OpenTelemetry instrumentation following semantic conventions for generative AI. Disable with .
+///
///
///
-/// The underlying is configured with
-/// and
-/// set to
-/// to match the manually-assembled pipeline.
+/// Default tools:
+///
+/// - — a hosted web search tool added to chat options by default. Disable with .
+///
///
///
-/// When no is supplied, the agent defaults to an
-/// whose chat reducer applies the same compaction strategy,
-/// keeping in-memory history from growing unboundedly across sessions.
+/// Chat history: When no is supplied,
+/// the agent defaults to an . If compaction is enabled, the provider
+/// is configured with a compaction-based chat reducer to keep in-memory history bounded. Otherwise, no reducer
+/// is applied.
+///
+///
+/// Default instructions: The agent includes built-in system instructions ()
+/// that guide general tool usage and reasoning patterns. These can be overridden via
+/// and combined with agent-specific instructions via .
///
///
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
@@ -90,21 +105,13 @@ public sealed class HarnessAgent : DelegatingAIAgent
///
///
/// The that provides access to the underlying AI model.
- /// The agent wraps this client in a function-invocation, per-service-call persistence,
- /// and compaction pipeline automatically.
- ///
- ///
- /// The maximum number of tokens the model's context window supports (e.g., 1,050,000 for gpt-5.4).
- /// Used to configure the compaction strategy.
- ///
- ///
- /// The maximum number of output tokens the model can generate per response (e.g., 128,000 for gpt-5.4).
- /// Used to configure the compaction strategy and to limit the model's output.
+ /// The agent wraps this client in a function-invocation and per-service-call persistence pipeline.
+ /// When compaction is enabled via , a compaction decorator is also added.
///
///
/// Optional configuration options for the agent, including instructions override, tools,
- /// additional context providers, and chat history provider.
- /// When , the agent uses built-in default settings.
+ /// additional context providers, chat history provider, and compaction settings.
+ /// When , the agent uses built-in default settings with compaction disabled.
///
///
/// Optional logger factory for creating loggers used by the agent and its components.
@@ -116,23 +123,22 @@ public sealed class HarnessAgent : DelegatingAIAgent
/// is .
///
///
- /// is not positive, or
- /// is negative or greater than or equal to .
+ /// is not positive, or
+ /// is negative or greater than or equal to
+ /// (when both are provided).
///
- public HarnessAgent(IChatClient chatClient, int maxContextWindowTokens, int maxOutputTokens, HarnessAgentOptions? options = null, ILoggerFactory? loggerFactory = null, IServiceProvider? services = null)
+ public HarnessAgent(IChatClient chatClient, HarnessAgentOptions? options = null, ILoggerFactory? loggerFactory = null, IServiceProvider? services = null)
: base(BuildAgent(
Throw.IfNull(chatClient),
- maxContextWindowTokens,
- maxOutputTokens,
options,
loggerFactory,
services))
{
}
- private static AIAgent BuildAgent(IChatClient chatClient, int maxContextWindowTokens, int maxOutputTokens, HarnessAgentOptions? options, ILoggerFactory? loggerFactory, IServiceProvider? services)
+ private static AIAgent BuildAgent(IChatClient chatClient, HarnessAgentOptions? options, ILoggerFactory? loggerFactory, IServiceProvider? services)
{
- ChatClientAgent innerAgent = BuildInnerAgent(chatClient, maxContextWindowTokens, maxOutputTokens, options, loggerFactory, services);
+ ChatClientAgent innerAgent = BuildInnerAgent(chatClient, options, loggerFactory, services);
AIAgentBuilder builder = innerAgent.AsBuilder();
@@ -149,17 +155,35 @@ public sealed class HarnessAgent : DelegatingAIAgent
return builder.Build(services);
}
- private static ChatClientAgent BuildInnerAgent(IChatClient chatClient, int maxContextWindowTokens, int maxOutputTokens, HarnessAgentOptions? options, ILoggerFactory? loggerFactory, IServiceProvider? services)
+ private static ChatClientAgent BuildInnerAgent(IChatClient chatClient, HarnessAgentOptions? options, ILoggerFactory? loggerFactory, IServiceProvider? services)
{
- var compactionStrategy = new ContextWindowCompactionStrategy(
- maxContextWindowTokens: maxContextWindowTokens,
- maxOutputTokens: maxOutputTokens);
+ // Determine compaction strategy:
+ // 1. DisableCompaction = true → no compaction
+ // 2. Custom CompactionStrategy provided → use it (ignore token params)
+ // 3. Both token params provided → build default ContextWindowCompactionStrategy
+ // 4. Otherwise → no compaction
+ CompactionStrategy? compactionStrategy = null;
+ if (options?.DisableCompaction is not true)
+ {
+ if (options?.CompactionStrategy is CompactionStrategy customStrategy)
+ {
+ compactionStrategy = customStrategy;
+ }
+ else if (options?.MaxContextWindowTokens is int maxCtx && options?.MaxOutputTokens is int maxOut)
+ {
+ compactionStrategy = new ContextWindowCompactionStrategy(
+ maxContextWindowTokens: maxCtx,
+ maxOutputTokens: maxOut);
+ }
+ }
ChatHistoryProvider chatHistoryProvider = options?.ChatHistoryProvider
- ?? new InMemoryChatHistoryProvider(new InMemoryChatHistoryProviderOptions
- {
- ChatReducer = compactionStrategy.AsChatReducer(),
- });
+ ?? (compactionStrategy is not null
+ ? new InMemoryChatHistoryProvider(new InMemoryChatHistoryProviderOptions
+ {
+ ChatReducer = compactionStrategy.AsChatReducer(),
+ })
+ : new InMemoryChatHistoryProvider());
string harnessInstructions = options?.HarnessInstructions ?? DefaultInstructions;
string? agentInstructions = options?.ChatOptions?.Instructions;
@@ -172,9 +196,11 @@ public sealed class HarnessAgent : DelegatingAIAgent
(false, false) => $"{harnessInstructions}\n\n{agentInstructions}",
};
- ChatOptions chatOptions = BuildChatOptions(options, instructions, maxOutputTokens);
+ ChatOptions chatOptions = BuildChatOptions(options, instructions, options?.MaxOutputTokens);
- var compactionProvider = new CompactionProvider(compactionStrategy, loggerFactory: loggerFactory);
+ CompactionProvider? compactionProvider = compactionStrategy is not null
+ ? new CompactionProvider(compactionStrategy, loggerFactory: loggerFactory)
+ : null;
IEnumerable contextProviders = BuildContextProviders(options, loggerFactory);
@@ -185,13 +211,19 @@ public sealed class HarnessAgent : DelegatingAIAgent
chatClientBuilder.UseNonApprovalRequiredFunctionBypassing();
}
- return chatClientBuilder
+ ChatClientBuilder pipeline = chatClientBuilder
.UseFunctionInvocation(loggerFactory, configure: options?.MaximumIterationsPerRequest is int maxIterations
? ficc => ficc.MaximumIterationsPerRequest = maxIterations
: null)
.UseMessageInjection()
- .UsePerServiceCallChatHistoryPersistence()
- .UseAIContextProviders(compactionProvider)
+ .UsePerServiceCallChatHistoryPersistence();
+
+ if (compactionProvider is not null)
+ {
+ pipeline = pipeline.UseAIContextProviders(compactionProvider);
+ }
+
+ return pipeline
.BuildAIAgent(new ChatClientAgentOptions
{
Id = options?.Id,
@@ -209,11 +241,15 @@ public sealed class HarnessAgent : DelegatingAIAgent
services);
}
- private static ChatOptions BuildChatOptions(HarnessAgentOptions? options, string instructions, int maxOutputTokens)
+ private static ChatOptions BuildChatOptions(HarnessAgentOptions? options, string instructions, int? maxOutputTokens)
{
ChatOptions result = options?.ChatOptions?.Clone() ?? new ChatOptions();
result.Instructions = instructions;
- result.MaxOutputTokens ??= maxOutputTokens;
+
+ if (maxOutputTokens.HasValue)
+ {
+ result.MaxOutputTokens ??= maxOutputTokens.Value;
+ }
if (options?.DisableWebSearch is not true)
{
diff --git a/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgentOptions.cs b/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgentOptions.cs
index 85924b7c3e..291650b9b9 100644
--- a/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgentOptions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Harness/HarnessAgentOptions.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+using Microsoft.Agents.AI.Compaction;
#if NET
using Microsoft.Agents.AI.Tools.Shell;
#endif
@@ -31,6 +32,68 @@ public sealed class HarnessAgentOptions
///
public string? Description { get; set; }
+ ///
+ /// Gets or sets the maximum number of tokens the model's context window supports (e.g., 1,050,000 for gpt-5.4).
+ ///
+ ///
+ ///
+ /// When both and are provided (and no
+ /// custom is set), a default
+ /// is constructed from these values to prevent function-invocation loops from overflowing the context window.
+ ///
+ ///
+ /// Ignored when is provided or when is
+ /// .
+ ///
+ ///
+ public int? MaxContextWindowTokens { get; set; }
+
+ ///
+ /// Gets or sets the maximum number of output tokens the model can generate per response (e.g., 128,000 for gpt-5.4).
+ ///
+ ///
+ ///
+ /// When set, this value is used as the default for .
+ /// when not explicitly configured.
+ ///
+ ///
+ /// For compaction purposes, this value is used together with to construct a
+ /// default — but only when no custom
+ /// is provided and is .
+ ///
+ ///
+ public int? MaxOutputTokens { get; set; }
+
+ ///
+ /// Gets or sets a custom to use for in-loop context-window compaction.
+ ///
+ ///
+ ///
+ /// When provided, this strategy is used directly and and
+ /// are ignored for compaction purposes ( is still
+ /// used as the default for . if set).
+ ///
+ ///
+ /// When and both and
+ /// are provided, a default is constructed from those values.
+ ///
+ ///
+ /// This property is ignored when is .
+ ///
+ ///
+ public CompactionStrategy? CompactionStrategy { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether in-loop compaction is disabled.
+ ///
+ ///
+ /// When , compaction is disabled regardless of ,
+ /// , or settings. No
+ /// is added to the chat client pipeline, and the default
+ /// is configured without a chat reducer.
+ ///
+ public bool DisableCompaction { get; set; }
+
///
/// Gets or sets additional chat options such as tools for the agent to use.
///
@@ -68,9 +131,9 @@ public sealed class HarnessAgentOptions
/// Gets or sets the to use for storing chat history.
///
///
- /// When , the agent defaults to an
- /// configured with a compaction-based chat reducer derived from the maxContextWindowTokens
- /// and maxOutputTokens constructor parameters of .
+ /// When , the agent defaults to an .
+ /// If and are both provided,
+ /// the default provider is configured with a compaction-based chat reducer; otherwise, no reducer is applied.
///
public ChatHistoryProvider? ChatHistoryProvider { get; set; }
diff --git a/dotnet/tests/Microsoft.Agents.AI.Harness.UnitTests/HarnessAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.Harness.UnitTests/HarnessAgentTests.cs
index f7977b595f..a6b06d2a10 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Harness.UnitTests/HarnessAgentTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Harness.UnitTests/HarnessAgentTests.cs
@@ -21,9 +21,12 @@ public class HarnessAgentTests
///
/// Creates a HarnessAgent with all default features disabled to isolate tests for specific behaviors.
+ /// Compaction is enabled by default for backward compatibility with existing tests.
///
private static HarnessAgentOptions CreateAllDisabledOptions() => new()
{
+ MaxContextWindowTokens = TestMaxContextWindowTokens,
+ MaxOutputTokens = TestMaxOutputTokens,
DisableToolApproval = true,
DisableOpenTelemetry = true,
DisableFileMemory = true,
@@ -43,7 +46,7 @@ public class HarnessAgentTests
public void Constructor_ThrowsWhenChatClientIsNull()
{
// Act & Assert
- Assert.Throws(() => new HarnessAgent(null!, TestMaxContextWindowTokens, TestMaxOutputTokens));
+ Assert.Throws(() => new HarnessAgent(null!));
}
///
@@ -54,9 +57,10 @@ public class HarnessAgentTests
{
// Arrange
var chatClient = new Mock().Object;
+ var options = new HarnessAgentOptions { MaxContextWindowTokens = 0, MaxOutputTokens = TestMaxOutputTokens };
// Act & Assert
- Assert.Throws(() => new HarnessAgent(chatClient, 0, TestMaxOutputTokens));
+ Assert.Throws(() => new HarnessAgent(chatClient, options));
}
///
@@ -67,9 +71,10 @@ public class HarnessAgentTests
{
// Arrange
var chatClient = new Mock().Object;
+ var options = new HarnessAgentOptions { MaxContextWindowTokens = 100_000, MaxOutputTokens = 100_000 };
// Act & Assert
- Assert.Throws(() => new HarnessAgent(chatClient, 100_000, 100_000));
+ Assert.Throws(() => new HarnessAgent(chatClient, options));
}
///
@@ -82,7 +87,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens);
+ var agent = new HarnessAgent(chatClient);
// Assert
Assert.NotNull(agent);
@@ -105,7 +110,7 @@ public class HarnessAgentTests
options.Description = "A test agent";
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
// Assert
Assert.Equal("TestAgent", agent.Name);
@@ -124,7 +129,7 @@ public class HarnessAgentTests
options.Id = "my-agent-id";
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
// Assert
Assert.Equal("my-agent-id", agent.Id);
@@ -144,7 +149,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert
@@ -164,7 +169,7 @@ public class HarnessAgentTests
options.ChatOptions = new ChatOptions { Temperature = 0.5f };
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -184,7 +189,7 @@ public class HarnessAgentTests
options.ChatOptions = new ChatOptions { Instructions = "You are a custom assistant." };
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -205,7 +210,7 @@ public class HarnessAgentTests
options.HarnessInstructions = "Custom harness rules.";
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -226,7 +231,7 @@ public class HarnessAgentTests
options.ChatOptions = new ChatOptions { Instructions = "You are a research agent." };
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -247,7 +252,7 @@ public class HarnessAgentTests
options.ChatOptions = new ChatOptions { Instructions = "Agent only instructions." };
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -267,7 +272,7 @@ public class HarnessAgentTests
options.HarnessInstructions = string.Empty;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -289,7 +294,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert
@@ -310,7 +315,7 @@ public class HarnessAgentTests
options.ChatHistoryProvider = customProvider;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -332,7 +337,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert
@@ -353,7 +358,7 @@ public class HarnessAgentTests
var rawClient = mockClient.Object;
// Act
- var agent = new HarnessAgent(rawClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(rawClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert — the pipeline wraps the raw client, so the outer client is not the same object.
@@ -378,7 +383,7 @@ public class HarnessAgentTests
options.AIContextProviders = [customProvider];
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert — the custom provider should appear in the inner agent's AIContextProviders.
@@ -398,7 +403,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert
@@ -432,7 +437,7 @@ public class HarnessAgentTests
var options = CreateAllDisabledOptions();
options.ChatOptions = new ChatOptions { Tools = [tool] };
- var agent = new HarnessAgent(mockClient.Object, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(mockClient.Object, options);
var session = await agent.CreateSessionAsync();
// Act
@@ -459,8 +464,10 @@ public class HarnessAgentTests
};
// Act
- _ = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, new HarnessAgentOptions
+ _ = new HarnessAgent(chatClient, new HarnessAgentOptions
{
+ MaxContextWindowTokens = TestMaxContextWindowTokens,
+ MaxOutputTokens = TestMaxOutputTokens,
ChatOptions = sourceChatOptions,
});
@@ -483,7 +490,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
// Assert
Assert.Same(agent, agent.GetService());
@@ -499,7 +506,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
// Assert
Assert.NotNull(agent.GetService());
@@ -524,7 +531,7 @@ public class HarnessAgentTests
It.IsAny()))
.ReturnsAsync(new ChatResponse(new ChatMessage(ChatRole.Assistant, "Hello!")));
- var agent = new HarnessAgent(mockClient.Object, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(mockClient.Object, CreateAllDisabledOptions());
var session = await agent.CreateSessionAsync();
// Act
@@ -565,7 +572,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = chatClient.AsHarnessAgent(TestMaxContextWindowTokens, TestMaxOutputTokens);
+ var agent = chatClient.AsHarnessAgent();
// Assert
Assert.NotNull(agent);
@@ -586,7 +593,7 @@ public class HarnessAgentTests
options.ChatOptions = new ChatOptions { Instructions = "Custom instructions" };
// Act
- var agent = chatClient.AsHarnessAgent(TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = chatClient.AsHarnessAgent(options);
var innerAgent = agent.GetService();
// Assert
@@ -603,7 +610,7 @@ public class HarnessAgentTests
public void AsHarnessAgent_ThrowsWhenChatClientIsNull()
{
// Act & Assert
- Assert.Throws(() => ((IChatClient)null!).AsHarnessAgent(TestMaxContextWindowTokens, TestMaxOutputTokens));
+ Assert.Throws(() => ((IChatClient)null!).AsHarnessAgent());
}
#endregion
@@ -622,7 +629,7 @@ public class HarnessAgentTests
options.DisableToolApproval = false;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
// Assert
Assert.NotNull(agent.GetService());
@@ -638,7 +645,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
// Assert
Assert.Null(agent.GetService());
@@ -678,7 +685,7 @@ public class HarnessAgentTests
AutoApprovalRules = [fcc => new ValueTask(fcc.Name == "ReadTool")]
};
- var agent = new HarnessAgent(mockClient.Object, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(mockClient.Object, options);
var session = await agent.CreateSessionAsync();
// Act
@@ -721,7 +728,7 @@ public class HarnessAgentTests
var options = CreateAllDisabledOptions();
options.ChatOptions = new ChatOptions { Tools = [normalTool, approvalTool] };
- var agent = new HarnessAgent(mockClient.Object, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(mockClient.Object, options);
var session = await agent.CreateSessionAsync();
// Act
@@ -763,7 +770,7 @@ public class HarnessAgentTests
options.DisableNonApprovalRequiredFunctionBypassing = true;
options.ChatOptions = new ChatOptions { Tools = [normalTool, approvalTool] };
- var agent = new HarnessAgent(mockClient.Object, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(mockClient.Object, options);
var session = await agent.CreateSessionAsync();
// Act
@@ -796,7 +803,7 @@ public class HarnessAgentTests
options.DisableOpenTelemetry = false;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
// Assert
Assert.NotNull(agent.GetService());
@@ -812,7 +819,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
// Assert
Assert.Null(agent.GetService());
@@ -831,7 +838,7 @@ public class HarnessAgentTests
options.OpenTelemetrySourceName = "MyApp.AgentTracing";
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
// Assert
Assert.NotNull(agent.GetService());
@@ -858,7 +865,7 @@ public class HarnessAgentTests
var options = CreateAllDisabledOptions();
options.DisableWebSearch = false;
- var agent = new HarnessAgent(mockClient.Object, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(mockClient.Object, options);
var session = await agent.CreateSessionAsync();
// Act
@@ -883,7 +890,7 @@ public class HarnessAgentTests
.Callback, ChatOptions?, CancellationToken>((_, opts, _) => capturedOptions = opts)
.ReturnsAsync(new ChatResponse(new ChatMessage(ChatRole.Assistant, "Done")));
- var agent = new HarnessAgent(mockClient.Object, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(mockClient.Object, CreateAllDisabledOptions());
var session = await agent.CreateSessionAsync();
// Act
@@ -916,7 +923,7 @@ public class HarnessAgentTests
options.DisableWebSearch = false;
options.ChatOptions = new ChatOptions { Tools = [userTool] };
- var agent = new HarnessAgent(mockClient.Object, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(mockClient.Object, options);
var session = await agent.CreateSessionAsync();
// Act
@@ -944,7 +951,7 @@ public class HarnessAgentTests
options.DisableTodoProvider = false;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -962,7 +969,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert
@@ -989,7 +996,7 @@ public class HarnessAgentTests
options.DisableAgentModeProvider = false;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -1007,7 +1014,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert
@@ -1038,7 +1045,7 @@ public class HarnessAgentTests
};
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert — AgentModeProvider should be present (we can't easily inspect its internal options,
@@ -1063,7 +1070,7 @@ public class HarnessAgentTests
options.DisableFileMemory = false;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -1081,7 +1088,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert
@@ -1106,7 +1113,7 @@ public class HarnessAgentTests
options.FileMemoryStore = customStore;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert — FileMemoryProvider should be present with the custom store.
@@ -1130,7 +1137,7 @@ public class HarnessAgentTests
options.DisableFileAccess = false;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -1148,7 +1155,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert
@@ -1173,7 +1180,7 @@ public class HarnessAgentTests
options.FileAccessStore = customStore;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert — FileAccessProvider should be present with the custom store.
@@ -1197,7 +1204,7 @@ public class HarnessAgentTests
options.DisableAgentSkillsProvider = false;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -1215,7 +1222,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
// Assert
@@ -1240,7 +1247,7 @@ public class HarnessAgentTests
options.AgentSkillsSource = customSource;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert — AgentSkillsProvider should be present.
@@ -1264,7 +1271,7 @@ public class HarnessAgentTests
options.MaximumIterationsPerRequest = 42;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
var ficc = innerAgent!.ChatClient.GetService();
@@ -1283,7 +1290,7 @@ public class HarnessAgentTests
var chatClient = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions());
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
var innerAgent = agent.GetService();
var ficc = innerAgent!.ChatClient.GetService();
@@ -1311,7 +1318,7 @@ public class HarnessAgentTests
.ReturnsAsync(new ChatResponse(new ChatMessage(ChatRole.Assistant, "Done")));
// Act
- var agent = new HarnessAgent(mockClient.Object, TestMaxContextWindowTokens, TestMaxOutputTokens);
+ var agent = new HarnessAgent(mockClient.Object);
var innerAgent = agent.GetService();
// Assert — agent wrappers
@@ -1354,7 +1361,7 @@ public class HarnessAgentTests
options.BackgroundAgents = [bgAgentMock.Object];
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -1374,7 +1381,7 @@ public class HarnessAgentTests
options.BackgroundAgents = null;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -1397,7 +1404,7 @@ public class HarnessAgentTests
options.BackgroundAgents = Array.Empty();
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -1428,7 +1435,7 @@ public class HarnessAgentTests
options.BackgroundAgentsProviderOptions = providerOptions;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
var bgProvider = innerAgent!.AIContextProviders!.OfType().Single();
@@ -1465,7 +1472,7 @@ public class HarnessAgentTests
options.BackgroundAgents = [agent1Mock.Object, agent2Mock.Object];
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
var bgProvider = innerAgent!.AIContextProviders!.OfType().Single();
@@ -1506,7 +1513,7 @@ public class HarnessAgentTests
options.ShellExecutor = executorMock.Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -1526,7 +1533,7 @@ public class HarnessAgentTests
options.ShellExecutor = null;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert
@@ -1558,7 +1565,7 @@ public class HarnessAgentTests
options.ShellExecutor = executorMock.Object;
// Act
- var agent = new HarnessAgent(chatClientMock.Object, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClientMock.Object, options);
var session = await agent.CreateSessionAsync();
await agent.RunAsync([new ChatMessage(ChatRole.User, "Hi")], session);
@@ -1587,7 +1594,7 @@ public class HarnessAgentTests
options.ShellEnvironmentProviderOptions = envOptions;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options);
+ var agent = new HarnessAgent(chatClient, options);
var innerAgent = agent.GetService();
// Assert — provider should exist (options wiring is validated by the provider's behavior)
@@ -1611,7 +1618,7 @@ public class HarnessAgentTests
var loggerFactory = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions(), loggerFactory);
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions(), loggerFactory);
// Assert
Assert.NotNull(agent);
@@ -1628,7 +1635,7 @@ public class HarnessAgentTests
var services = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions(), services: services);
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions(), services: services);
// Assert
Assert.NotNull(agent);
@@ -1646,7 +1653,7 @@ public class HarnessAgentTests
var services = new Mock().Object;
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions(), loggerFactory, services);
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions(), loggerFactory, services);
// Assert
Assert.NotNull(agent);
@@ -1664,7 +1671,7 @@ public class HarnessAgentTests
var services = new Mock().Object;
// Act
- var agent = chatClient.AsHarnessAgent(TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions(), loggerFactory, services);
+ var agent = chatClient.AsHarnessAgent(CreateAllDisabledOptions(), loggerFactory, services);
// Assert
Assert.NotNull(agent);
@@ -1686,6 +1693,8 @@ public class HarnessAgentTests
// Act — use options that leave CompactionProvider and AgentSkillsProvider enabled
var options = new HarnessAgentOptions
{
+ MaxContextWindowTokens = TestMaxContextWindowTokens,
+ MaxOutputTokens = TestMaxOutputTokens,
DisableToolApproval = true,
DisableOpenTelemetry = true,
DisableFileMemory = true,
@@ -1694,7 +1703,7 @@ public class HarnessAgentTests
DisableTodoProvider = true,
DisableAgentModeProvider = true,
};
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, options, mockLoggerFactory.Object);
+ var agent = new HarnessAgent(chatClient, options, mockLoggerFactory.Object);
// Assert — CreateLogger should have been called by one or more downstream components
Assert.NotNull(agent);
@@ -1716,7 +1725,7 @@ public class HarnessAgentTests
.Returns(null!);
// Act
- var agent = new HarnessAgent(chatClient, TestMaxContextWindowTokens, TestMaxOutputTokens, CreateAllDisabledOptions(), services: mockServices.Object);
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions(), services: mockServices.Object);
// Assert — the service provider should have been queried during pipeline construction
Assert.NotNull(agent);
@@ -1724,4 +1733,91 @@ public class HarnessAgentTests
}
#endregion
+
+ #region Compaction Opt-in
+
+ ///
+ /// Verify that constructing without token values succeeds (compaction disabled).
+ ///
+ [Fact]
+ public void Constructor_SucceedsWithoutTokenValues()
+ {
+ // Arrange
+ var chatClient = new Mock().Object;
+ var options = new HarnessAgentOptions
+ {
+ DisableToolApproval = true,
+ DisableOpenTelemetry = true,
+ DisableFileMemory = true,
+ DisableFileAccess = true,
+ DisableWebSearch = true,
+ DisableTodoProvider = true,
+ DisableAgentModeProvider = true,
+ DisableAgentSkillsProvider = true,
+ };
+
+ // Act
+ var agent = new HarnessAgent(chatClient, options);
+
+ // Assert — compaction should be disabled (no chat reducer)
+ var innerAgent = agent.GetService();
+ Assert.NotNull(innerAgent);
+ var historyProvider = innerAgent!.ChatHistoryProvider as InMemoryChatHistoryProvider;
+ Assert.NotNull(historyProvider);
+ Assert.Null(historyProvider!.ChatReducer);
+ }
+
+ ///
+ /// Verify that when only MaxContextWindowTokens is provided (no MaxOutputTokens), compaction is disabled.
+ ///
+ [Fact]
+ public void Constructor_SucceedsWithOnlyMaxContextWindowTokens()
+ {
+ // Arrange
+ var chatClient = new Mock().Object;
+ var options = new HarnessAgentOptions
+ {
+ MaxContextWindowTokens = TestMaxContextWindowTokens,
+ DisableToolApproval = true,
+ DisableOpenTelemetry = true,
+ DisableFileMemory = true,
+ DisableFileAccess = true,
+ DisableWebSearch = true,
+ DisableTodoProvider = true,
+ DisableAgentModeProvider = true,
+ DisableAgentSkillsProvider = true,
+ };
+
+ // Act
+ var agent = new HarnessAgent(chatClient, options);
+
+ // Assert — compaction should be disabled (only one token value provided)
+ var innerAgent = agent.GetService();
+ Assert.NotNull(innerAgent);
+ var historyProvider = innerAgent!.ChatHistoryProvider as InMemoryChatHistoryProvider;
+ Assert.NotNull(historyProvider);
+ Assert.Null(historyProvider!.ChatReducer);
+ }
+
+ ///
+ /// Verify that when both token values are provided, the agent is constructed successfully with compaction.
+ ///
+ [Fact]
+ public void Constructor_SucceedsWithBothTokenValues()
+ {
+ // Arrange
+ var chatClient = new Mock().Object;
+
+ // Act
+ var agent = new HarnessAgent(chatClient, CreateAllDisabledOptions());
+
+ // Assert — compaction should be enabled (chat reducer configured)
+ var innerAgent = agent.GetService();
+ Assert.NotNull(innerAgent);
+ var historyProvider = innerAgent!.ChatHistoryProvider as InMemoryChatHistoryProvider;
+ Assert.NotNull(historyProvider);
+ Assert.NotNull(historyProvider!.ChatReducer);
+ }
+
+ #endregion
}