An agent or workflow is only useful when people and other systems can reach it through the interfaces and channels they already use. That might be an OpenAI Responses client, Telegram, another agent using A2A, or an MCP client. As a builder of agents and workflow, you need control over which channels you expose it to and how it behaves. To help, we’re introducing channels in Microsoft Agent Framework for agents and workflows in Python.
Choose the channels your application needs
The new packages are organized around a small shared hosting core and a set of channel-specific integrations:
agent-framework-hosting provides shared agent, workflow, and session-state helpers.
agent-framework-hosting-responses converts OpenAI Responses requests and results.
agent-framework-hosting-telegram converts Telegram updates and outbound operations.
agent-framework-hosting-a2a connects agents and workflows to native A2A SDK types.
agent-framework-hosting-mcp exposes agents and workflows as native MCP tools.
Each channel package focuses on its protocol boundary. Your application keeps using its chosen web framework or native SDK and owns routing, authentication, authorization, storage, background processing, and deployment.
This means you can add one channel or several without placing the agent or workflow inside a new application runtime, or having to maintain an agent multiple times and with multiple SDKs.

One shared target and state model
The agent-framework-hosting package provides the common foundation used with each channel. AgentState holds an agent target together with its session store, while WorkflowState resolves a workflow target from an instance, factory, or builder:
from agent_framework_hosting import AgentState, WorkflowState
agent_state = AgentState(agent)
workflow_state = WorkflowState(workflow_builder, cache_target=False)
Both state types give channel handlers and adapters one consistent way to resolve their target. The target can be created directly or supplied through synchronous or asynchronous setup code, and it can be cached or recreated for each request.
For agents, AgentState maps application-selected session IDs to AgentSession values. It deliberately does not decide how a Responses caller, Telegram user, A2A context, or MCP client becomes a session ID. You build that mapping in your application; resolve_session_id below is illustrative application code, not a function supplied by Agent Framework:
# Application-defined identity and session mapping.
session_id = resolve_session_id(authenticated_user, channel_identity)
session = await agent_state.get_or_create_session(session_id)
This mapping is what enables one conversation to continue across channels. If the same authenticated user resolves to the same canonical session ID from Responses and Telegram, both channels load and update the same AgentSession. If they resolve to different IDs, their histories remain separate. Your application owns the identity linking, authorization, and concurrency controls that make shared sessions safe.
Workflows use the same target-resolution model through WorkflowState, while checkpoint storage and the mapping from channel continuation IDs to checkpoints remain application-owned. Across both target types, the shared hosting layer keeps the agent or workflow definition independent from the channels around it; the channel packages handle their protocol-specific input and output.
OpenAI Responses
The Responses helpers convert an incoming request into Agent Framework run values and convert the completed or streaming result back into the Responses format:
from agent_framework_hosting_responses import (
create_response_id,
responses_from_run,
responses_session_id,
responses_to_run,
)
run = responses_to_run(body)
session_id, is_conversation = responses_session_id(body)
response_id = create_response_id()
session = await agent_state.get_or_create_session(session_id or response_id)
result = await (await agent_state.get_target()).run(
run["messages"],
session=session,
options=run["options"],
)
await agent_state.set_session(session_id if is_conversation else response_id, session)
response = responses_from_run(
result,
response_id=response_id,
conversation_id=session_id if is_conversation else None,
)
The application decides how response IDs and conversation IDs map to sessions. It also decides which request options callers may control, when to stream, how to authorize continuation IDs, and where session state is stored.
The runnable Responses agent sample demonstrates native FastAPI routing, streaming, session continuation, and an application-owned option policy.
Workflows can use the same Responses interface. Instead of storing an AgentSession, the application maps response IDs to workflow checkpoints. See the Responses workflow sample for a complete implementation.
Telegram
The Telegram helpers translate native updates into Agent Framework input and translate a streaming run into Telegram operations. The application executes those operations through direct HTTP calls or a Telegram SDK such as aiogram or python-telegram-bot.
Commands, webhook authentication, polling, media handling, edit throttling, and delivery policy remain regular application code. You can also add channel-specific instructions manually or through a context provider, for example to tailor the response format for Telegram.
The Telegram sample includes complete polling and webhook applications using aiogram. It demonstrates streaming edits, commands such as /new, media conversion, per-chat ordering, and session continuity.
A2A and MCP
For A2A, AgentA2AAdapter and WorkflowA2AAdapter generate native agent cards and keep the advertised input and output modes aligned with the conversion helpers. Your application continues to own the native A2A executor, task lifecycle, event queue, routes, and task store.
The A2A hosting sample shows how to expose an Agent Framework agent through a native A2A server.
For MCP, AgentMCPTool and WorkflowMCPTool derive native tools from Agent Framework targets. Applications can also use the lower-level conversion functions with a server such as FastMCP or with directly registered MCP handlers.
The MCP hosting samples cover manual conversion, FastMCP, generated agent tools, session-aware agents, and workflow-derived tools.
Build your own channel mix
The same agent or workflow can serve more than one channel. Each channel can have its own authorization rules and presentation instructions while sharing the underlying target and application infrastructure.
As the developer, you define the resolver that maps a channel-specific identity to a session ID. A unified resolver lets a user start in a Responses client and continue in Telegram, or move between any other supported channels, without starting a new conversation. Keeping channel identities in separate namespaces remains available when that is the desired experience.
This flexibility also applies to the application framework. The current HTTP samples use FastAPI, but the helpers operate at the protocol-conversion and execution-state boundary. You can integrate them with Django, Flask, another Python web framework, an existing service, or a native protocol SDK.
What’s next…
We plan to invest in extending this functionality further, with more channels, additional helpers and other features to make it even easier to host your agent! But in order to build the right things, we want to hear from you, on what works, what doesn’t work, and what else you need to complete your scenario end-to-end. So, use these packages to connect an Agent Framework agent or workflow to the protocols and channels your users need, within the application and infrastructure you already operate.
Start with the Agent Framework hosting documentation and the runnable samples linked above, build the channel mix that fits your users, and let us know what works well and which integrations you need next in Python: Channels issue #6265.
The post Introducing agent and workflow channels appeared first on Microsoft Agent Framework.