Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,12 @@ $env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-5.4-mini"
```powershell
dotnet run
```

## Security Considerations

Discovering skills over MCP means an external MCP server controls what skill content (including
instructions and, for archive-type entries, extracted files) reaches the agent. A compromised or
untrustworthy server could return adversarial content designed to manipulate the agent (indirect
prompt injection) or to exfiltrate data through skill instructions/scripts. Only connect `UseMcpSkills`
to MCP servers you have vetted and trust, and keep the conservative archive size/file-count limits in
`AgentMcpSkillsSourceOptions` unless you have a specific reason to raise them.
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,13 @@ AIAgent agent = agentChatClient
This places the compaction provider at the agent level instead of the chat client level, which allows you to use different compaction strategies for different agents that share the same chat client.

> Note: In this mode the `CompactionProvider` is not engaged during the tool calling loop. Agent-level `AIContextProviders` run before chat history is stored, so any synthetic summary messages produced by `CompactionProvider` can become part of the persisted history when using `ChatHistoryProvider`. If you want to compact only the request context while preserving the original stored history, register `CompactionProvider` on the `ChatClientBuilder` via `UseAIContextProviders(...)` instead of on `ChatClientAgentOptions`.

## Security Considerations

Most compaction strategies in this pipeline (tool-result summarization, sliding window, truncation) only
remove or reorder existing messages and carry no additional risk. `SummarizationCompactionStrategy` is
the exception: it calls out to an LLM to produce replacement summary content that permanently becomes
part of chat history. A compromised or malicious summarization service could return a summary containing
unsafe instructions, creating a persistent indirect-prompt-injection vector. Using
`SummarizationCompactionStrategy` is optional and requires explicit configuration — only point its
`IChatClient` at a summarization service you trust as much as the primary model.
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,11 @@ BAC, MSFT, BA
```

The parent agent will delegate each ticker lookup to the web search background agent concurrently and present the results in a table.

## Security Considerations

`BackgroundAgentsProvider` delegates work to the agents you supply — the parent sends them text input
and receives back whatever they produce. A compromised or malicious background agent could exfiltrate
data it receives, or return adversarial output designed to influence the parent agent via indirect
prompt injection once its result is retrieved. Only supply background agents you have vetted and trust
with the data the parent may pass to them.
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,11 @@ dotnet run --project samples/02-agents/Harness/Harness_Step05_Loop
## What to Expect

The program runs the four demos in order. Each loop is executed with `RunStreamingAsync`, so output is printed live and every re-invocation of the inner agent is marked with a `--- run N ---` header (detected via a change in the streamed `ResponseId`) — this lets you see exactly when the `LoopAgent` loops. Each streamed message is prefixed with `User:` or `Agent:` based on its role, so the loop's on-behalf-of feedback messages (surfaced as `User` turns) are visually distinct from the agent's responses (`Agent`). Each demo finishes by printing its aggregated final response. Demo 4 also prints an `Auto-approving: ...` line each time the `ToolApprovalAgent` heuristic approves the `DeployService` tool call, showing how approval-aware agents integrate with the loop.

## Security Considerations

Demo 3 uses `AIJudgeLoopEvaluator`, which is an explicit opt-in to sending the original request and the
agent's latest response to a second, external judge `IChatClient` on every iteration. A compromised or
malicious judge endpoint could exfiltrate that data, or return a manipulated verdict/gap analysis that
gets fed back into the loop as feedback — a form of indirect prompt injection. Only configure a judge
client that points at a service you trust as much as the primary model.
19 changes: 19 additions & 0 deletions dotnet/samples/02-agents/Harness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,22 @@ Samples accompanying the [*Build your own agent harness or claw with Microsoft A
| --- | --- |
| [Claw_Step01_MeetYourClaw](./BuildYourOwnClaw/Claw_Step01_MeetYourClaw/README.md) | Post 1 — a minimal HarnessAgent with a custom `get_stock_price` tool, web search, and planning |
| [Claw_Step02_WorkingWithData](./BuildYourOwnClaw/Claw_Step02_WorkingWithData/README.md) | Post 2 — file access, approvals, and durable memory (file memory plus optional Foundry memory) |

## Security Considerations

Several harness providers extend the agent's trust boundary to external systems the developer
configures — see the security notes in the individual sample READMEs (and the XML docs on the
corresponding types) before enabling them in production:
- **`BackgroundAgentsProvider`** — delegates work to developer-supplied agents (see
[Harness_Step02_Research_WithBackgroundAgents](./Harness_Step02_Research_WithBackgroundAgents/README.md)).
- **`AIJudgeLoopEvaluator`** (used by `LoopAgent`) — sends conversation content to a second, external
judge chat client (see [Harness_Step05_Loop](./Harness_Step05_Loop/README.md)).
- **`AgentSkillsProvider`** with external skill sources (e.g. `UseMcpSkills`) — loads skill content,
and potentially scripts, from a remote source (see
[AgentSkills samples](../AgentSkills/Agent_Step06_McpBasedSkills/README.md)).
- **`SummarizationCompactionStrategy`** — used for in-loop context compaction via
`HarnessAgentOptions.CompactionStrategy`, calls out to an LLM whose output becomes permanent chat
history (see [Agent_Step18_CompactionPipeline](../Agents/Agent_Step18_CompactionPipeline/README.md)).

In every case, the capability is opt-in and requires explicit configuration by the developer, who is
responsible for vetting the external service, agent, skill source, or provider before enabling it.
10 changes: 10 additions & 0 deletions dotnet/src/Microsoft.Agents.AI.Mcp/Skills/AgentMcpSkillsSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ namespace Microsoft.Agents.AI;
/// and reconciles instead of doing so on every call.</description></item>
/// </list>
/// </para>
/// <para>
/// <strong>Security considerations:</strong> This source discovers and loads skills — including full
/// skill instructions and, for <c>archive</c>-type entries, files extracted to local disk — from a
/// remote MCP server that the caller connects to explicitly (via <c>UseMcpSkills</c>); it is never
/// enabled by default. A compromised, malicious, or simply untrustworthy MCP server can return
/// adversarial skill content designed to manipulate the agent through indirect prompt injection, or
/// instructions/scripts designed to exfiltrate data once loaded and, for script-capable skills,
/// executed. Only connect this source to MCP servers you trust, and review archive extraction limits (<see cref="AgentMcpSkillsSourceOptions"/>)
/// to bound the impact of a malicious server.
/// </para>
/// </remarks>
internal sealed partial class AgentMcpSkillsSource : AgentSkillsSource
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ namespace Microsoft.Agents.AI;
/// <summary>
/// Configuration options for <see cref="AgentMcpSkillsSource"/>.
/// </summary>
/// <remarks>
/// <strong>Security consideration:</strong> The archive limits (<see cref="ArchiveMaxFileCount"/>,
/// <see cref="ArchiveMaxSizeBytes"/>, <see cref="ArchiveMaxUncompressedSizeBytes"/>) bound how much a
/// single MCP server response can extract to local disk. Since the server supplying these archives is
/// an external, potentially untrusted system, keep these limits conservative unless you have vetted the
/// server and legitimately need to raise them.
/// </remarks>
public sealed class AgentMcpSkillsSourceOptions
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ public static class AgentSkillsProviderBuilderMcpExtensions
/// <param name="client">An MCP client connected to a server exposing Agent Skills resources.</param>
/// <param name="options">Optional options that control archive-distributed skill handling.</param>
/// <returns>The builder instance for chaining.</returns>
/// <remarks>
/// <strong>Security considerations:</strong> Calling this method is an explicit opt-in to loading
/// skills — including instructions and, for archive-type entries, extracted files — from the MCP
/// server that <paramref name="client"/> is connected to. External skill sources may introduce
/// adversarial or compromised skills designed to influence the agent via indirect prompt injection
/// or to exfiltrate data through instructions or scripts the agent is induced to run. Only connect
/// to MCP servers you trust and have evaluated, and treat their responses as untrusted input.
/// </remarks>
public static AgentSkillsProviderBuilder UseMcpSkills(this AgentSkillsProviderBuilder builder, McpClient client, AgentMcpSkillsSourceOptions? options = null)
{
_ = Throw.IfNull(builder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ namespace Microsoft.Agents.AI.Compaction;
/// (such as <c>MessageCountingChatReducer</c>) and want to apply it as part of a
/// <see cref="CompactionStrategy"/> pipeline or as an in-run compaction strategy.
/// </para>
/// <para>
/// <strong>Security consideration:</strong> This strategy rebuilds the conversation from whatever
/// messages the supplied <see cref="IChatReducer"/> returns, replacing the original included messages
/// outright. If <see cref="ChatReducer"/> is backed by an external or LLM-based service (rather than a
/// purely local/deterministic reduction such as trimming by message count), a compromised or malicious
/// reducer could return messages containing unsafe instructions that permanently become part of chat
/// history — the same persistent indirect-prompt-injection risk described for
/// <see cref="SummarizationCompactionStrategy"/>. Only use a reducer implementation you trust as much
/// as the primary model when it is backed by an external service.
/// </para>
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
public sealed class ChatReducerCompactionStrategy : CompactionStrategy
Expand Down
11 changes: 11 additions & 0 deletions dotnet/src/Microsoft.Agents.AI/Compaction/CompactionProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ namespace Microsoft.Agents.AI.Compaction;
/// via <see cref="ChatClientAgentOptions.AIContextProviders"/> or via <c>UseAIContextProviders</c>
/// on a <see cref="ChatClientBuilder"/> or <see cref="AIAgentBuilder"/>.
/// </para>
/// <para>
/// <strong>Security consideration:</strong> Adding this provider, and choosing which
/// <see cref="CompactionStrategy"/> it applies, is entirely opt-in and developer-configured. Most
/// strategies (e.g. truncation, sliding-window) only remove or reorder existing messages and carry no
/// additional risk. Strategies that generate or accept externally produced replacement content are the
/// exception: <see cref="SummarizationCompactionStrategy"/> always calls out to an LLM to produce
/// summary content, and <see cref="ChatReducerCompactionStrategy"/> rebuilds the conversation from
/// whatever its supplied <see cref="IChatReducer"/> returns, which may itself be
/// backed by an external or LLM-based service. In either case, a compromised service could inject unsafe
/// instructions that persist in chat history — see each strategy's documentation for details.
/// </para>
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
public sealed class CompactionProvider : AIContextProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ namespace Microsoft.Agents.AI.Compaction;
/// The <see cref="CompactionTrigger"/> predicate controls when compaction proceeds. Use
/// <see cref="CompactionTriggers"/> for common trigger conditions such as token thresholds.
/// </para>
/// <para>
/// <strong>Security considerations:</strong> Using this strategy is an explicit opt-in — it must be
/// constructed with a summarization <see cref="IChatClient"/> and configured (e.g. via a harness
/// agent's <c>CompactionStrategy</c> option or <see cref="CompactionProvider"/>). The
/// summarized text produced by the summarization client permanently replaces the original messages in
/// chat history and is trusted the same as any other assistant message going forward. A compromised or
/// malicious summarization service could therefore return a summary containing unsafe instructions,
/// which become a persistent part of the conversation — a form of indirect prompt injection that
/// survives beyond the turn in which it was introduced. Only point <c>chatClient</c> at a summarization
/// service you trust as much as the primary model.
/// </para>
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
public sealed class SummarizationCompactionStrategy : CompactionStrategy
Expand All @@ -58,7 +69,13 @@ Omit pleasantries and redundant exchanges. Be factual and brief.
/// <summary>
/// Initializes a new instance of the <see cref="SummarizationCompactionStrategy"/> class.
/// </summary>
/// <param name="chatClient">The <see cref="IChatClient"/> to use for generating summaries. A smaller, faster model is recommended.</param>
/// <param name="chatClient">
/// The <see cref="IChatClient"/> to use for generating summaries. A smaller, faster model is
/// recommended. <strong>Security:</strong> Its output permanently replaces the original messages in
/// chat history, so only use a summarization service you trust as much as the primary model — see
/// the type-level security considerations for the indirect-prompt-injection risk of an untrusted
/// summarizer.
/// </param>
/// <param name="trigger">
/// The <see cref="CompactionTrigger"/> that controls when compaction proceeds.
/// </param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ namespace Microsoft.Agents.AI;
/// <item><description><c>background_agents_clear_completed_task</c> — Remove a completed background task and release its session to free memory.</description></item>
/// </list>
/// </para>
/// <para>
/// <strong>Security considerations:</strong> The agents passed to the constructor are delegated
/// arbitrary work by the parent agent — the parent sends them text input (which may include content
/// derived from the parent's own untrusted context) and receives back whatever text they produce. A
/// compromised or malicious supplied agent (for example, one with a compromised system prompt, tools,
/// or upstream model) could exfiltrate that input to an external system, or return adversarial output
/// designed to influence the parent agent via indirect prompt injection once its result is retrieved.
/// Only supply agents you have vetted and trust with the data the parent may pass to them.
/// </para>
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
public sealed class BackgroundAgentsProvider : AIContextProvider
Expand All @@ -60,7 +69,12 @@ You have access to background agents that can perform work on your behalf.
/// <summary>
/// Initializes a new instance of the <see cref="BackgroundAgentsProvider"/> class.
/// </summary>
/// <param name="agents">The collection of background agents available for delegation.</param>
/// <param name="agents">
/// The collection of background agents available for delegation. <strong>Security:</strong> Each
/// supplied agent should be vetted and trusted, since it will receive text input from the parent
/// agent and its output is fed back into the parent's context — see the type-level security
/// considerations for details on the exfiltration and prompt-injection risks of untrusted agents.
/// </param>
/// <param name="options">Optional settings controlling the provider behavior.</param>
/// <exception cref="ArgumentNullException"><paramref name="agents"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">An agent has a null or empty name, or agent names are not unique.</exception>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ namespace Microsoft.Agents.AI;
/// LLM-judged loops are costly and probabilistic, so consider setting a stricter
/// <see cref="LoopAgentOptions.MaxIterations"/> on the owning <see cref="LoopAgent"/>.
/// </para>
/// <para>
/// <strong>Security considerations:</strong> Using this evaluator is an explicit opt-in — the caller
/// must construct an <see cref="AIJudgeLoopEvaluator"/> with a judge <see cref="IChatClient"/> and add
/// it to the <see cref="LoopAgent"/>'s evaluator set; no judge is used by default. The judge
/// introduces a second external LLM boundary in addition to the agent's own model: on every iteration
/// it is sent the original request and the agent's latest response, both of which may contain
/// sensitive or untrusted content. A compromised or malicious judge endpoint could exfiltrate that
/// data, or return a manipulated <see cref="JudgeVerdict"/>/gap analysis that is fed back into the loop
/// as feedback, potentially steering the agent via indirect prompt injection. Only configure a judge
/// <see cref="IChatClient"/> that points at a service you trust as much as the primary model.
/// </para>
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
public sealed class AIJudgeLoopEvaluator : LoopEvaluator
Expand Down Expand Up @@ -104,7 +115,12 @@ public sealed class AIJudgeLoopEvaluator : LoopEvaluator
/// <summary>
/// Initializes a new instance of the <see cref="AIJudgeLoopEvaluator"/> class.
/// </summary>
/// <param name="judgeClient">The chat client used to judge whether the original request was answered.</param>
/// <param name="judgeClient">
/// The chat client used to judge whether the original request was answered. <strong>Security:</strong>
/// This client is sent the original request and the agent's latest response on every iteration, so
/// only point it at a service you trust as much as the primary model — see the type-level security
/// considerations for the exfiltration and prompt-injection risks of an untrusted judge.
/// </param>
/// <param name="options">Optional configuration for the judge. When <see langword="null"/>, defaults are used.</param>
/// <exception cref="ArgumentNullException"><paramref name="judgeClient"/> is <see langword="null"/>.</exception>
public AIJudgeLoopEvaluator(IChatClient judgeClient, AIJudgeLoopEvaluatorOptions? options = null)
Expand Down
11 changes: 11 additions & 0 deletions dotnet/src/Microsoft.Agents.AI/OpenTelemetryAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ namespace Microsoft.Agents.AI;
/// <remarks>
/// This class provides an implementation of the Semantic Conventions for Generative AI systems v1.37, defined at <see href="https://opentelemetry.io/docs/specs/semconv/gen-ai/" />.
/// The specification is still experimental and subject to change; as such, the telemetry output by this client is also subject to change.
/// <para>
/// <strong>Security considerations:</strong> This class emits telemetry via the standard .NET
/// <c>System.Diagnostics</c> (<see cref="Activity"/>/metrics) APIs — it does not itself contact any
/// external system. Where that telemetry is sent (a local collector, a hosted observability backend,
/// etc.) is entirely determined by the OpenTelemetry exporters and pipeline the developer configures
/// outside of Agent Framework. By default, emitted telemetry is limited to metadata (e.g. token counts,
/// operation names, durations) and does not include message content. Enabling
/// <see cref="EnableSensitiveData"/> is an explicit, separate opt-in that additionally emits raw chat
/// message content, function-call arguments, and function-call results — treat that data as sensitive
/// and ensure it is not sent to, or retained by, a telemetry backend you have not secured appropriately.
/// </para>
/// </remarks>
public sealed class OpenTelemetryAgent : DelegatingAIAgent, IDisposable
{
Expand Down
Loading
Loading