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
4 changes: 3 additions & 1 deletion agent-framework/TOC.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ items:
href: agents/observability.md
- name: Evaluation
href: agents/evaluation.md
- name: Agent Hooks
href: agents/agent-hooks.md
- name: Agent Skills
href: agents/skills.md
- name: CodeAct
Expand Down Expand Up @@ -307,7 +309,7 @@ items:
href: integrations/by-component/ui/ag-ui/backend-tool-rendering.md
- name: Frontend Tool Rendering
href: integrations/by-component/ui/ag-ui/frontend-tools.md
- name: Security Considerations
- name: Production and Security Considerations
href: integrations/by-component/ui/ag-ui/security-considerations.md
- name: Workflows
href: integrations/by-component/ui/ag-ui/workflows.md
Expand Down
336 changes: 336 additions & 0 deletions agent-framework/agents/agent-hooks.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion agent-framework/agents/background-responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ Background responses require an explicit session via `agent.WithSession(session)

A Harness Agent remains a standard Agent Framework agent, so provider background responses use the same per-run options documented above. Harness construction doesn't enable provider background responses automatically: set `AllowBackgroundResponses` in .NET or `options={"background": True}` in Python when starting the run, keep the session, and persist continuation tokens when the operation must survive a process restart.

This is separate from [background agents](background-agents.md#use-background-agents-with-harnessed-agent), which delegate work to child agents rather than continuing one provider request.
This is separate from [background agents](background-agents.md#use-background-agents-with-harness-agent), which delegate work to child agents rather than continuing one provider request.

## Best Practices

Expand Down
3 changes: 2 additions & 1 deletion agent-framework/agents/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Browse built-in Agent Framework capabilities for multimodal input,
author: eavanvalkenburg
ms.topic: overview
ms.author: edvan
ms.date: 07/30/2026
ms.date: 08/07/2026
ms.service: agent-framework
---

Expand Down Expand Up @@ -52,6 +52,7 @@ Looking for the agent-type and SDK-selection guidance previously hosted on this
|---|---|
| [Observability](observability.md) | Export traces, metrics, and logs. |
| [Evaluation](evaluation.md) | Measure agent quality, safety, and correctness. |
| [Agent Hooks](agent-hooks.md) | Apply fail-closed governance controls through a shared interception contract. |
| [Agent Security with FIDES](security.md) | Enforce information-flow controls across agent data and tools. |

The [Harness Agent](../concepts/harness.md) assembles many of these capabilities into an opinionated operational agent.
Expand Down
4 changes: 3 additions & 1 deletion agent-framework/concepts/agents/agent-pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ zone_pivot_groups: programming-languages
author: eavanvalkenburg
ms.topic: article
ms.author: edvan
ms.date: 07/01/2026
ms.date: 08/07/2026
ms.service: agent-framework
---

Expand Down Expand Up @@ -51,6 +51,8 @@ The `Agent` class builds a pipeline through class composition with two main comp

When you call `run()`, your request flows through the Agent layers, then into the ChatClient pipeline for LLM communication.

The optional [Agent Hooks](../../agents/agent-hooks.md) capability installs one middleware bundle across the agent, chat, and function layers. Core streaming and persistence gates extend that boundary so output isn't released or stored before the applicable verdict permits it.

::: zone-end

::: zone pivot="programming-language-go"
Expand Down
5 changes: 4 additions & 1 deletion agent-framework/concepts/agents/conversations/session.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ zone_pivot_groups: programming-languages
author: eavanvalkenburg
ms.topic: article
ms.author: edvan
ms.date: 07/29/2026
ms.date: 08/11/2026
ms.service: agent-framework
---

Expand All @@ -19,6 +19,7 @@ ms.service: agent-framework
| Harness Agent session usage | ✅ | ✅ | ❌ | Harness Agent isn't available in Go |
| Existing service conversation ID | ✅ | ✅ | ❌ | |
| Serialization and restoration | ✅ | ✅ | ✅ | |
| Hosted session persistence | ✅ | ❌ | ❌ | .NET hosting-specific |
-->

# Session
Expand Down Expand Up @@ -205,6 +206,8 @@ var serialized = agent.SerializeSession(session);
AgentSession resumed = await agent.DeserializeSessionAsync(serialized);
```

In a self-hosted application, an `AgentSessionStore` can load and save sessions by a continuation ID as part of request processing. This is distinct from manually persisting a session and from configuring a history provider. See [Self-host Agent Framework applications](../../../hosting/self-hosting/index.md#persist-hosted-sessions).

:::zone-end

:::zone pivot="programming-language-python"
Expand Down
5 changes: 4 additions & 1 deletion agent-framework/concepts/agents/middleware/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ zone_pivot_groups: programming-languages
author: dmytrostruk
ms.topic: reference
ms.author: dmytrostruk
ms.date: 07/01/2026
ms.date: 08/07/2026
ms.service: agent-framework
---

Expand Down Expand Up @@ -193,6 +193,9 @@ All types support both function-based and class-based implementations. When mult
> `A1 -> A2 -> R1 -> R2 -> Agent -> R2 -> R1 -> A2 -> A1`.
> - Function/chat middleware follows the same wrapping principle at tool/chat-call time.

> [!TIP]
> For a standardized, fail-closed control boundary spanning agent, chat, and function middleware, see [Agent Hooks](../../../agents/agent-hooks.md). Agent Hooks also coordinates core streaming and persistence behavior that ordinary middleware can't provide by itself.

## Agent Middleware

Agent middleware intercepts and modifies agent run execution. It uses the `AgentContext` which contains:
Expand Down
28 changes: 14 additions & 14 deletions agent-framework/concepts/harness.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,27 @@ The Harness composes existing Agent Framework building blocks rather than defini
1. **Middleware and decorators** — add approval handling, observability, and optional bounded looping.
1. **Application UX** — streams responses, displays progress, and collects input such as tool approvals.

The resulting object remains a normal Agent Framework agent: a `HarnessAgent` that derives from `AIAgent` in .NET, or an `Agent` returned by `create_harness_agent` in Python. Its sessions use the same [session](./agents/conversations/session.md#use-sessions-with-harnessed-agent) and [context provider](./agents/conversations/context-providers.md#use-context-providers-with-harnessed-agent) abstractions as other agents.
The resulting object remains a normal Agent Framework agent: a `HarnessAgent` that derives from `AIAgent` in .NET, or an `Agent` returned by `create_harness_agent` in Python. Its sessions use the same [session](./agents/conversations/session.md#use-sessions-with-harness-agent) and [context provider](./agents/conversations/context-providers.md#use-context-providers-with-harness-agent) abstractions as other agents.

## Harness capability matrix

| Capability | Harness behavior | Canonical guidance |
|---|---|---|
| Function invocation | Enabled with a configurable per-request iteration limit. | [Function tools](../agents/tools/function-tools.md#use-function-tools-with-harnessed-agent) |
| Per-service-call history persistence | Persists history after each model call in a tool-calling run. | [Sessions](./agents/conversations/session.md#use-sessions-with-harnessed-agent) |
| Compaction | Enabled when token limits or a custom strategy are supplied. | [Compaction](./agents/conversations/compaction.md#use-compaction-with-harnessed-agent) |
| Todo tracking | Enabled by default. | [Planning and todos](../agents/planning-and-todos.md#use-planning-and-todos-with-harnessed-agent) |
| Agent modes | Plan and execute modes are enabled by default. | [Planning and todos](../agents/planning-and-todos.md#use-planning-and-todos-with-harnessed-agent) |
| File memory and file access | Session file memory is enabled by default; shared file access is opt-in. | [Context providers](./agents/conversations/context-providers.md#use-context-providers-with-harnessed-agent) |
| Per-service-call history persistence | Persists history after each model call in a tool-calling run. | [Sessions](./agents/conversations/session.md#use-sessions-with-harness-agent) |
| Compaction | Enabled when token limits or a custom strategy are supplied. | [Compaction](./agents/conversations/compaction.md#use-compaction-with-harness-agent) |
| Todo tracking | Enabled by default. | [Planning and todos](../agents/planning-and-todos.md#use-planning-and-todos-with-harness-agent) |
| Agent modes | Plan and execute modes are enabled by default. | [Planning and todos](../agents/planning-and-todos.md#use-planning-and-todos-with-harness-agent) |
| File memory and file access | Session file memory is enabled by default; shared file access is opt-in. | [Context providers](./agents/conversations/context-providers.md#use-context-providers-with-harness-agent) |
| Tool approval | Standing approvals and auto-approval rules are enabled by default. | [Tool approval](../agents/tools/tool-approval.md#use-tool-approval-with-harnessed-agent) |
| OpenTelemetry | Agent observability is enabled by default. | [Observability](../agents/observability.md#use-observability-with-harnessed-agent) |
| Web search | Added by default where the selected chat client supports it. | [Web search](../agents/tools/web-search.md#use-web-search-with-harnessed-agent) |
| Agent Skills | Enabled by default in .NET; opt-in through a provider or paths in Python. | [Agent Skills](../agents/skills.md#use-agent-skills-with-harnessed-agent) |
| Background agents | Optional parallel delegation to named child agents. | [Background agents](../agents/background-agents.md#use-background-agents-with-harnessed-agent) |
| Agent Skills | Enabled by default in .NET; opt-in through a provider or paths in Python. | [Agent Skills](../agents/skills.md#use-agent-skills-with-harness-agent) |
| Background agents | Optional parallel delegation to named child agents. | [Background agents](../agents/background-agents.md#use-background-agents-with-harness-agent) |
| Shell execution | Composed from the shell package; the Python factory can wire it automatically. | [Shell tools](../integrations/by-component/tools/shell-tools.md#use-shell-tools-with-harnessed-agent) |
| Looping | Optional bounded re-invocation driven by evaluators or predicates. | [Agent looping](../agents/looping.md#use-looping-with-harnessed-agent) |
| Looping | Optional bounded re-invocation driven by evaluators or predicates. | [Agent looping](../agents/looping.md#use-looping-with-harness-agent) |

Background-agent delegation is separate from provider-managed [background responses](../agents/background-responses.md#use-background-responses-with-harnessed-agent). Background agents run child agents on delegated tasks; background responses poll or resume one provider request by using a continuation token.
Background-agent delegation is separate from provider-managed [background responses](../agents/background-responses.md#use-background-responses-with-harness-agent). Background agents run child agents on delegated tasks; background responses poll or resume one provider request by using a continuation token.

::: zone pivot="programming-language-csharp"

Expand Down Expand Up @@ -198,11 +198,11 @@ The repository doesn't currently include a packaged Go Harness terminal sample.
## Next steps

> [!div class="nextstepaction"]
> [Plan work and track todos](../agents/planning-and-todos.md#use-planning-and-todos-with-harnessed-agent)
> [Plan work and track todos](../agents/planning-and-todos.md#use-planning-and-todos-with-harness-agent)

### Go deeper

- [Looping](../agents/looping.md#use-looping-with-harnessed-agent)
- [Background agents](../agents/background-agents.md#use-background-agents-with-harnessed-agent)
- [Compaction](./agents/conversations/compaction.md#use-compaction-with-harnessed-agent)
- [Looping](../agents/looping.md#use-looping-with-harness-agent)
- [Background agents](../agents/background-agents.md#use-background-agents-with-harness-agent)
- [Compaction](./agents/conversations/compaction.md#use-compaction-with-harness-agent)
- [Shell tools](../integrations/by-component/tools/shell-tools.md#use-shell-tools-with-harnessed-agent)
44 changes: 43 additions & 1 deletion agent-framework/concepts/workflows/executors.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ zone_pivot_groups: programming-languages
author: TaoChenOSU
ms.topic: article
ms.author: taochen
ms.date: 07/01/2026
ms.date: 08/11/2026
ms.service: agent-framework
---

Expand All @@ -20,6 +20,7 @@ ms.service: agent-framework
| Function-Based Executors | ✅ | ✅ | ✅ | |
| Explicit Type Parameters | ❌ | ✅ | ❌ | Python-specific |
| The WorkflowContext Object | ✅ | ✅ | ✅ | |
| Declaring Protocol Types | ✅ | ❌ | ❌ | C#-specific protocol declaration attributes |
| Designating Terminal and Intermediate Outputs | ❌ | ✅ | ❌ | Python-specific |
| Agent Executors | ❌ | ❌ | ✅ | Go-specific |
| Executor Lifecycle | ❌ | ❌ | ✅ | Go-specific |
Expand Down Expand Up @@ -137,6 +138,47 @@ internal sealed partial class LogExecutor() : Executor("LogExecutor")
}
```

## Declaring Protocol Types

An executor's protocol declares the message types it may send to connected executors and the output types it may yield. The workflow validates calls to `SendMessageAsync` and `YieldOutputAsync` against these declarations and throws an `InvalidOperationException` when an executor uses an undeclared type.

Use `[SendsMessage]` to declare sent message types and `[YieldsOutput]` to declare yielded output types. These attributes describe the executor's capabilities; they do not send or yield values themselves. Apply each attribute multiple times when the executor uses multiple types.

For executors with a single typed handler, derive from `Executor<TInput>` or `Executor<TInput, TOutput>` and override `HandleAsync`:

```csharp
internal sealed record ProcessRequest(string Text);
internal sealed record ProgressUpdate(string Status);

[SendsMessage(typeof(ProgressUpdate))]
[YieldsOutput(typeof(string))]
internal sealed partial class ProcessingExecutor()
: Executor<ProcessRequest>("ProcessingExecutor")
{
public override async ValueTask HandleAsync(
ProcessRequest message,
IWorkflowContext context,
CancellationToken cancellationToken = default)
{
await context.SendMessageAsync(
new ProgressUpdate("Processing started"),
cancellationToken);

await context.YieldOutputAsync(
message.Text.ToUpperInvariant(),
cancellationToken);
}
}
```

When the workflows source generator is referenced, a class with `[SendsMessage]` or `[YieldsOutput]` must be declared `partial` so the generator can add its protocol configuration.

For source-generated executors with `[MessageHandler]` methods, declare types used by one handler with its `Send` and `Yield` named arguments, such as `[MessageHandler(Send = [typeof(ProgressUpdate)], Yield = [typeof(string)])]`. Use class-level `[SendsMessage]` and `[YieldsOutput]` when the declarations apply to the entire executor.

Non-void handler return types are automatically added to the sent and yielded protocol types when `ExecutorOptions.AutoSendMessageHandlerResultObject` and `ExecutorOptions.AutoYieldOutputHandlerResultObject` are enabled. Both options are enabled by default. Explicit declarations are therefore primarily needed for additional types emitted directly through `SendMessageAsync` or `YieldOutputAsync`.

`[YieldsOutput]` permits the executor to yield a type, but it does not designate the executor as a terminal output source. Register the executor with `WorkflowBuilder.WithOutputFrom` for its yielded values to surface to the workflow caller.

::: zone-end

::: zone pivot="programming-language-python"
Expand Down
Loading