Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This document provides an overview of how to use Workflows as Agents in Microsoft Agent Framework.
Overview
Sometimes you've built a sophisticated workflow with multiple agents, custom executors, and complex logic - but you want to use it just like any other agent. That's exactly what workflow agents let you do. By wrapping your workflow as an Agent, you can interact with it through the same familiar API you'd use for a simple chat agent.
Key Benefits
- Unified Interface: Interact with complex workflows using the same API as simple agents
- API Compatibility: Integrate workflows with existing systems that support the Agent interface
- Composability: Use workflow agents as building blocks in larger agent systems or other workflows
- Session Management: Leverage agent sessions for conversation state and resumption
- Streaming Support: Get real-time updates as the workflow executes
How It Works
When you convert a workflow to an agent:
- The workflow is validated to ensure its start executor can accept the required input types
- A session is created to manage conversation state
- Input messages are routed to the workflow's start executor
- Workflow events are converted to agent response updates
- External input requests (from
RequestInfoExecutor) are surfaced as function calls
Requirements
To use a workflow as an agent, the workflow's start executor must be able to handle IEnumerable<ChatMessage> as input. This is automatically satisfied when using agent-based executors created with AsAIAgent.
Create a Workflow Agent
Use the AsAIAgent() extension method to convert any compatible workflow into an agent:
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;
// Create agents
AIAgent researchAgent = chatClient.AsAIAgent("You are a researcher. Research and gather information on the given topic.");
AIAgent writerAgent = chatClient.AsAIAgent("You are a writer. Write clear, engaging content based on research.");
AIAgent reviewerAgent = chatClient.AsAIAgent("You are a reviewer. Review the content and provide a final polished version.");
// Build a sequential workflow
var workflow = new WorkflowBuilder(researchAgent)
.AddEdge(researchAgent, writerAgent)
.AddEdge(writerAgent, reviewerAgent)
.Build();
// Convert the workflow to an agent
AIAgent workflowAgent = workflow.AsAIAgent(
id: "content-pipeline",
name: "Content Pipeline Agent",
description: "A multi-agent workflow that researches, writes, and reviews content"
);
AsAIAgent Parameters
| Parameter | Type | Description |
|---|---|---|
id |
string? |
Optional unique identifier for the agent. Auto-generated if not provided. |
name |
string? |
Optional display name for the agent. |
description |
string? |
Optional description of the agent's purpose. |
executionEnvironment |
IWorkflowExecutionEnvironment? |
Optional execution environment. Defaults to InProcessExecution.OffThread or InProcessExecution.Concurrent based on workflow configuration. |
includeExceptionDetails |
bool |
If true, includes exception messages in error content. Defaults to false. |
includeWorkflowOutputsInResponse |
bool |
If true, transforms outgoing workflow outputs into content in agent responses. Defaults to false. |
Using Workflow Agents
Creating a Session
Each conversation with a workflow agent requires a session to manage state:
// Create a new session for the conversation
AgentSession session = await workflowAgent.CreateSessionAsync();
Non-Streaming Execution
For simple use cases where you want the complete response:
var messages = new List<ChatMessage>
{
new(ChatRole.User, "Write an article about renewable energy trends in 2025")
};
AgentResponse response = await workflowAgent.RunAsync(messages, session);
foreach (ChatMessage message in response.Messages)
{
Console.WriteLine($"{message.AuthorName}: {message.Text}");
}
Streaming Execution
For real-time updates as the workflow executes:
var messages = new List<ChatMessage>
{
new(ChatRole.User, "Write an article about renewable energy trends in 2025")
};
await foreach (AgentResponseUpdate update in workflowAgent.RunStreamingAsync(messages, session))
{
// Process streaming updates from each agent in the workflow
if (!string.IsNullOrEmpty(update.Text))
{
Console.Write(update.Text);
}
}
Handling External Input Requests
When a workflow contains executors that request external input (using RequestInfoExecutor), these requests are surfaced as function calls in the agent response:
await foreach (AgentResponseUpdate update in workflowAgent.RunStreamingAsync(messages, session))
{
// Check for function call requests
foreach (AIContent content in update.Contents)
{
if (content is FunctionCallContent functionCall)
{
// Handle the external input request
Console.WriteLine($"Workflow requests input: {functionCall.Name}");
Console.WriteLine($"Request data: {functionCall.Arguments}");
// Provide the response in the next message
}
}
}
Session Serialization and Resumption
Workflow agent sessions can be serialized for persistence and resumed later:
// Serialize the session state
JsonElement serializedSession = await workflowAgent.SerializeSessionAsync(session);
// Store serializedSession to your persistence layer...
// Later, resume the session
AgentSession resumedSession = await workflowAgent.DeserializeSessionAsync(serializedSession);
// Continue the conversation
await foreach (var update in workflowAgent.RunStreamingAsync(newMessages, resumedSession))
{
Console.Write(update.Text);
}
Requirements
To use a workflow as an agent, the workflow's start executor must be able to handle message input. This is automatically satisfied when using Agent or agent-based executors.
Creating a Workflow Agent
Call as_agent() on any compatible workflow to convert it into an agent:
from agent_framework.azure import AzureOpenAIResponsesClient
from agent_framework.orchestrations import SequentialBuilder
from azure.identity import AzureCliCredential
# Create your chat client and agents
client = AzureOpenAIResponsesClient(
project_endpoint="<your-endpoint>",
deployment_name="<your-deployment>",
credential=AzureCliCredential(),
)
researcher = client.as_agent(
name="Researcher",
instructions="Research and gather information on the given topic.",
)
writer = client.as_agent(
name="Writer",
instructions="Write clear, engaging content based on research.",
)
# Build a sequential workflow
workflow = SequentialBuilder(participants=[researcher, writer]).build()
# Convert the workflow to an agent
workflow_agent = workflow.as_agent(name="Content Pipeline Agent")
as_agent Parameters
| Parameter | Type | Description |
|---|---|---|
name |
str | None |
Optional display name for the agent. Auto-generated if not provided. |
Using Workflow Agents
Creating a Session
You can optionally create a session to manage conversation state across multiple turns:
# Create a new session for the conversation
session = await workflow_agent.create_session()
Note
Sessions are optional. If you don't pass a session to run(), the agent handles state internally.
If workflow.as_agent() is created without context_providers, the framework adds an InMemoryHistoryProvider() by default so multi-turn history works out of the box.
If you pass context_providers explicitly, that list is used as-is.
Non-Streaming Execution
For simple use cases where you want the complete response:
# You can pass a plain string as input
response = await workflow_agent.run("Write an article about AI trends")
for message in response.messages:
print(f"{message.author_name}: {message.text}")
Streaming Execution
For real-time updates as the workflow executes:
async for update in workflow_agent.run(
"Write an article about AI trends",
stream=True,
):
if update.text:
print(update.text, end="", flush=True)
Handling External Input Requests
When a workflow contains executors that request external input (using request_info), these requests are surfaced as function calls in the agent response. The function call uses the name WorkflowAgent.REQUEST_INFO_FUNCTION_NAME:
from agent_framework import Content, Message, WorkflowAgent
response = await workflow_agent.run("Process my request")
# Look for function calls in the response
human_review_function_call = None
for message in response.messages:
for content in message.contents:
if content.name == WorkflowAgent.REQUEST_INFO_FUNCTION_NAME:
human_review_function_call = content
Providing Responses to Pending Requests
To continue workflow execution after an external input request, create a function result and send it back:
if human_review_function_call:
# Parse the request arguments
request = WorkflowAgent.RequestInfoFunctionArgs.from_json(
human_review_function_call.arguments
)
# Create a response (your custom response type)
result_data = MyResponseType(approved=True, feedback="Looks good")
# Create the function call result
function_result = Content.from_function_result(
call_id=human_review_function_call.call_id,
result=result_data,
)
# Send the response back to continue the workflow
response = await workflow_agent.run(Message("tool", [function_result]))
Complete Example
Here's a complete example demonstrating a workflow agent with streaming output:
import asyncio
import os
from agent_framework.azure import AzureOpenAIResponsesClient
from agent_framework.orchestrations import SequentialBuilder
from azure.identity import AzureCliCredential
async def main():
# Set up the chat client
client = AzureOpenAIResponsesClient(
project_endpoint=os.environ["AZURE_AI_PROJECT_ENDPOINT"],
deployment_name=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
credential=AzureCliCredential(),
)
# Create specialized agents
researcher = client.as_agent(
name="Researcher",
instructions="Research the given topic and provide key facts.",
)
writer = client.as_agent(
name="Writer",
instructions="Write engaging content based on the research provided.",
)
reviewer = client.as_agent(
name="Reviewer",
instructions="Review the content and provide a final polished version.",
)
# Build a sequential workflow
workflow = SequentialBuilder(participants=[researcher, writer, reviewer]).build()
# Convert to a workflow agent
workflow_agent = workflow.as_agent(name="Content Creation Pipeline")
# Run the workflow
print("Starting workflow...")
print("=" * 60)
current_author = None
async for update in workflow_agent.run(
"Write about quantum computing",
stream=True,
):
# Show when different agents are responding
if update.author_name and update.author_name != current_author:
if current_author:
print("\n" + "-" * 40)
print(f"\n[{update.author_name}]:")
current_author = update.author_name
if update.text:
print(update.text, end="", flush=True)
print("\n" + "=" * 60)
print("Workflow completed!")
if __name__ == "__main__":
asyncio.run(main())
Understanding Event Conversion
When a workflow runs as an agent, workflow events are converted to agent responses. The type of response depends on how you call run():
run(): Returns anAgentResponsecontaining the complete result after the workflow finishesrun(..., stream=True): Returns an async iterable ofAgentResponseUpdateobjects as the workflow executes, providing real-time updates
During execution, internal workflow events are mapped to agent responses as follows:
| Workflow Event | Agent Response |
|---|---|
event.type == "output" |
Passed through as AgentResponseUpdate (streaming) or aggregated into AgentResponse (non-streaming) |
event.type == "request_info" |
Converted to function call content using WorkflowAgent.REQUEST_INFO_FUNCTION_NAME |
| Other events | Ignored (workflow-internal only) |
This conversion allows you to use the standard agent interface while still having access to detailed workflow information when needed.
Use Cases
1. Complex Agent Pipelines
Wrap a multi-agent workflow as a single agent for use in applications:
User Request --> [Workflow Agent] --> Final Response
|
+-- Researcher Agent
+-- Writer Agent
+-- Reviewer Agent
2. Agent Composition
Use workflow agents as components in larger systems:
- A workflow agent can be used as a tool by another agent
- Multiple workflow agents can be orchestrated together
- Workflow agents can be nested within other workflows
3. API Integration
Expose complex workflows through APIs that expect the standard Agent interface, enabling:
- Chat interfaces that use sophisticated backend workflows
- Integration with existing agent-based systems
- Gradual migration from simple agents to complex workflows