Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Executors sind die grundlegenden Bausteine, die Nachrichten in einem Workflow verarbeiten. Sie sind autonome Verarbeitungseinheiten, die eingegebene Nachrichten empfangen, Vorgänge ausführen und Ausgabemeldungen oder Ereignisse erzeugen können.
Überblick
Jeder Executor verfügt über einen eindeutigen Bezeichner und kann bestimmte Nachrichtentypen verarbeiten. Ausführende können sein:
- Benutzerdefinierte Logikkomponenten – Verarbeiten von Daten, Aufrufen von APIs oder Transformieren von Nachrichten
- KI-Agents – Verwenden von LLMs zum Generieren von Antworten (siehe Agents in Workflows)
Von Bedeutung
Die empfohlene Methode zum Definieren von Executor-Nachrichtenhandlern in C# besteht darin, das [MessageHandler]-Attribut für Methoden innerhalb einer partial-Klasse zu verwenden, die von Executor-Klasse abgeleitet ist. Dies verwendet die Generierung der Kompilierungszeitquelle für die Handlerregistrierung, bietet eine bessere Leistung, Kompilierungszeitüberprüfung und native AOT-Kompatibilität.
Grundlegende Executorstruktur
Executors leiten von der Executor Basisklasse ab und verwenden das [MessageHandler] Attribut zum Deklarieren von Handlermethoden. Die Klasse muss markiert partial werden, um die Quellgenerierung zu aktivieren.
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
}
}
Sie können Nachrichten auch manuell senden, ohne einen Wert zurückzugeben:
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
}
}
Mehrere Eingabetypen
Behandeln Sie mehrere Eingabetypen, indem Sie mehrere [MessageHandler] Methoden definieren:
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);
}
}
Funktionsbasierte Ausführungsumgebungen
Erstellen Sie einen Executor aus einer Funktion mithilfe der BindExecutor Erweiterungsmethode:
Func<string, string> uppercaseFunc = s => s.ToUpperInvariant();
var uppercase = uppercaseFunc.BindExecutor("UppercaseExecutor");
Grundlegende Executorstruktur
Executors erben von der Executor Basisklasse. Jeder Executor verwendet Methoden, die mit dem @handler Decorator versehen sind. Handler müssen über richtige Typanmerkungen verfügen, um die nachrichtentypen anzugeben, die sie verarbeiten.
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())
Funktionsbasierte Executors
Erstellen Sie einen Executor aus einer Funktion mithilfe des @executor Dekorators:
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())
Mehrere Eingabetypen
Behandeln Sie mehrere Eingabetypen, indem Sie mehrere Handler definieren:
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)
Explizite Typparameter
Als Alternative zu Typanmerkungen können Sie Typen explizit über Dekorierparameter angeben:
Von Bedeutung
Wenn Sie explizite Typparameter verwenden, müssen Sie alle Typen über den Dekorateur angeben . Sie können keine expliziten Parameter mit Typanmerkungen kombinieren. Der input Parameter ist erforderlich und outputworkflow_output optional.
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)
Das WorkflowContext-Objekt
Die WorkflowContext bietet Methoden für die Interaktion mit dem Workflow während der Ausführung:
-
send_message— Nachrichten an verbundene Executoren senden -
yield_output— Erstellen von Workflowausgaben, die an den Aufrufer zurückgegeben/gestreamt werden
class OutputExecutor(Executor):
@handler
async def handle(self, message: str, ctx: WorkflowContext[Never, str]) -> None:
await ctx.yield_output("Hello, World!")
Wenn ein Handler weder Nachrichten sendet noch Ausgaben liefert, ist kein Typparameter erforderlich:
class LogExecutor(Executor):
@handler
async def handle(self, message: str, ctx: WorkflowContext) -> None:
print("Doing some work...")