工作流事件系统提供工作流执行的可观测性。 事件会在执行过程中的关键节点触发,并可通过流式处理进行实时处理。
内置事件类型
// Workflow lifecycle events
WorkflowStartedEvent // Workflow execution begins
WorkflowOutputEvent // Workflow outputs data
WorkflowErrorEvent // Workflow encounters an error
WorkflowWarningEvent // Workflow encountered a warning
// Executor events
ExecutorInvokedEvent // Executor starts processing
ExecutorCompletedEvent // Executor finishes processing
ExecutorFailedEvent // Executor encounters an error
AgentResponseEvent // An agent run produces output
AgentResponseUpdateEvent // An agent run produces a streaming update
// Superstep events
SuperStepStartedEvent // Superstep begins
SuperStepCompletedEvent // Superstep completes
// Request events
RequestInfoEvent // A request is issued
注释
当代理使用需要审批的工具时,RequestInfoEvent 通常携带一个 ToolApprovalRequestContent 有效负载,用于需要人工审批的工具调用。 有关处理这些事件的详细信息,请参阅 Human-in-the-Loop 。
# All events use the unified WorkflowEvent class with a type discriminator:
# Workflow lifecycle events
WorkflowEvent.type == "started" # Workflow execution begins
WorkflowEvent.type == "status" # Workflow state changed (use .state)
WorkflowEvent.type == "output" # Workflow produces a terminal (final) output
WorkflowEvent.type == "intermediate" # Workflow produces an intermediate (observational) output
WorkflowEvent.type == "failed" # Workflow terminated with error (use .details)
WorkflowEvent.type == "error" # Non-fatal error from user code
WorkflowEvent.type == "warning" # Workflow encountered a warning
# Executor events
WorkflowEvent.type == "executor_invoked" # Executor starts processing
WorkflowEvent.type == "executor_completed" # Executor finishes processing
WorkflowEvent.type == "executor_failed" # Executor encounters an error
WorkflowEvent.type == "data" # Deprecated alias for "intermediate"
# Superstep events
WorkflowEvent.type == "superstep_started" # Superstep begins
WorkflowEvent.type == "superstep_completed" # Superstep completes
# Request events
WorkflowEvent.type == "request_info" # A request is issued
注释
当智能体使用需要审批的工具时,对于需要人工审批的工具调用,request_info 事件通常会携带一个包含 type == "function_approval_request" 的 Content 有效负载。 有关处理这些事件的详细信息,请参阅 Human-in-the-Loop 。
注释
"output" 和 "intermediate" 是两个输出鉴别器。 被指定为终端输出源的执行程序会发出 "output" 事件(由 WorkflowRunResult.get_outputs() 处理)。 被指定为中间输出源的执行程序会发出 "intermediate" 事件(由 WorkflowRunResult.get_intermediate_outputs() 处理)。
"data" 类型是 "intermediate" 的已弃用别名,并将在未来版本中移除;在新代码中,建议优先基于 "intermediate" 进行筛选。
Go 事件通过 workflow.Event 实现,并通过 Data() 公开其有效负载。 使用类型开关检查其类型化字段:
| 事件类型 | 有效负载和用途 |
|---|---|
workflow.StartedEvent |
启动输入处理周期。
Message 包含输入。 |
workflow.OutputEvent |
指定的执行器在 Output 中输出一个值。
Tags 标识中间输出。 |
workflow.ErrorEvent |
在Error中报告错误。 设置后,SubWorkflowID 标识嵌套工作流。 |
workflow.WorkflowWarningEvent |
在Message中报告一个警告。 |
workflow.ExecutorInvokedEvent |
执行器开始处理。
ExecutorID 标识它,并 Message 包含其输入。 |
workflow.ExecutorCompletedEvent |
执行程序完成处理。
Result 包含其结果。 |
workflow.ExecutorFailedEvent |
执行器失败。
ExecutorID 和 Error 用于标识失败。 |
workflow.SuperStepStartedEvent |
一个 superstep 开始了。
StepNumber 和 StartInfo用于描述失败。 |
workflow.SuperStepCompletedEvent |
一个超步已完成。
CompletionInfo 描述待处理的工作、请求和任何检查点。 |
workflow.RequestInfoEvent |
Request 包含一个可由宿主程序响应的外部请求。 |
workflow.RequestHaltEvent |
执行器请求暂停。
Result 包含其有效负载(如果有)。 |
Go 对终端输出和中间输出都使用 OutputEvent。 调用 IsIntermediate() 来区分它们;它不使用 Python 中单独的 "output" 和 "intermediate" 判别字段。
托管智能体也使用 OutputEvent,并在启用相应事件时使用 *agent.ResponseUpdate 或 *agent.Response 有效负载。 Go 没有定义单独的 AgentResponseEvent 和 AgentResponseUpdateEvent 类型。 有关配置,请参阅 Agent 执行器。
使用事件
using Microsoft.Agents.AI.Workflows;
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
switch (evt)
{
case ExecutorInvokedEvent invoke:
Console.WriteLine($"Starting {invoke.ExecutorId}");
break;
case ExecutorCompletedEvent complete:
Console.WriteLine($"Completed {complete.ExecutorId}: {complete.Data}");
break;
case WorkflowOutputEvent output:
Console.WriteLine($"Workflow output: {output.Data}");
return;
case WorkflowErrorEvent error:
Console.WriteLine($"Workflow error: {error.Exception}");
return;
}
}
from agent_framework import WorkflowEvent
async for event in workflow.run(input_message, stream=True):
if event.type == "executor_invoked":
print(f"Starting {event.executor_id}")
elif event.type == "executor_completed":
print(f"Completed {event.executor_id}: {event.data}")
elif event.type == "intermediate":
print(f"Intermediate output from {event.executor_id}: {event.data}")
elif event.type == "output":
print(f"Terminal output: {event.data}")
return
elif event.type == "error":
print(f"Workflow error: {event.data}")
return
对 Go 工作流事件使用类型开关。 单独处理迭代器错误和失败事件:接收输出不保证工作流的其余部分成功。
观察事件
inproc.Default.Run 会推进到下一个暂停点并累积事件。 运行可以因等待外部输入而暂停;停止并不一定表示已完成。
以下函数会打印执行器活动和输出、返回失败信息并关闭运行:
import (
"context"
"errors"
"fmt"
"github.com/microsoft/agent-framework-go/workflow"
"github.com/microsoft/agent-framework-go/workflow/inproc"
)
func observeEvents(
ctx context.Context, wf *workflow.Workflow, input any,
) (err error) {
run, err := inproc.Default.Run(ctx, wf, input)
if err != nil {
return err
}
defer func() {
err = errors.Join(err, run.Close(context.WithoutCancel(ctx)))
}()
for event := range run.NewEvents() {
switch event := event.(type) {
case workflow.ExecutorInvokedEvent:
fmt.Printf("Starting %s\n", event.ExecutorID)
case workflow.ExecutorCompletedEvent:
fmt.Printf("Completed %s: %v\n",
event.ExecutorID, event.Result)
case workflow.OutputEvent:
kind := "Terminal"
if event.IsIntermediate() {
kind = "Intermediate"
}
fmt.Printf("%s output from %s: %v\n",
kind, event.ExecutorID, event.Output)
case workflow.ErrorEvent:
return event.Error
case workflow.ExecutorFailedEvent:
return fmt.Errorf("executor %q failed: %w",
event.ExecutorID, event.Error)
}
}
return nil
}
NewEvents() 返回自上一次调用以来累积的事件。 即使你提前停止迭代,调用它时它的书签也会前移。 使用 OutgoingEvents() 重播所有累积的事件,而不是再次调用 NewEvents()。
流媒体事件
使用 RunStreaming 在事件到达时对其进行观察。 此函数用于观察不需要外部输入的工作流:
import (
"context"
"errors"
"fmt"
"github.com/microsoft/agent-framework-go/workflow"
"github.com/microsoft/agent-framework-go/workflow/inproc"
)
func streamEvents(
ctx context.Context, wf *workflow.Workflow, input any,
) (err error) {
run, err := inproc.Default.RunStreaming(ctx, wf, input)
if err != nil {
return err
}
defer func() {
err = errors.Join(err, run.Close(context.WithoutCancel(ctx)))
}()
for event, streamErr := range run.WatchStream(ctx) {
if streamErr != nil {
return streamErr
}
switch event := event.(type) {
case workflow.OutputEvent:
kind := "Terminal"
if event.IsIntermediate() {
kind = "Intermediate"
}
fmt.Printf("%s output from %s: %v\n",
kind, event.ExecutorID, event.Output)
case workflow.ErrorEvent:
return event.Error
case workflow.ExecutorFailedEvent:
return fmt.Errorf("executor %q failed: %w",
event.ExecutorID, event.Error)
}
}
return nil
}
WatchStream 当工作流具有挂起的外部请求时,会一直等待。 在将其用于请求驱动的工作流时,处理 RequestInfoEvent 并通过 SendResponse 发送匹配响应。
如果使用方必须在暂停时返回而不等待响应,请改用 WatchUntilHalt。 同一时间只能有一个事件迭代器消费流式运行中的事件。 有关请求处理和恢复执行的信息,请参阅人工参与的工作流。
自定义事件
自定义事件允许执行程序在工作流执行期间发出特定于域的信号,以满足应用程序的需求。 一些示例用例包括:
- 跟踪进度 - 报告中间步骤,以便调用方可以显示状态更新。
- 发出诊断 - 在不更改工作流输出的情况下显示警告、指标或调试信息。
- 中继域数据 - 实时将结构化有效负载(例如数据库写入、工具调用)推送到侦听器。
定义自定义事件
通过子类化 WorkflowEvent定义自定义事件。 基本构造函数接受一个可选的object? data有效负载,该有效负载通过Data属性公开。
using Microsoft.Agents.AI.Workflows;
// Simple event with a string payload
internal sealed class ProgressEvent(string step) : WorkflowEvent(step) { }
// Event with a structured payload
internal sealed class MetricsEvent(MetricsData metrics) : WorkflowEvent(metrics) { }
在 Python 中,直接使用 WorkflowEvent 类和自定义类型鉴别器字符串来创建自定义事件。 参数 type 和 data 携带所有信息。
from agent_framework import WorkflowEvent
# Create a custom event with a custom type string and payload
event = WorkflowEvent(type="progress", data="Step 1 complete")
# Custom event with a structured payload
event = WorkflowEvent(type="metrics", data={"latency_ms": 42, "tokens": 128})
注释
事件类型 "started", "status"并 "failed" 保留用于框架生命周期通知。 如果执行程序尝试发出其中一种类型,则会忽略该事件并记录警告。
通过创建实现 workflow.Event 接口的类型来定义自定义事件。 该方法 Data 返回事件有效负载。
import "github.com/microsoft/agent-framework-go/workflow"
type ProgressEvent struct {
Step string
}
func (e ProgressEvent) Data() any {
return e.Step
}
var _ workflow.Event = ProgressEvent{}
发出自定义事件
通过在 IWorkflowContext 上调用 AddEventAsync,从执行程序的消息处理程序发出自定义事件:
using Microsoft.Agents.AI.Workflows;
internal sealed class ProgressEvent(string step) : WorkflowEvent(step) { }
internal sealed partial class CustomExecutor() : Executor("CustomExecutor")
{
[MessageHandler]
private async ValueTask HandleAsync(string message, IWorkflowContext context)
{
await context.AddEventAsync(new ProgressEvent("Validating input"));
// Executor logic...
await context.AddEventAsync(new ProgressEvent("Processing complete"));
}
}
通过在 WorkflowContext 上调用 add_event,从处理程序发出自定义事件:
from agent_framework import (
handler,
Executor,
WorkflowContext,
WorkflowEvent,
)
class CustomExecutor(Executor):
@handler
async def handle(self, message: str, ctx: WorkflowContext[str]) -> None:
await ctx.add_event(WorkflowEvent(type="progress", data="Validating input"))
# Executor logic...
await ctx.add_event(WorkflowEvent(type="progress", data="Processing complete"))
通过在 AddEvent 上调用 workflow.Context,从执行器处理程序发出自定义事件:
import "github.com/microsoft/agent-framework-go/workflow"
customExecutor := workflow.NewExecutor("CustomExecutor", func(ctx *workflow.Context, message string) error {
if err := ctx.AddEvent(ProgressEvent{Step: "Validating input"}); err != nil {
return err
}
// Executor logic...
return ctx.AddEvent(ProgressEvent{Step: "Processing complete"})
}).Bind()
自定义事件不需要 WithOutputFrom:AddEvent 可以直接发出这些事件。 如果还需要常规工作流输出,请使用 YieldOutput 并指定输出源。
处理自定义事件
使用模式匹配筛选事件流中的自定义事件类型:
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
{
switch (evt)
{
case ProgressEvent progress:
Console.WriteLine($"Progress: {progress.Data}");
break;
case WorkflowOutputEvent output:
Console.WriteLine($"Done: {output.Data}");
return;
}
}
根据自定义类型鉴别器字符串进行筛选:
async for event in workflow.run(input_message, stream=True):
if event.type == "progress":
print(f"Progress: {event.data}")
elif event.type == "output":
print(f"Done: {event.data}")
return
使用类型开关或类型断言筛选事件流中的自定义事件类型:
for evt, err := range run.WatchStream(ctx) {
if err != nil {
return err
}
switch e := evt.(type) {
case ProgressEvent:
fmt.Printf("Progress: %v\n", e.Data())
case workflow.OutputEvent:
fmt.Printf("Done: %v\n", e.Output)
case workflow.ErrorEvent:
return e.Error
case workflow.ExecutorFailedEvent:
return fmt.Errorf("executor %q failed: %w", e.ExecutorID, e.Error)
}
}
后续步骤
相关主题: