Executor は、ワークフロー内のメッセージを処理する基本的な構成要素です。 型指定されたメッセージを受信し、操作を実行し、出力メッセージまたはイベントを生成できる自律処理ユニットです。
概要
各 Executor には一意の識別子があり、特定のメッセージの種類を処理できます。 Executor は次のようになります。
- カスタム ロジック コンポーネント — データの処理、API の呼び出し、メッセージの変換
- AI エージェント — LLM を使用して応答を生成する ( ワークフローのエージェントを参照)
Important
C# で Executor メッセージ ハンドラーを定義する推奨される方法は、[MessageHandler]から派生するpartial クラス内のメソッドでExecutor属性を使用することです。 これにより、ハンドラーの登録にコンパイル時のソース生成が使用され、パフォーマンスの向上、コンパイル時の検証、ネイティブ AOT の互換性が提供されます。
基本的な Executor 構造体
Executor は、 Executor 基底クラスから派生し、 [MessageHandler] 属性を使用してハンドラー メソッドを宣言します。 ソース生成を有効にするには、クラスに partial マークを付ける必要があります。
using Microsoft.Agents.AI.Workflows;
internal sealed partial class UppercaseExecutor() : Executor("UppercaseExecutor")
{
[MessageHandler]
private ValueTask<string> HandleAsync(string message, IWorkflowContext context)
{
string result = message.ToUpperInvariant();
return ValueTask.FromResult(result); // Return value is automatically sent to connected executors
}
}
値を返さずに手動でメッセージを送信することもできます。
internal sealed partial class UppercaseExecutor() : Executor("UppercaseExecutor")
{
[MessageHandler]
private async ValueTask HandleAsync(string message, IWorkflowContext context)
{
string result = message.ToUpperInvariant();
await context.SendMessageAsync(result); // Manually send messages to connected executors
}
}
複数の入力の種類
複数の [MessageHandler] メソッドを定義して、複数の入力の種類を処理します。
internal sealed partial class SampleExecutor() : Executor("SampleExecutor")
{
[MessageHandler]
private ValueTask<string> HandleStringAsync(string message, IWorkflowContext context)
{
return ValueTask.FromResult(message.ToUpperInvariant());
}
[MessageHandler]
private ValueTask<int> HandleIntAsync(int message, IWorkflowContext context)
{
return ValueTask.FromResult(message * 2);
}
}
関数ベースのエグゼキュータ들
BindExecutor拡張メソッドを使用して関数から Executor を作成します。
Func<string, string> uppercaseFunc = s => s.ToUpperInvariant();
var uppercase = uppercaseFunc.BindExecutor("UppercaseExecutor");
基本的な Executor 構造体
Executor は、 Executor 基底クラスから継承します。 各 Executor は、 @handler デコレーターで修飾されたメソッドを使用します。 ハンドラーには、処理するメッセージの種類を指定するための適切な型注釈が必要です。
from agent_framework import (
Executor,
WorkflowContext,
handler,
)
class UpperCase(Executor):
@handler
async def to_upper_case(self, text: str, ctx: WorkflowContext[str]) -> None:
"""Convert the input to uppercase and forward it to the next node."""
await ctx.send_message(text.upper())
Function-Based Executors
@executor デコレーターを使用して関数から Executor を作成します。
from agent_framework import (
WorkflowContext,
executor,
)
@executor(id="upper_case_executor")
async def upper_case(text: str, ctx: WorkflowContext[str]) -> None:
"""Convert the input to uppercase and forward it to the next node."""
await ctx.send_message(text.upper())
複数の入力の種類
複数のハンドラーを定義して、複数の入力型を処理します。
class SampleExecutor(Executor):
@handler
async def to_upper_case(self, text: str, ctx: WorkflowContext[str]) -> None:
await ctx.send_message(text.upper())
@handler
async def double_integer(self, number: int, ctx: WorkflowContext[int]) -> None:
await ctx.send_message(number * 2)
明示的な型パラメーター
型注釈の代わりに、デコレーター パラメーターを使用して型を明示的に指定できます。
Important
明示的な型パラメーターを使用する場合は、デコレーターを使用 してすべての 型を指定する必要があります。明示的なパラメーターと型注釈を混在させることはできません。
input パラメーターは必須です。outputとworkflow_outputは省略可能です。
class ExplicitTypesExecutor(Executor):
@handler(input=str, output=str)
async def to_upper_case(self, text, ctx) -> None:
await ctx.send_message(text.upper())
@handler(input=str | int, output=str)
async def handle_mixed(self, message, ctx) -> None:
await ctx.send_message(str(message).upper())
@handler(input=str, output=int, workflow_output=bool)
async def process_with_workflow_output(self, message, ctx) -> None:
await ctx.send_message(len(message))
await ctx.yield_output(True)
WorkflowContext オブジェクト
WorkflowContextは、実行中にワークフローと対話するためのメソッドを提供します。
-
send_message— 接続された Executor にメッセージを送信する -
yield_output— 呼び出し元に返される/ストリーミングされたワークフロー出力を生成する
class OutputExecutor(Executor):
@handler
async def handle(self, message: str, ctx: WorkflowContext[Never, str]) -> None:
await ctx.yield_output("Hello, World!")
ハンドラーがメッセージを送信せず、出力を生成しない場合、型パラメーターは必要ありません。
class LogExecutor(Executor):
@handler
async def handle(self, message: str, ctx: WorkflowContext) -> None:
print("Doing some work...")