Scope
Port the Python feature/python-hosting work (the "hosting channels" surface) to .NET. Tracks the staged delivery onto the existing microsoft/agent-framework:feature/dotnet-hosting-channels integration branch.
Spec: docs/specs/003-dotnet-hosting-channels.md (lands with the first PR).
Why
Today every wire format (Responses, A2A, AG-UI, Functions, Foundry hosting) has its own Map* extension and its own state-and-identity story bolted on. As more transports land (Telegram, Discord, Slack, Activity Protocol), the surface area multiplies and cross-channel scenarios (link a Telegram identity to a Responses session, fan a response out to multiple destinations, etc.) have no consistent place to live.
The hosting-channels surface introduces a single composable seam — one AgentFrameworkHost per target, many Channels mounted side-by-side — with shared infrastructure for authorization, identity linking, link policies, host-execution state, durable push, and response-target routing. Python locked the design first; this issue tracks the literal .NET port.
Posture
Translate, not redesign. Python is canonical. Names, taxonomy, wire-level behaviors mirror Python; ASP.NET Core mechanics only where they have to. Net-new in v1; existing Hosting.OpenAI / Hosting.A2A / Hosting.AGUI.AspNetCore / Hosting.AzureFunctions / Foundry.Hosting packages stay untouched.
Delivery plan
Staged PRs against feature/dotnet-hosting-channels.
- Core scaffold —
Microsoft.Agents.AI.Hosting.Channels (Channel, ChannelContribution, capability interfaces, ChannelRequest, ResponseTarget, HostedRunResult, HostedStreamItem, AgentFrameworkHost + AuthorizeAsync pipeline, IAgentFrameworkHostBuilder, Map/AddAgentFrameworkHost extensions, IsolationKeys).
- Identity + state + runner —
IIdentityAllowlist family + combinators + AuthorizationProfile, IIdentityLinker, ILinkPolicy + 4 built-ins, IHostStateStore + InMemory and File impls, IDurableTaskRunner + InProcessDurableTaskRunner, OneTimeCodeIdentityLinker, ResponseRouter (registers hosting.push, walks response targets, fans out, runs per-destination hooks, echo idempotency).
- Channel: Invocations —
Microsoft.Agents.AI.Hosting.Channels.Invocations. JSON POST /invocations/invoke + background + polling. WorkflowRunResult rendered as awaiting_input / completed / failed.
- Workflow runner — drives
InProcessExecution.RunStreamingAsync, persists resume tokens on IHostStateStore, resumes via ExternalResponse.
- Channel: Telegram —
Microsoft.Agents.AI.Hosting.Channels.Telegram. Polling + webhook over raw HTTP. IChannelPush. ConversationScope (PerUser / PerUserPerConversation / PerConversation). AcceptInGroup (MentionOnly default for groups). DM-redirect link challenge. setMyCommands at startup.
- Sample + unit tests — one sample per channel under
samples/04-hosting/HostingChannels/. Microsoft.Agents.AI.Hosting.Channels.UnitTests covering response target / allowlists / state store / linker / durable runner.
- Fast-follow (separate issues):
Microsoft.Agents.AI.Hosting.Channels.Responses (Responses wire-compat), FoundryHostedAgentRunner in Microsoft.Agents.AI.Foundry.Hosting, IsolationKeysMiddleware (ASP.NET Core header lifting), workflow-runner durability across process restarts, per-channel IChannelPushCodec (for JSON-payload durable runners), .DurableTask / .Discord / .Activity / .EntraId packages.
Active PRs
- #6151 — draft scaffold (commits 1–6 above)
Out of scope (v1)
- Rewriting any existing
Map* extension to delegate to the new builder. Tier-2 migration ships as a separate, fast-follow release once v1 is stable.
- Any hard break in alpha or shipped packages.
References
Scope
Port the Python
feature/python-hostingwork (the "hosting channels" surface) to .NET. Tracks the staged delivery onto the existingmicrosoft/agent-framework:feature/dotnet-hosting-channelsintegration branch.Spec:
docs/specs/003-dotnet-hosting-channels.md(lands with the first PR).Why
Today every wire format (Responses, A2A, AG-UI, Functions, Foundry hosting) has its own
Map*extension and its own state-and-identity story bolted on. As more transports land (Telegram, Discord, Slack, Activity Protocol), the surface area multiplies and cross-channel scenarios (link a Telegram identity to a Responses session, fan a response out to multiple destinations, etc.) have no consistent place to live.The hosting-channels surface introduces a single composable seam — one
AgentFrameworkHostper target, manyChannels mounted side-by-side — with shared infrastructure for authorization, identity linking, link policies, host-execution state, durable push, and response-target routing. Python locked the design first; this issue tracks the literal .NET port.Posture
Translate, not redesign. Python is canonical. Names, taxonomy, wire-level behaviors mirror Python; ASP.NET Core mechanics only where they have to. Net-new in v1; existing
Hosting.OpenAI/Hosting.A2A/Hosting.AGUI.AspNetCore/Hosting.AzureFunctions/Foundry.Hostingpackages stay untouched.Delivery plan
Staged PRs against
feature/dotnet-hosting-channels.Microsoft.Agents.AI.Hosting.Channels(Channel,ChannelContribution, capability interfaces,ChannelRequest,ResponseTarget,HostedRunResult,HostedStreamItem,AgentFrameworkHost+AuthorizeAsyncpipeline,IAgentFrameworkHostBuilder,Map/AddAgentFrameworkHostextensions,IsolationKeys).IIdentityAllowlistfamily + combinators +AuthorizationProfile,IIdentityLinker,ILinkPolicy+ 4 built-ins,IHostStateStore+InMemoryandFileimpls,IDurableTaskRunner+InProcessDurableTaskRunner,OneTimeCodeIdentityLinker,ResponseRouter(registershosting.push, walks response targets, fans out, runs per-destination hooks, echo idempotency).Microsoft.Agents.AI.Hosting.Channels.Invocations. JSONPOST /invocations/invoke+ background + polling.WorkflowRunResultrendered asawaiting_input/completed/failed.InProcessExecution.RunStreamingAsync, persists resume tokens onIHostStateStore, resumes viaExternalResponse.Microsoft.Agents.AI.Hosting.Channels.Telegram. Polling + webhook over raw HTTP.IChannelPush.ConversationScope(PerUser/PerUserPerConversation/PerConversation).AcceptInGroup(MentionOnlydefault for groups). DM-redirect link challenge.setMyCommandsat startup.samples/04-hosting/HostingChannels/.Microsoft.Agents.AI.Hosting.Channels.UnitTestscovering response target / allowlists / state store / linker / durable runner.Microsoft.Agents.AI.Hosting.Channels.Responses(Responses wire-compat),FoundryHostedAgentRunnerinMicrosoft.Agents.AI.Foundry.Hosting,IsolationKeysMiddleware(ASP.NET Core header lifting), workflow-runner durability across process restarts, per-channelIChannelPushCodec(for JSON-payload durable runners),.DurableTask/.Discord/.Activity/.EntraIdpackages.Active PRs
Out of scope (v1)
Map*extension to delegate to the new builder. Tier-2 migration ships as a separate, fast-follow release once v1 is stable.References
feature/python-hostingdocs/specs/002-python-hosting-channels.mdon the Python branch