mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Make Todo, Mode and FileMemory providers more configurable (#5477)
* Make Todo, Mode and FileMemory providers more configurable * Address PR comments.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.AI;
|
||||
@@ -21,10 +22,15 @@ namespace Microsoft.Agents.AI;
|
||||
/// and is included in the instructions provided to the agent on each invocation.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The set of available modes is configurable via <see cref="AgentModeProviderOptions.Modes"/>.
|
||||
/// By default, two modes are provided: <c>"plan"</c> (interactive planning) and <c>"execute"</c>
|
||||
/// (autonomous execution).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This provider exposes the following tools to the agent:
|
||||
/// <list type="bullet">
|
||||
/// <item><description><c>SetMode</c> — Switch the agent's operating mode.</description></item>
|
||||
/// <item><description><c>GetMode</c> — Retrieve the agent's current operating mode.</description></item>
|
||||
/// <item><description><c>AgentMode_Set</c> — Switch the agent's operating mode.</description></item>
|
||||
/// <item><description><c>AgentMode_Get</c> — Retrieve the agent's current operating mode.</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
@@ -35,26 +41,68 @@ namespace Microsoft.Agents.AI;
|
||||
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
|
||||
public sealed class AgentModeProvider : AIContextProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The "plan" mode, indicating the agent is planning work.
|
||||
/// </summary>
|
||||
public const string PlanMode = "plan";
|
||||
|
||||
/// <summary>
|
||||
/// The "execute" mode, indicating the agent is executing work.
|
||||
/// </summary>
|
||||
public const string ExecuteMode = "execute";
|
||||
private static readonly IReadOnlyList<AgentModeProviderOptions.AgentMode> s_defaultModes =
|
||||
[
|
||||
new("plan", "Use this mode when analyzing requirements, breaking down tasks, and creating plans. This is the interactive mode — ask clarifying questions, discuss options, and get user approval before proceeding."),
|
||||
new("execute", "Use this mode when carrying out approved plans. Work autonomously using your best judgement — do not ask the user questions or wait for feedback. Make reasonable decisions on your own so that there is a complete, useful result when the user returns. If you encounter ambiguity, choose the most reasonable option and note your choice."),
|
||||
];
|
||||
|
||||
private readonly ProviderSessionState<AgentModeState> _sessionState;
|
||||
private readonly IReadOnlyList<AgentModeProviderOptions.AgentMode> _modes;
|
||||
private readonly string _defaultMode;
|
||||
private readonly string? _customInstructions;
|
||||
private readonly HashSet<string> _validModeNames;
|
||||
private readonly string _modeNamesDisplay;
|
||||
private IReadOnlyList<string>? _stateKeys;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentModeProvider"/> class.
|
||||
/// </summary>
|
||||
public AgentModeProvider()
|
||||
/// <param name="options">Optional settings that control provider behavior. When <see langword="null"/>, defaults are used.</param>
|
||||
public AgentModeProvider(AgentModeProviderOptions? options = null)
|
||||
{
|
||||
this._modes = options?.Modes ?? s_defaultModes;
|
||||
|
||||
if (this._modes.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("At least one mode must be configured.", nameof(options));
|
||||
}
|
||||
|
||||
this._customInstructions = options?.Instructions;
|
||||
|
||||
this._validModeNames = new HashSet<string>(StringComparer.Ordinal);
|
||||
var modeNamesList = new List<string>(this._modes.Count);
|
||||
for (int i = 0; i < this._modes.Count; i++)
|
||||
{
|
||||
var mode = this._modes[i];
|
||||
if (mode is null)
|
||||
{
|
||||
throw new ArgumentException($"Configured mode at index {i} must not be null.", nameof(options));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(mode.Name))
|
||||
{
|
||||
throw new ArgumentException($"Configured mode at index {i} must have a non-empty name.", nameof(options));
|
||||
}
|
||||
|
||||
if (!this._validModeNames.Add(mode.Name))
|
||||
{
|
||||
throw new ArgumentException($"Configured modes contain a duplicate mode name \"{mode.Name}\".", nameof(options));
|
||||
}
|
||||
|
||||
modeNamesList.Add(mode.Name);
|
||||
}
|
||||
|
||||
this._modeNamesDisplay = string.Join("\", \"", modeNamesList);
|
||||
this._defaultMode = options?.DefaultMode ?? modeNamesList[0];
|
||||
|
||||
if (!this._validModeNames.Contains(this._defaultMode))
|
||||
{
|
||||
throw new ArgumentException($"Default mode \"{this._defaultMode}\" is not in the configured modes list.", nameof(options));
|
||||
}
|
||||
|
||||
this._sessionState = new ProviderSessionState<AgentModeState>(
|
||||
_ => new AgentModeState(),
|
||||
_ => new AgentModeState { CurrentMode = this._defaultMode },
|
||||
this.GetType().Name,
|
||||
AgentJsonUtilities.DefaultOptions);
|
||||
}
|
||||
@@ -77,15 +125,20 @@ public sealed class AgentModeProvider : AIContextProvider
|
||||
/// </summary>
|
||||
/// <param name="session">The agent session to update the mode in.</param>
|
||||
/// <param name="mode">The new mode to set.</param>
|
||||
/// <exception cref="ArgumentException"><paramref name="mode"/> is not a configured mode.</exception>
|
||||
public void SetMode(AgentSession? session, string mode)
|
||||
{
|
||||
if (mode != PlanMode && mode != ExecuteMode)
|
||||
{
|
||||
throw new ArgumentException($"Invalid mode: {mode}. Supported modes are \"{PlanMode}\" and \"{ExecuteMode}\".", nameof(mode));
|
||||
}
|
||||
this.ValidateMode(mode);
|
||||
|
||||
AgentModeState state = this._sessionState.GetOrInitializeState(session);
|
||||
string previousMode = state.CurrentMode;
|
||||
state.CurrentMode = mode;
|
||||
|
||||
if (!string.Equals(previousMode, mode, StringComparison.Ordinal))
|
||||
{
|
||||
state.PreviousModeForNotification = previousMode;
|
||||
}
|
||||
|
||||
this._sessionState.SaveState(session, state);
|
||||
}
|
||||
|
||||
@@ -94,20 +147,54 @@ public sealed class AgentModeProvider : AIContextProvider
|
||||
{
|
||||
AgentModeState state = this._sessionState.GetOrInitializeState(context.Session);
|
||||
|
||||
string instructions = $"""
|
||||
You are currently operating in "{state.CurrentMode}" mode.
|
||||
Available modes:
|
||||
- "plan": Use this mode when analyzing requirements, breaking down tasks, and creating plans. This is the interactive mode — ask clarifying questions, discuss options, and get user approval before proceeding.
|
||||
- "execute": Use this mode when carrying out approved plans. Work autonomously using your best judgement — do not ask the user questions or wait for feedback. Make reasonable decisions on your own so that there is a complete, useful result when the user returns. If you encounter ambiguity, choose the most reasonable option and note your choice.
|
||||
Use the SetMode tool to switch between modes as your work progresses. Only use SetMode if the user explicitly instructs you to change modes.
|
||||
Use the GetMode tool to check your current operating mode.
|
||||
""";
|
||||
string instructions = this._customInstructions ?? this.BuildDefaultInstructions(state.CurrentMode);
|
||||
|
||||
return new ValueTask<AIContext>(new AIContext
|
||||
var aiContext = new AIContext
|
||||
{
|
||||
Instructions = instructions,
|
||||
Tools = this.CreateTools(state, context.Session),
|
||||
});
|
||||
};
|
||||
|
||||
// If the mode was changed externally (e.g., via /mode command), inject a notification message
|
||||
// so the agent clearly sees the change rather than relying solely on the system instructions.
|
||||
if (state.PreviousModeForNotification != null)
|
||||
{
|
||||
string previousMode = state.PreviousModeForNotification;
|
||||
state.PreviousModeForNotification = null;
|
||||
|
||||
aiContext.Messages =
|
||||
[
|
||||
new ChatMessage(ChatRole.User, $"[Mode changed: The operating mode has been switched from \"{previousMode}\" to \"{state.CurrentMode}\". You must now adjust your behavior to match the \"{state.CurrentMode}\" mode.]"),
|
||||
];
|
||||
}
|
||||
|
||||
return new ValueTask<AIContext>(aiContext);
|
||||
}
|
||||
|
||||
private string BuildDefaultInstructions(string currentMode)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append($"You are currently operating in \"{currentMode}\" mode.");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Available modes:");
|
||||
|
||||
foreach (var mode in this._modes)
|
||||
{
|
||||
sb.AppendLine($"- \"{mode.Name}\": {mode.Description}");
|
||||
}
|
||||
|
||||
sb.AppendLine("Use the AgentMode_Set tool to switch between modes as your work progresses. Only use AgentMode_Set if the user explicitly instructs/allows you to change modes.");
|
||||
sb.Append("Use the AgentMode_Get tool to check your current operating mode.");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private void ValidateMode(string mode)
|
||||
{
|
||||
if (!this._validModeNames.Contains(mode))
|
||||
{
|
||||
throw new ArgumentException($"Invalid mode: \"{mode}\". Supported modes are: \"{this._modeNamesDisplay}\".", nameof(mode));
|
||||
}
|
||||
}
|
||||
|
||||
private AITool[] CreateTools(AgentModeState state, AgentSession? session)
|
||||
@@ -119,10 +206,7 @@ public sealed class AgentModeProvider : AIContextProvider
|
||||
AIFunctionFactory.Create(
|
||||
(string mode) =>
|
||||
{
|
||||
if (mode != PlanMode && mode != ExecuteMode)
|
||||
{
|
||||
throw new ArgumentException($"Invalid mode: {mode}. Supported modes are \"{PlanMode}\" and \"{ExecuteMode}\".", nameof(mode));
|
||||
}
|
||||
this.ValidateMode(mode);
|
||||
|
||||
state.CurrentMode = mode;
|
||||
this._sessionState.SaveState(session, state);
|
||||
@@ -130,8 +214,8 @@ public sealed class AgentModeProvider : AIContextProvider
|
||||
},
|
||||
new AIFunctionFactoryOptions
|
||||
{
|
||||
Name = "SetMode",
|
||||
Description = "Switch the agent's operating mode. Supported modes: \"plan\" and \"execute\".",
|
||||
Name = "AgentMode_Set",
|
||||
Description = $"Switch the agent's operating mode. Supported modes: \"{this._modeNamesDisplay}\".",
|
||||
SerializerOptions = serializerOptions,
|
||||
}),
|
||||
|
||||
@@ -139,7 +223,7 @@ public sealed class AgentModeProvider : AIContextProvider
|
||||
() => state.CurrentMode,
|
||||
new AIFunctionFactoryOptions
|
||||
{
|
||||
Name = "GetMode",
|
||||
Name = "AgentMode_Get",
|
||||
Description = "Get the agent's current operating mode.",
|
||||
SerializerOptions = serializerOptions,
|
||||
}),
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Shared.DiagnosticIds;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Options controlling the behavior of <see cref="AgentModeProvider"/>.
|
||||
/// </summary>
|
||||
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
|
||||
public sealed class AgentModeProviderOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets custom instructions provided to the agent for using the mode tools.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// When <see langword="null"/> (the default), the provider generates instructions dynamically
|
||||
/// from the configured <see cref="Modes"/> list.
|
||||
/// </value>
|
||||
public string? Instructions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of available modes the agent can operate in.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// When <see langword="null"/> (the default), the provider uses two built-in modes:
|
||||
/// <c>"plan"</c> (interactive planning) and <c>"execute"</c> (autonomous execution).
|
||||
/// </value>
|
||||
public IReadOnlyList<AgentMode>? Modes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the initial mode for new sessions.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// When <see langword="null"/> (the default), the first mode in the <see cref="Modes"/> list is used.
|
||||
/// Must match the <see cref="AgentMode.Name"/> of one of the configured modes.
|
||||
/// </value>
|
||||
public string? DefaultMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents an agent operating mode with a name and description.
|
||||
/// </summary>
|
||||
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
|
||||
public sealed class AgentMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentMode"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the mode.</param>
|
||||
/// <param name="description">A description of when and how to use this mode.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="name"/> or <paramref name="description"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="name"/> or <paramref name="description"/> is empty or whitespace.</exception>
|
||||
public AgentMode(string name, string description)
|
||||
{
|
||||
this.Name = Throw.IfNullOrWhitespace(name);
|
||||
this.Description = Throw.IfNullOrWhitespace(description);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the mode.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a description of when and how to use this mode.
|
||||
/// </summary>
|
||||
public string Description { get; }
|
||||
}
|
||||
}
|
||||
@@ -16,5 +16,12 @@ internal sealed class AgentModeState
|
||||
/// Gets or sets the current operating mode of the agent.
|
||||
/// </summary>
|
||||
[JsonPropertyName("currentMode")]
|
||||
public string CurrentMode { get; set; } = AgentModeProvider.PlanMode;
|
||||
public string CurrentMode { get; set; } = "plan";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the previous mode before the last external change, if a mode change notification is pending.
|
||||
/// When non-null, indicates that the mode was changed externally and a notification should be injected.
|
||||
/// </summary>
|
||||
[JsonPropertyName("previousModeForNotification")]
|
||||
public string? PreviousModeForNotification { get; set; }
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ public sealed class FileMemoryProvider : AIContextProvider
|
||||
|
||||
private readonly AgentFileStore _fileStore;
|
||||
private readonly ProviderSessionState<FileMemoryState> _sessionState;
|
||||
private readonly string _instructions;
|
||||
private IReadOnlyList<string>? _stateKeys;
|
||||
private AITool[]? _tools;
|
||||
|
||||
@@ -70,12 +71,14 @@ public sealed class FileMemoryProvider : AIContextProvider
|
||||
/// Use this to customize the working folder (e.g., per-user or per-session subfolders).
|
||||
/// When <see langword="null"/>, the default initializer creates state with an empty working folder.
|
||||
/// </param>
|
||||
/// <param name="options">Optional settings that control provider behavior. When <see langword="null"/>, defaults are used.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="fileStore"/> is <see langword="null"/>.</exception>
|
||||
public FileMemoryProvider(AgentFileStore fileStore, Func<AgentSession?, FileMemoryState>? stateInitializer = null)
|
||||
public FileMemoryProvider(AgentFileStore fileStore, Func<AgentSession?, FileMemoryState>? stateInitializer = null, FileMemoryProviderOptions? options = null)
|
||||
{
|
||||
Throw.IfNull(fileStore);
|
||||
|
||||
this._fileStore = fileStore;
|
||||
this._instructions = options?.Instructions ?? DefaultInstructions;
|
||||
this._sessionState = new ProviderSessionState<FileMemoryState>(
|
||||
stateInitializer ?? (_ => new FileMemoryState()),
|
||||
this.GetType().Name,
|
||||
@@ -98,7 +101,7 @@ public sealed class FileMemoryProvider : AIContextProvider
|
||||
|
||||
return new AIContext
|
||||
{
|
||||
Instructions = DefaultInstructions,
|
||||
Instructions = this._instructions,
|
||||
Tools = this._tools ??= this.CreateTools(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Shared.DiagnosticIds;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Options controlling the behavior of <see cref="FileMemoryProvider"/>.
|
||||
/// </summary>
|
||||
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
|
||||
public sealed class FileMemoryProviderOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets custom instructions provided to the agent for using the file memory tools.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// When <see langword="null"/> (the default), the provider uses built-in instructions
|
||||
/// that guide the agent on how to use file-based memory effectively.
|
||||
/// </value>
|
||||
public string? Instructions { get; set; }
|
||||
}
|
||||
@@ -23,11 +23,11 @@ namespace Microsoft.Agents.AI;
|
||||
/// <para>
|
||||
/// This provider exposes the following tools to the agent:
|
||||
/// <list type="bullet">
|
||||
/// <item><description><c>AddTodos</c> — Add one or more todo items, each with a title and optional description.</description></item>
|
||||
/// <item><description><c>CompleteTodos</c> — Mark one or more todo items as complete by their IDs.</description></item>
|
||||
/// <item><description><c>RemoveTodos</c> — Remove one or more todo items by their IDs.</description></item>
|
||||
/// <item><description><c>GetRemainingTodos</c> — Retrieve only incomplete todo items.</description></item>
|
||||
/// <item><description><c>GetAllTodos</c> — Retrieve all todo items (complete and incomplete).</description></item>
|
||||
/// <item><description><c>TodoList_Add</c> — Add one or more todo items, each with a title and optional description.</description></item>
|
||||
/// <item><description><c>TodoList_Complete</c> — Mark one or more todo items as complete by their IDs.</description></item>
|
||||
/// <item><description><c>TodoList_Remove</c> — Remove one or more todo items by their IDs.</description></item>
|
||||
/// <item><description><c>TodoList_GetRemaining</c> — Retrieve only incomplete todo items.</description></item>
|
||||
/// <item><description><c>TodoList_GetAll</c> — Retrieve all todo items (complete and incomplete).</description></item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
@@ -44,21 +44,24 @@ public sealed class TodoProvider : AIContextProvider
|
||||
When a user changes the topic or changes their mind, ensure that you update the todo list accordingly by removing irrelevant items or adding new ones as needed.
|
||||
|
||||
Use these tools to manage your tasks:
|
||||
- Use AddTodos to break down complex work into trackable items (supports adding one or many at once).
|
||||
- Use CompleteTodos to mark items as done when finished (supports one or many at once).
|
||||
- Use GetRemainingTodos to check what work is still pending.
|
||||
- Use GetAllTodos to review the full list including completed items.
|
||||
- Use RemoveTodos to remove items that are no longer needed (supports one or many at once).
|
||||
- Use TodoList_Add to break down complex work into trackable items (supports adding one or many at once).
|
||||
- Use TodoList_Complete to mark items as done when finished (supports one or many at once).
|
||||
- Use TodoList_GetRemaining to check what work is still pending.
|
||||
- Use TodoList_GetAll to review the full list including completed items.
|
||||
- Use TodoList_Remove to remove items that are no longer needed (supports one or many at once).
|
||||
""";
|
||||
|
||||
private readonly ProviderSessionState<TodoState> _sessionState;
|
||||
private readonly string _instructions;
|
||||
private IReadOnlyList<string>? _stateKeys;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TodoProvider"/> class.
|
||||
/// </summary>
|
||||
public TodoProvider()
|
||||
/// <param name="options">Optional settings that control provider behavior. When <see langword="null"/>, defaults are used.</param>
|
||||
public TodoProvider(TodoProviderOptions? options = null)
|
||||
{
|
||||
this._instructions = options?.Instructions ?? DefaultInstructions;
|
||||
this._sessionState = new ProviderSessionState<TodoState>(
|
||||
_ => new TodoState(),
|
||||
this.GetType().Name,
|
||||
@@ -95,7 +98,7 @@ public sealed class TodoProvider : AIContextProvider
|
||||
|
||||
return new ValueTask<AIContext>(new AIContext
|
||||
{
|
||||
Instructions = DefaultInstructions,
|
||||
Instructions = this._instructions,
|
||||
Tools = this.CreateTools(state, context.Session),
|
||||
});
|
||||
}
|
||||
@@ -129,7 +132,7 @@ public sealed class TodoProvider : AIContextProvider
|
||||
},
|
||||
new AIFunctionFactoryOptions
|
||||
{
|
||||
Name = "AddTodos",
|
||||
Name = "TodoList_Add",
|
||||
Description = "Add one or more todo items. Each item has a title and an optional description. Returns the list of created todo items.",
|
||||
SerializerOptions = serializerOptions,
|
||||
}),
|
||||
@@ -157,7 +160,7 @@ public sealed class TodoProvider : AIContextProvider
|
||||
},
|
||||
new AIFunctionFactoryOptions
|
||||
{
|
||||
Name = "CompleteTodos",
|
||||
Name = "TodoList_Complete",
|
||||
Description = "Mark one or more todo items as complete by their IDs. Returns the number of items that were found and marked complete.",
|
||||
SerializerOptions = serializerOptions,
|
||||
}),
|
||||
@@ -177,7 +180,7 @@ public sealed class TodoProvider : AIContextProvider
|
||||
},
|
||||
new AIFunctionFactoryOptions
|
||||
{
|
||||
Name = "RemoveTodos",
|
||||
Name = "TodoList_Remove",
|
||||
Description = "Remove one or more todo items by their IDs. Returns the number of items that were found and removed.",
|
||||
SerializerOptions = serializerOptions,
|
||||
}),
|
||||
@@ -186,7 +189,7 @@ public sealed class TodoProvider : AIContextProvider
|
||||
() => state.Items.Where(t => !t.IsComplete).ToList(),
|
||||
new AIFunctionFactoryOptions
|
||||
{
|
||||
Name = "GetRemainingTodos",
|
||||
Name = "TodoList_GetRemaining",
|
||||
Description = "Retrieve the list of incomplete todo items.",
|
||||
SerializerOptions = serializerOptions,
|
||||
}),
|
||||
@@ -195,7 +198,7 @@ public sealed class TodoProvider : AIContextProvider
|
||||
() => state.Items,
|
||||
new AIFunctionFactoryOptions
|
||||
{
|
||||
Name = "GetAllTodos",
|
||||
Name = "TodoList_GetAll",
|
||||
Description = "Retrieve the full list of todo items, both complete and incomplete.",
|
||||
SerializerOptions = serializerOptions,
|
||||
}),
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Shared.DiagnosticIds;
|
||||
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Options controlling the behavior of <see cref="TodoProvider"/>.
|
||||
/// </summary>
|
||||
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
|
||||
public sealed class TodoProviderOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets custom instructions provided to the agent for using the todo tools.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// When <see langword="null"/> (the default), the provider uses built-in instructions
|
||||
/// that guide the agent on how to manage todos effectively.
|
||||
/// </value>
|
||||
public string? Instructions { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user