Events

工作流程事件系統提供對工作流程執行的可觀察性。 事件會在執行的關鍵點發布,並可透過串流即時觀看。

內建事件類型

// 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 酬載。 有關處理這些事件的細節,請參見「人機互動」一節。

# 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 酬載,以用於需要人工核准的工具呼叫。 有關處理這些事件的細節,請參見「人機互動」一節。

備註

"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 超級步驟開始。 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 類型。 關於配置,請參見 代理程式執行器。

消費事件

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{}

發出自訂事件

透過在AddEventAsync上呼叫IWorkflowContext,從執行者的訊息處理程序發出自訂事件:

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"))

透過在 workflow.Context 上呼叫 AddEvent,從執行程式處理常式發出自訂事件:

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)
    }
}

下一步

相關主題: