diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index 6f5fa9d46a..35df1a77f6 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -307,7 +307,9 @@
-
+
+
+
diff --git a/dotnet/samples/04-hosting/ContainerWorkflow/ContainerWorkflow.csproj b/dotnet/samples/04-hosting/ContainerWorkflow/ContainerWorkflow.csproj
new file mode 100644
index 0000000000..a7d4c64490
--- /dev/null
+++ b/dotnet/samples/04-hosting/ContainerWorkflow/ContainerWorkflow.csproj
@@ -0,0 +1,10 @@
+
+
+ net10.0
+ enable
+ enable
+
+
+
+
+
diff --git a/dotnet/samples/04-hosting/ContainerWorkflow/Dockerfile b/dotnet/samples/04-hosting/ContainerWorkflow/Dockerfile
new file mode 100644
index 0000000000..7ad8c6a55a
--- /dev/null
+++ b/dotnet/samples/04-hosting/ContainerWorkflow/Dockerfile
@@ -0,0 +1,13 @@
+FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
+WORKDIR /src
+COPY . .
+RUN dotnet publish dotnet/samples/04-hosting/ContainerWorkflow/ContainerWorkflow.csproj \
+ -c Release -f net10.0 -o /app/publish --tl:off
+
+FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
+WORKDIR /app
+COPY --from=build /app/publish .
+USER $APP_UID
+ENV ASPNETCORE_HTTP_PORTS=8080
+EXPOSE 8080
+ENTRYPOINT ["dotnet", "ContainerWorkflow.dll"]
diff --git a/dotnet/samples/04-hosting/ContainerWorkflow/Dockerfile.dockerignore b/dotnet/samples/04-hosting/ContainerWorkflow/Dockerfile.dockerignore
new file mode 100644
index 0000000000..18c7b2c67e
--- /dev/null
+++ b/dotnet/samples/04-hosting/ContainerWorkflow/Dockerfile.dockerignore
@@ -0,0 +1,15 @@
+**
+!CODE_OF_CONDUCT.md
+!.editorconfig
+!dotnet/
+!dotnet/**
+**/bin/
+**/obj/
+**/.env
+**/.env.*
+**/local-feed/
+**/appsettings.Development.json
+**/secrets.json
+**/*.pfx
+**/*.pem
+**/*.key
diff --git a/dotnet/samples/04-hosting/ContainerWorkflow/Program.cs b/dotnet/samples/04-hosting/ContainerWorkflow/Program.cs
new file mode 100644
index 0000000000..207cb7118f
--- /dev/null
+++ b/dotnet/samples/04-hosting/ContainerWorkflow/Program.cs
@@ -0,0 +1,67 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+// Host a deterministic expense-routing workflow in ASP.NET Core, locally or in a container.
+using Microsoft.Agents.AI.Workflows;
+
+WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
+WebApplication app = builder.Build();
+
+app.MapGet("/health", () => Results.Ok());
+app.MapPost("/expenses", async (ExpenseRequest expense, CancellationToken cancellationToken) =>
+{
+ if (string.IsNullOrWhiteSpace(expense.Id) || expense.Id.Length > 128 || expense.Amount <= 0)
+ {
+ return Results.BadRequest(new { error = "Supply an id of 1-128 characters and an amount greater than zero." });
+ }
+
+ // Each request owns its executors and workflow state, so concurrent requests remain isolated.
+ NormalizeExpenseExecutor normalize = new();
+ RouteExpenseExecutor route = new();
+ Workflow workflow = new WorkflowBuilder(normalize).AddEdge(normalize, route).WithOutputFrom(route).Build();
+
+ await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, expense, cancellationToken: cancellationToken);
+ ExpenseDecision? decision = null;
+ await foreach (WorkflowEvent evt in run.WatchStreamAsync(cancellationToken))
+ {
+ if (evt is WorkflowErrorEvent or ExecutorFailedEvent)
+ {
+ return Results.Problem("The expense workflow failed.");
+ }
+
+ if (evt is WorkflowOutputEvent { Data: ExpenseDecision output })
+ {
+ decision = output;
+ }
+ }
+
+ // Disposing the run also stops execution when request cancellation ends stream consumption.
+ return decision is null ? Results.Problem("The workflow produced no decision.") : Results.Ok(decision);
+});
+
+await app.RunAsync();
+
+internal readonly record struct ExpenseRequest(string? Id, decimal Amount);
+
+internal sealed record ExpenseDecision(string Id, decimal Amount, string Route);
+
+internal sealed class NormalizeExpenseExecutor() : Executor("NormalizeExpense")
+{
+ ///
+ public override ValueTask HandleAsync(ExpenseRequest message, IWorkflowContext context, CancellationToken cancellationToken = default)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ return ValueTask.FromResult(message with { Id = message.Id!.Trim() });
+ }
+}
+
+internal sealed class RouteExpenseExecutor() : Executor("RouteExpense")
+{
+ ///
+ public override ValueTask HandleAsync(ExpenseRequest message, IWorkflowContext context, CancellationToken cancellationToken = default)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ // ponytail: this sample routes expenses; it does not approve payments or call a business system.
+ return ValueTask.FromResult(new ExpenseDecision(message.Id!, message.Amount,
+ message.Amount > 100 ? "manager_review" : "standard_review"));
+ }
+}
diff --git a/dotnet/samples/04-hosting/ContainerWorkflow/README.md b/dotnet/samples/04-hosting/ContainerWorkflow/README.md
new file mode 100644
index 0000000000..921590b9eb
--- /dev/null
+++ b/dotnet/samples/04-hosting/ContainerWorkflow/README.md
@@ -0,0 +1,76 @@
+# Host a workflow in a container
+
+This sample hosts a pro-code workflow in ASP.NET Core and packages it as a non-root
+Linux container. It routes an expense through two executors: normalize the expense
+ID, then select standard review (amount <= 100) or manager review (amount > 100).
+The rules are deterministic so you can verify the hosting setup without a model,
+cloud account, credentials, or external business system.
+
+Each HTTP request builds its own workflow and executors. Cancelling a request ends
+event consumption; disposing its `StreamingRun` stops the underlying execution.
+An executor failure produces an HTTP 500 response rather than a successful result.
+
+## Run locally
+
+Install the .NET SDK specified in `dotnet/global.json`. From the repository root:
+
+```sh
+dotnet run --project dotnet/samples/04-hosting/ContainerWorkflow -f net10.0 -- --urls http://localhost:8080
+```
+
+In another terminal:
+
+```sh
+curl http://localhost:8080/health
+curl -H "Content-Type: application/json" -d '{"id":"EXP-001","amount":150}' http://localhost:8080/expenses
+```
+
+Expected response:
+
+```json
+{"id":"EXP-001","amount":150,"route":"manager_review"}
+```
+
+For PowerShell, use:
+
+```powershell
+Invoke-RestMethod http://localhost:8080/expenses -Method Post -ContentType application/json -Body '{"id":"EXP-001","amount":150}'
+```
+
+Amounts of 100 or less select `standard_review`. A missing/blank ID, an ID longer
+than 128 characters, or a non-positive amount returns HTTP 400. Malformed JSON is
+also rejected by ASP.NET Core.
+
+## Build and run the container
+
+With Docker running in Linux-container mode, run these commands from the repository
+root. The build uses project references to compile this checkout of the framework.
+The Dockerfile-specific ignore file limits the build context to .NET sources and
+excludes local build output and common credential files.
+
+```sh
+docker build -f dotnet/samples/04-hosting/ContainerWorkflow/Dockerfile -t agent-framework-workflow .
+docker run --rm --name agent-framework-workflow -p 127.0.0.1:8080:8080 agent-framework-workflow
+```
+
+Use the same requests above to verify the container. Stop it with Ctrl+C, or from
+another terminal:
+
+```sh
+docker stop agent-framework-workflow
+```
+
+## Hosting boundaries
+
+This is an in-process, request/response deployment example. It does not persist
+workflow state across process restarts, execute payments, or provide a human
+approval UI. The expense ID is returned for correlation; it is not an idempotency
+key. Repeating a request executes a new workflow.
+
+The endpoint is unauthenticated for local testing. Add application authentication
+and authorization before exposing it to other users. No inbound credentials or
+request bodies are deliberately logged by the sample.
+
+For cloud-managed hosting, see [Foundry hosted agents](../FoundryHostedAgents).
+For durable agents and external scheduling, see the
+[Durable Agent Framework extension](https://github.com/microsoft/agent-framework-durable-extension).
diff --git a/dotnet/samples/04-hosting/README.md b/dotnet/samples/04-hosting/README.md
new file mode 100644
index 0000000000..31bba5b91e
--- /dev/null
+++ b/dotnet/samples/04-hosting/README.md
@@ -0,0 +1,7 @@
+# Hosting samples
+
+| Sample | Demonstrates |
+| --- | --- |
+| [Container workflow](./ContainerWorkflow) | Host a pro-code workflow with ASP.NET Core and run it in a Docker container |
+| [Foundry hosted agents](./FoundryHostedAgents) | Deploy and invoke agents with Microsoft Foundry |
+| [A2A](./A2A) | Host agents using the Agent-to-Agent protocol |