Implementation:Microsoft Semantic kernel OrchestrationResult GetValueAsync
Overview
OrchestrationResult<T>.GetValueAsync(timeout) is the API for collecting the final output from a multi-agent orchestration in Microsoft Semantic Kernel. It acts as a future/promise that blocks until the orchestration completes or the specified timeout expires. Combined with runtime.RunUntilIdleAsync(), it forms the complete result collection pattern for all orchestration types.
Source reference: dotnet/samples/GettingStartedWithAgents/Orchestration/Step01_Concurrent.cs:L57-66
Principle page: Orchestration Result Collection
Principle:Microsoft_Semantic_kernel_Orchestration_Result_Collection
Code Reference
OrchestrationResult<T> Class
public class OrchestrationResult<T>
{
public Task<T> GetValueAsync(TimeSpan timeout);
}
Complementary Runtime Method
// Called after GetValueAsync to ensure complete cleanup
public class InProcessRuntime
{
public Task RunUntilIdleAsync(CancellationToken cancellationToken = default);
}
Type Parameter Variants
| Orchestration Type | Result Type | Description |
|---|---|---|
ConcurrentOrchestration |
OrchestrationResult<string[]> |
Array of strings, one per participating agent. Order matches the agent order passed to the constructor. |
GroupChatOrchestration |
OrchestrationResult<string> |
Single string containing the final message from the last agent to speak in the group chat. |
HandoffOrchestration |
OrchestrationResult<string> |
Single string containing the final response from whichever agent last handled the conversation. |
Method Parameters
| Parameter | Type | Description |
|---|---|---|
timeout |
TimeSpan |
The maximum time to wait for the orchestration to complete. If the timeout expires before results are available, a TimeoutException is thrown.
|
I/O Contract
Input
result.GetValueAsync(timeout)
├── result: OrchestrationResult<T> → Returned by orchestration.InvokeAsync()
└── timeout: TimeSpan → Maximum wait duration (e.g., TimeSpan.FromSeconds(300))
runtime.RunUntilIdleAsync(cancellationToken?)
└── Ensures all in-flight messages are processed after result collection
Output
For ConcurrentOrchestration → Task<string[]>
├── string[0]: First agent's response
├── string[1]: Second agent's response
└── string[N]: Nth agent's response
Order matches agent order in ConcurrentOrchestration constructor
For GroupChatOrchestration → Task<string>
└── The final message produced by the last agent to speak
For HandoffOrchestration → Task<string>
└── The final response from the last agent that handled the conversation
Error Cases
TimeoutException
└── Thrown when GetValueAsync timeout expires before orchestration completes
├── Cause: Agents took longer than expected (slow model responses, many turns)
└── Remedy: Increase timeout or reduce orchestration complexity
OperationCanceledException
└── Thrown when the operation is cancelled via CancellationToken
Complete Three-Step Pattern
Step 1: Invoke → OrchestrationResult<T> result = await orchestration.InvokeAsync(input, runtime)
Step 2: Await → T value = await result.GetValueAsync(TimeSpan.FromSeconds(N))
Step 3: Cleanup → await runtime.RunUntilIdleAsync()
Usage Examples
Concurrent Orchestration Result Collection
InProcessRuntime runtime = new();
await runtime.StartAsync();
ChatCompletionAgent writer = new()
{
Name = "Writer",
Instructions = "Write a short story on the given topic.",
Kernel = kernel
};
ChatCompletionAgent reviewer = new()
{
Name = "Reviewer",
Instructions = "Write a critical review of the given topic.",
Kernel = kernel
};
ConcurrentOrchestration orchestration = new(writer, reviewer);
OrchestrationResult<string[]> result = await orchestration.InvokeAsync(
"Write a story about a brave knight", runtime);
// Await with 5-minute timeout
string[] results = await result.GetValueAsync(TimeSpan.FromSeconds(300));
await runtime.RunUntilIdleAsync();
Console.WriteLine($"Writer output: {results[0]}");
Console.WriteLine($"Reviewer output: {results[1]}");
Group Chat Result Collection
InProcessRuntime runtime = new();
await runtime.StartAsync();
GroupChatOrchestration groupChat = new(
new RoundRobinGroupChatManager { MaximumInvocationCount = 5 },
writer, reviewer);
OrchestrationResult<string> result = await groupChat.InvokeAsync(
"Write a haiku about autumn", runtime);
string finalOutput = await result.GetValueAsync(TimeSpan.FromSeconds(300));
await runtime.RunUntilIdleAsync();
Console.WriteLine($"Final group chat output: {finalOutput}");
Handoff Result Collection
InProcessRuntime runtime = new();
await runtime.StartAsync();
HandoffOrchestration handoff = new(
OrchestrationHandoffs.StartWith(triageAgent)
.Add(triageAgent, [billingAgent, refundAgent])
.Add(billingAgent, [triageAgent]),
triageAgent, billingAgent, refundAgent);
OrchestrationResult<string> result = await handoff.InvokeAsync(
"I was charged twice for my order", runtime);
string resolution = await result.GetValueAsync(TimeSpan.FromSeconds(300));
await runtime.RunUntilIdleAsync();
Console.WriteLine($"Customer resolution: {resolution}");
Timeout Handling
InProcessRuntime runtime = new();
await runtime.StartAsync();
ConcurrentOrchestration orchestration = new(agentA, agentB, agentC);
OrchestrationResult<string[]> result = await orchestration.InvokeAsync("Complex topic", runtime);
try
{
// Short timeout for time-sensitive operations
string[] results = await result.GetValueAsync(TimeSpan.FromSeconds(60));
Console.WriteLine("All agents completed within timeout.");
foreach (string r in results)
{
Console.WriteLine(r);
}
}
catch (TimeoutException)
{
Console.WriteLine("Orchestration did not complete within 60 seconds.");
}
finally
{
await runtime.RunUntilIdleAsync();
}
Full End-to-End Example
// 1. Build kernel
Kernel kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion("gpt-4o", apiKey)
.Build();
// 2. Create agents
ChatCompletionAgent writer = new()
{
Name = "Writer",
Instructions = "Write creative content on the given topic.",
Kernel = kernel
};
ChatCompletionAgent reviewer = new()
{
Name = "Reviewer",
Instructions = "Review content and provide constructive feedback.",
Kernel = kernel
};
// 3. Set up runtime
InProcessRuntime runtime = new();
await runtime.StartAsync();
// 4. Create and invoke orchestration
ConcurrentOrchestration orchestration = new(writer, reviewer);
OrchestrationResult<string[]> result = await orchestration.InvokeAsync(
"The beauty of mathematics", runtime);
// 5. Collect results with timeout
string[] outputs = await result.GetValueAsync(TimeSpan.FromSeconds(300));
// 6. Cleanup
await runtime.RunUntilIdleAsync();
// 7. Process results
Console.WriteLine("=== Writer ===");
Console.WriteLine(outputs[0]);
Console.WriteLine("=== Reviewer ===");
Console.WriteLine(outputs[1]);
Related Pages
- Orchestration Result Collection (Principle) -- The conceptual foundation for result collection.
- InProcessRuntime (Implementation) -- The runtime that provides
RunUntilIdleAsync. - Orchestration Runtime (Principle) -- The runtime lifecycle including idle state management.
- Orchestration Patterns (Implementation) -- The orchestrations that produce
OrchestrationResult<T>. - Multi-Agent Orchestration (Principle) -- The multi-agent patterns whose results are collected.
- ChatCompletionAgent (Implementation) -- The agents whose outputs are collected as results.