Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Med deklarativa arbetsflöden kan du definiera arbetsflödeslogik med YAML-konfigurationsfiler i stället för att skriva programmatisk kod. Den här metoden gör arbetsflöden enklare att läsa, ändra och dela mellan team.
Översikt
Med deklarativa arbetsflöden beskriver du vad arbetsflödet ska göra snarare än hur du ska implementera det. Ramverket hanterar den underliggande körningen och konverterar dina YAML-definitioner till körbara arbetsflödesdiagram.
Viktiga fördelar:
- Läsbart format: YAML-syntax är lätt att förstå, även för icke-utvecklare
- Bärbar: Arbetsflödesdefinitioner kan delas, versionshanteras och ändras utan kodändringar
- Snabb iteration: Ändra arbetsflödets beteende genom att redigera konfigurationsfiler
- Konsekvent struktur: Fördefinierade åtgärdstyper säkerställer att arbetsflöden följer bästa praxis
När du ska använda deklarativa eller programmatiska arbetsflöden
| Scenario | Rekommenderad metodik |
|---|---|
| Standardorkestreringsmönster | Deklarativt |
| Arbetsflöden som ändras ofta | Deklarativt |
| Icke-utvecklare behöver ändra arbetsflöden | Deklarativt |
| Komplex anpassad logik | Programmatic |
| Maximal flexibilitet och kontroll | Programmatic |
| Integrering med befintlig Python-kod | Programmatic |
Grundläggande YAML-struktur
YAML-strukturen skiljer sig något mellan C# och Python-implementeringar. Mer information finns i de språkspecifika avsnitten nedan.
Åtgärdstyper
Deklarativa arbetsflöden stöder en mängd olika åtgärdstyper som omfattar variabel hantering, kontrollflöde, agent- och verktygsanrop, HTTP- och MCP-integrering, mänsklig-i-slinga och konversationskontroll. Den fullständiga språkspecifika referensen visas i varje zon nedan. En tillgänglighetsmatris för snabbinsikter för båda språken finns i Snabbreferens för åtgärder längst ned i den här artikeln.
C# YAML-struktur
Deklarativa C#-arbetsflöden använder en utlösarbaserad struktur:
#
# Workflow description as a comment
#
kind: Workflow
trigger:
kind: OnConversationStart
id: my_workflow
actions:
- kind: ActionType
id: unique_action_id
displayName: Human readable name
# Action-specific properties
Strukturelement
| Komponent | Krävs | Description |
|---|---|---|
kind |
Ja | Måste vara Workflow |
trigger.kind |
Ja | Utlösartyp (vanligtvis OnConversationStart) |
trigger.id |
Ja | Unik identifierare för arbetsflödet |
trigger.actions |
Ja | Lista över åtgärder att utföra |
Python YAML-struktur
Python-deklarativa arbetsflöden använder en namnbaserad struktur med valfria indata:
name: my-workflow
description: A brief description of what this workflow does
inputs:
parameterName:
type: string
description: Description of the parameter
actions:
- kind: ActionType
id: unique_action_id
displayName: Human readable name
# Action-specific properties
Strukturelement
| Komponent | Krävs | Description |
|---|---|---|
name |
Ja | Unik identifierare för arbetsflödet |
description |
Nej. | Beskrivning som kan läsas av människor |
inputs |
Nej. | Indataparametrar som arbetsflödet accepterar |
actions |
Ja | Lista över åtgärder att utföra |
Förutsättningar
Kontrollera att du har följande innan du börjar:
- .NET 8.0 eller senare
- Ett Microsoft Foundry-projekt med minst en distribuerad agent
- Följande NuGet-paket har installerats:
dotnet add package Microsoft.Agents.AI.Workflows.Declarative --prerelease
dotnet add package Microsoft.Agents.AI.Workflows.Declarative.AzureAI --prerelease
- Om du tänker lägga till anropsåtgärden för MCP-verktyget i arbetsflödet installerar du även följande NuGet-paket:
dotnet add package Microsoft.Agents.AI.Workflows.Declarative.Mcp --prerelease
- Grundläggande kunskaper om YAML-syntax
- Förstå arbetsflödesbegrepp
Ditt första deklarativa arbetsflöde
Nu ska vi skapa ett enkelt arbetsflöde som hälsar på en användare baserat på deras indata.
Steg 1: Skapa YAML-filen
Skapa en fil med namnet greeting-workflow.yaml:
#
# This workflow demonstrates a simple greeting based on user input.
# The user's message is captured via System.LastMessage.
#
# Example input:
# Alice
#
kind: Workflow
trigger:
kind: OnConversationStart
id: greeting_workflow
actions:
# Capture the user's input from the last message
- kind: SetVariable
id: capture_name
displayName: Capture user name
variable: Local.userName
value: =System.LastMessage.Text
# Set a greeting prefix
- kind: SetVariable
id: set_greeting
displayName: Set greeting prefix
variable: Local.greeting
value: Hello
# Build the full message using an expression
- kind: SetVariable
id: build_message
displayName: Build greeting message
variable: Local.message
value: =Concat(Local.greeting, ", ", Local.userName, "!")
# Send the greeting to the user
- kind: SendActivity
id: send_greeting
displayName: Send greeting to user
activity: =Local.message
Steg 2: Konfigurera agentleverantören
Skapa ett C#-konsolprogram för att köra arbetsflödet. Konfigurera först agentprovidern som ansluter till Foundry:
using Azure.Identity;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Agents.AI.Workflows.Declarative;
using Microsoft.Extensions.Configuration;
// Load configuration (endpoint should be set in user secrets or environment variables)
IConfiguration configuration = new ConfigurationBuilder()
.AddUserSecrets<Program>()
.AddEnvironmentVariables()
.Build();
string foundryEndpoint = configuration["FOUNDRY_PROJECT_ENDPOINT"]
?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT not configured");
// Create the agent provider that connects to Foundry
// WARNING: DefaultAzureCredential is convenient for development but requires
// careful consideration in production environments.
AzureAgentProvider agentProvider = new(
new Uri(foundryEndpoint),
new DefaultAzureCredential());
Steg 3: Skapa och kör arbetsflödet
// Define workflow options with the agent provider
DeclarativeWorkflowOptions options = new(agentProvider)
{
Configuration = configuration,
// LoggerFactory = loggerFactory, // Optional: Enable logging
// ConversationId = conversationId, // Optional: Continue existing conversation
};
// Build the workflow from the YAML file
string workflowPath = Path.Combine(AppContext.BaseDirectory, "greeting-workflow.yaml");
Workflow workflow = DeclarativeWorkflowBuilder.Build<string>(workflowPath, options);
Console.WriteLine($"Loaded workflow from: {workflowPath}");
Console.WriteLine(new string('-', 40));
// Create a checkpoint manager (in-memory for this example)
CheckpointManager checkpointManager = CheckpointManager.CreateInMemory();
// Execute the workflow with input
string input = "Alice";
StreamingRun run = await InProcessExecution.RunStreamingAsync(
workflow,
input,
checkpointManager);
// Process workflow events
await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync())
{
switch (workflowEvent)
{
case MessageActivityEvent activityEvent:
Console.WriteLine($"Activity: {activityEvent.Message}");
break;
case AgentResponseEvent responseEvent:
Console.WriteLine($"Response: {responseEvent.Response.Text}");
break;
case WorkflowErrorEvent errorEvent:
Console.WriteLine($"Error: {errorEvent.Data}");
break;
}
}
Console.WriteLine("Workflow completed!");
Förväntade utdata
Loaded workflow from: C:\path\to\greeting-workflow.yaml
----------------------------------------
Activity: Hello, Alice!
Workflow completed!
Grundläggande begrepp
Variabelnamnområden
Deklarativa arbetsflöden i C# använder namnrymdsvariabler för att organisera tillstånd:
| Namespace | Description | Example |
|---|---|---|
Local.* |
Variabler som är lokala för arbetsflödet | Local.message |
System.* |
Systembaserade värden |
System.ConversationId, System.LastMessage |
Anmärkning
Deklarativa C#-arbetsflöden använder inte Workflow.Inputs- eller Workflow.Outputs-namnrymder. Indata tas emot via System.LastMessage och utdata skickas via SendActivity åtgärder.
Systemvariabler
| Variable | Description |
|---|---|
System.ConversationId |
Aktuellt konversations-ID |
System.LastMessage |
Det senaste användarmeddelandet |
System.LastMessage.Text |
Textinnehåll i det senaste meddelandet |
Uttrycksspråk
Värden som föregås av = utvärderas som uttryck med hjälp av PowerFx-uttrycksspråket:
# Literal value (no evaluation)
value: Hello
# Expression (evaluated at runtime)
value: =Concat("Hello, ", Local.userName)
# Access last message text
value: =System.LastMessage.Text
Vanliga funktioner är:
-
Concat(str1, str2, ...)– Sammanfoga strängar -
If(condition, trueValue, falseValue)– Villkorsuttryck -
IsBlank(value)– Kontrollera om värdet är tomt -
Upper(text)/Lower(text)– Skiftlägeskonvertering -
Find(searchText, withinText)– Hitta text i strängen -
MessageText(message)– Extrahera text från ett meddelandeobjekt -
UserMessage(text)– Skapa ett användarmeddelande från text -
AgentMessage(text)– Skapa ett agentmeddelande från text
Konfigurationsalternativ
Klassen DeclarativeWorkflowOptions tillhandahåller konfiguration för arbetsflödeskörning:
DeclarativeWorkflowOptions options = new(agentProvider)
{
// Application configuration for variable substitution
Configuration = configuration,
// Continue an existing conversation (optional)
ConversationId = "existing-conversation-id",
// Enable logging (optional)
LoggerFactory = loggerFactory,
// MCP tool handler for InvokeMcpTool actions (optional)
McpToolHandler = mcpToolHandler,
// HTTP request handler for HttpRequestAction actions (optional)
HttpRequestHandler = new DefaultHttpRequestHandler(),
// PowerFx expression limits (optional)
MaximumCallDepth = 50,
MaximumExpressionLength = 10000,
// Telemetry configuration (optional)
ConfigureTelemetry = opts => { /* configure telemetry */ },
TelemetryActivitySource = activitySource,
};
Konfiguration av agentprovider
Ansluter AzureAgentProvider arbetsflödet till Foundry-agenter:
using Azure.Identity;
using Microsoft.Agents.AI.Workflows.Declarative;
// Create the agent provider with Azure credentials
AzureAgentProvider agentProvider = new(
new Uri("https://your-project.api.azureml.ms"),
new DefaultAzureCredential())
{
// Optional: Define functions that agents can automatically invoke
Functions = [
AIFunctionFactory.Create(myPlugin.GetData),
AIFunctionFactory.Create(myPlugin.ProcessItem),
],
// Optional: Allow concurrent function invocation
AllowConcurrentInvocation = true,
// Optional: Allow multiple tool calls per response
AllowMultipleToolCalls = true,
};
Arbetsflödeskörning
Använd InProcessExecution för att köra arbetsflöden och hantera händelser:
using Microsoft.Agents.AI.Workflows;
using Microsoft.Agents.AI.Workflows.Checkpointing;
// Create checkpoint manager (choose in-memory or file-based)
CheckpointManager checkpointManager = CheckpointManager.CreateInMemory();
// Or persist to disk:
// var checkpointFolder = Directory.CreateDirectory("./checkpoints");
// var checkpointManager = CheckpointManager.CreateJson(
// new FileSystemJsonCheckpointStore(checkpointFolder));
// Start workflow execution
StreamingRun run = await InProcessExecution.RunStreamingAsync(
workflow,
input,
checkpointManager);
// Process events as they occur
await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync())
{
switch (workflowEvent)
{
case MessageActivityEvent activity:
Console.WriteLine($"Message: {activity.Message}");
break;
case AgentResponseUpdateEvent streamEvent:
Console.Write(streamEvent.Update.Text); // Streaming text
break;
case AgentResponseEvent response:
Console.WriteLine($"Agent: {response.Response.Text}");
break;
case RequestInfoEvent request:
// Handle external input requests (human-in-the-loop)
var userInput = await GetUserInputAsync(request);
await run.SendResponseAsync(request.Request.CreateResponse(userInput));
break;
case SuperStepCompletedEvent checkpoint:
// Checkpoint created - can resume from here if needed
var checkpointInfo = checkpoint.CompletionInfo?.Checkpoint;
break;
case WorkflowErrorEvent error:
Console.WriteLine($"Error: {error.Data}");
break;
}
}
Återuppta från kontrollpunkter
Arbetsflöden kan återupptas från kontrollpunkter för feltolerans:
// Save checkpoint info when workflow yields
CheckpointInfo? lastCheckpoint = null;
await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync())
{
if (workflowEvent is SuperStepCompletedEvent checkpointEvent)
{
lastCheckpoint = checkpointEvent.CompletionInfo?.Checkpoint;
}
}
// Later: Resume from the saved checkpoint
if (lastCheckpoint is not null)
{
// Recreate the workflow (can be on a different machine)
Workflow workflow = DeclarativeWorkflowBuilder.Build<string>(workflowPath, options);
StreamingRun resumedRun = await InProcessExecution.ResumeStreamingAsync(
workflow,
lastCheckpoint,
checkpointManager);
// Continue processing events...
}
Kontrollpunkter för AOT och Trim-Aggressive
När du publicerar med Native AOT (dotnet publish -p:PublishAot=true) eller på annat sätt inaktiverar System.Text.Jsons reservmekanism för reflektion (<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>), misslyckas standardanropet till CheckpointManager.CreateJson(store) vid checkpointsbekräftelse eller återhydrering.
Declarative-workflow-paketet levereras med en källkodsgenererad JsonSerializerOptions instans, DeclarativeWorkflowJsonOptions.Default, som täcker alla typer i declarative-package som passerar genom kontrollpunktspipelinen. Skicka det som det andra argumentet till CheckpointManager.CreateJson:
using Microsoft.Agents.AI.Workflows.Checkpointing;
using Microsoft.Agents.AI.Workflows.Declarative;
// AOT-safe: type info is resolved via the source-generated JsonSerializerContext,
// so no runtime reflection is required.
CheckpointManager checkpointManager = CheckpointManager.CreateJson(
store,
DeclarativeWorkflowJsonOptions.Default);
Anmärkning
Att skicka DeclarativeWorkflowJsonOptions.Default är säkert att använda även i miljöer som inte är AOT. Det är en drop-in-uppgradering för CheckpointManager.CreateJson(store) – reflektionsaktiverade appar ser inga beteendeändringar. Använd det utan förbehåll så att samma kod fortsätter att fungera om du senare publicerar med AOT eller trimning.
DeclarativeWorkflowJsonOptions är markerad [Experimental("MAAI001")]. Ignorera diagnostiken på anropsplatsen eller i projektfilen:
<PropertyGroup>
<NoWarn>$(NoWarn);MAAI001</NoWarn>
</PropertyGroup>
Registrera användardefinierade typer
Om dina arbetsflödesindata, anpassade ActionExecutorResult.Result nyttolaster eller icke-primitiva argument för godkännandebegäran är användardefinierade typer, klonar Default och lägger du till din egen källgenererade lösning:
// Compose: declarative-package types + your app's source-gen context.
JsonSerializerOptions options = new(DeclarativeWorkflowJsonOptions.Default);
options.TypeInfoResolverChain.Add(MyAppJsonContext.Default);
options.MakeReadOnly();
CheckpointManager checkpointManager = CheckpointManager.CreateJson(store, options);
Var MyAppJsonContext är en JsonSerializerContext du definierar för appens typer:
[JsonSourceGenerationOptions(JsonSerializerDefaults.Web)]
[JsonSerializable(typeof(MyWorkflowInput))]
[JsonSerializable(typeof(MyCustomResult))]
internal sealed partial class MyAppJsonContext : JsonSerializerContext;
Tip
Ett komplett körbart exempel – inklusive YAML-arbetsflödet, en agent som stöds av AzureCliCredential och ett observerbart läge för "ta bort alternativen för att se felet" – finns i AotCheckpointing-exemplet i dotnet/samples/03-workflows/Declarative/AotCheckpointing. Exemplet anger .csprojJsonSerializerIsReflectionEnabledByDefault=false för att återskapa AOT-feltillståndet utan att kräva en fullständig AOT-publicering.
Åtgärdsreferens
Åtgärder är byggstenarna i deklarativa arbetsflöden. Varje åtgärd utför en specifik åtgärd och åtgärderna körs sekventiellt i den ordning de visas i YAML-filen.
Åtgärdsstruktur
Alla åtgärder har gemensamma egenskaper:
- kind: ActionType # Required: The type of action
id: unique_id # Optional: Unique identifier for referencing
displayName: Name # Optional: Human-readable name for logging
# Action-specific properties...
Åtgärder för variabelhantering
SetVariable
Anger en variabel till ett angivet värde.
- kind: SetVariable
id: set_greeting
displayName: Set greeting message
variable: Local.greeting
value: Hello World
Med ett uttryck:
- kind: SetVariable
variable: Local.fullName
value: =Concat(Local.firstName, " ", Local.lastName)
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
variable |
Ja | Variabelsökväg (t.ex. Local.name, Workflow.Outputs.result) |
value |
Ja | Värde som ska anges (literal eller uttryck) |
SetMultipleVariables
Anger flera variabler i en enda åtgärd.
- kind: SetMultipleVariables
id: initialize_vars
displayName: Initialize variables
variables:
Local.counter: 0
Local.status: pending
Local.message: =Concat("Processing order ", Local.orderId)
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
variables |
Ja | Kartläggning av variabelsökvägar till värden |
SetTextVariable
Anger en textvariabel till ett angivet strängvärde.
- kind: SetTextVariable
id: set_text
displayName: Set text content
variable: Local.description
value: This is a text description
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
variable |
Ja | Sökväg för variabelns textvärde |
value |
Ja | Textvärde som ska anges |
ResetVariable
Rensar en variabels värde.
- kind: ResetVariable
id: clear_counter
variable: Local.counter
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
variable |
Ja | Variabel sökväg för återställning |
ClearAllVariables
Återställer alla variabler i den aktuella kontexten.
- kind: ClearAllVariables
id: clear_all
displayName: Clear all workflow variables
ParseValue
Extraherar eller konverterar data till ett användbart format.
- kind: ParseValue
id: parse_json
displayName: Parse JSON response
source: =Local.rawResponse
variable: Local.parsedData
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
source |
Ja | Uttryck som returnerar det värde som ska tolkas |
variable |
Ja | Variabelsökväg för att lagra det tolkade resultatet |
EditTableV2
Ändrar data i ett strukturerat tabellformat.
- kind: EditTableV2
id: update_table
displayName: Update configuration table
table: Local.configTable
operation: update
row:
key: =Local.settingName
value: =Local.settingValue
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
table |
Ja | Variabelstig till tabellen |
operation |
Ja | Åtgärdstyp (lägg till, uppdatera, ta bort) |
row |
Ja | Raddata för åtgärden |
Kontrollera flödesåtgärder
If
Utför åtgärder villkorligt baserat på ett villkor.
- kind: If
id: check_age
displayName: Check user age
condition: =Local.age >= 18
then:
- kind: SendActivity
activity:
text: "Welcome, adult user!"
else:
- kind: SendActivity
activity:
text: "Welcome, young user!"
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
condition |
Ja | Uttryck som utvärderas till sant/falskt |
then |
Ja | Åtgärder som ska köras om villkoret är sant |
else |
Nej. | Åtgärder som ska köras om villkoret är falskt |
ConditionGroup
Utvärderar flera villkor som en switch/case-instruktion.
- kind: ConditionGroup
id: route_by_category
displayName: Route based on category
conditions:
- condition: =Local.category = "electronics"
id: electronics_branch
actions:
- kind: SetVariable
variable: Local.department
value: Electronics Team
- condition: =Local.category = "clothing"
id: clothing_branch
actions:
- kind: SetVariable
variable: Local.department
value: Clothing Team
elseActions:
- kind: SetVariable
variable: Local.department
value: General Support
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
conditions |
Ja | Lista över villkor/åtgärdspar (första matchningen vinner) |
elseActions |
Nej. | Åtgärder om inget villkor matchar |
Foreach
Itererar över en samling.
- kind: Foreach
id: process_items
displayName: Process each item
source: =Local.items
itemName: item
indexName: index
actions:
- kind: SendActivity
activity:
text: =Concat("Processing item ", index, ": ", item)
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
source |
Ja | Uttryck som returnerar en samling |
itemName |
Nej. | Variabelnamn för aktuellt objekt (standard: item) |
indexName |
Nej. | Variabelnamn för aktuellt index (standard: index) |
actions |
Ja | Åtgärder som ska köras för varje objekt |
BreakLoop
Avslutar den aktuella loopen omedelbart.
- kind: Foreach
source: =Local.items
actions:
- kind: If
condition: =item = "stop"
then:
- kind: BreakLoop
- kind: SendActivity
activity:
text: =item
ContinueLoop
Hoppar till nästa iteration av loopen.
- kind: Foreach
source: =Local.numbers
actions:
- kind: If
condition: =item < 0
then:
- kind: ContinueLoop
- kind: SendActivity
activity:
text: =Concat("Positive number: ", item)
GotoAction
Hoppar till en specifik åtgärd med ID.
- kind: SetVariable
id: start_label
variable: Local.attempts
value: =Local.attempts + 1
- kind: SendActivity
activity:
text: =Concat("Attempt ", Local.attempts)
- kind: If
condition: =And(Local.attempts < 3, Not(Local.success))
then:
- kind: GotoAction
actionId: start_label
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
actionId |
Ja | ID för åtgärden att hoppa till |
Utdataåtgärder
SendActivity
Skickar ett meddelande till användaren.
- kind: SendActivity
id: send_welcome
displayName: Send welcome message
activity:
text: "Welcome to our service!"
Med ett uttryck:
- kind: SendActivity
activity:
text: =Concat("Hello, ", Local.userName, "! How can I help you today?")
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
activity |
Ja | Aktiviteten som ska skickas |
activity.text |
Ja | Meddelandetext (literal eller uttryck) |
Åtgärder vid agentanrop
AnropaAzureAgent
Anropar Foundry-agenten.
Grundläggande anrop:
- kind: InvokeAzureAgent
id: call_assistant
displayName: Call assistant agent
agent:
name: AssistantAgent
conversationId: =System.ConversationId
Med konfiguration av indata och utdata:
- kind: InvokeAzureAgent
id: call_analyst
displayName: Call analyst agent
agent:
name: AnalystAgent
conversationId: =System.ConversationId
input:
messages: =Local.userMessage
arguments:
topic: =Local.topic
output:
responseObject: Local.AnalystResult
messages: Local.AnalystMessages
autoSend: true
Med en extern slinga som fortsätter tills villkoret är uppfyllt:
- kind: InvokeAzureAgent
id: support_agent
agent:
name: SupportAgent
input:
externalLoop:
when: =Not(Local.IsResolved)
output:
responseObject: Local.SupportResult
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
agent.name |
Ja | Namnet på den registrerade agenten |
conversationId |
Nej. | Konversationskontextidentifierare |
input.messages |
Nej. | Meddelanden som ska skickas till agenten |
input.arguments |
Nej. | Ytterligare argument för agenten |
input.externalLoop.when |
Nej. | Villkor för att fortsätta agentloopen |
output.responseObject |
Nej. | Sökväg för att spara agentens svar |
output.messages |
Nej. | Sökväg för att lagra konversationsmeddelanden |
output.autoSend |
Nej. | Skicka automatiskt svar till användaren |
Verktyg och HTTP-åtgärder
InvokeFunctionTool
Anropar ett funktionsverktyg direkt från arbetsflödet utan att gå igenom en AI-agent.
- kind: InvokeFunctionTool
id: invoke_get_data
displayName: Get data from function
functionName: GetUserData
conversationId: =System.ConversationId
requireApproval: true
arguments:
userId: =Local.userId
output:
autoSend: true
result: Local.UserData
messages: Local.FunctionMessages
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
functionName |
Ja | Namnet på funktionen som ska anropas |
conversationId |
Nej. | Konversationskontextidentifierare |
requireApproval |
Nej. | Om du vill kräva användargodkännande före körning |
arguments |
Nej. | Argument som ska skickas till funktionen |
output.result |
Nej. | Sökväg för att lagra funktionsresultat |
output.messages |
Nej. | Sökväg för att lagra funktionsmeddelanden |
output.autoSend |
Nej. | Skicka resultatet automatiskt till användaren |
C#-installation för InvokeFunctionTool:
Funktioner måste registreras med WorkflowRunner eller hanteras via externa indata:
// Define functions that can be invoked
AIFunction[] functions = [
AIFunctionFactory.Create(myPlugin.GetUserData),
AIFunctionFactory.Create(myPlugin.ProcessOrder),
];
// Create workflow runner with functions
WorkflowRunner runner = new(functions) { UseJsonCheckpoints = true };
await runner.ExecuteAsync(workflowFactory.CreateWorkflow, input);
AnropaMcpTool
Anropar ett verktyg på en MCP-server (Model Context Protocol).
- kind: InvokeMcpTool
id: invoke_docs_search
displayName: Search documentation
serverUrl: https://learn.microsoft.com/api/mcp
serverLabel: microsoft_docs
toolName: microsoft_docs_search
conversationId: =System.ConversationId
requireApproval: false
headers:
X-Custom-Header: custom-value
arguments:
query: =Local.SearchQuery
output:
autoSend: true
result: Local.SearchResults
Med anslutningsnamn för värdbaserade scenarier:
- kind: InvokeMcpTool
id: invoke_hosted_mcp
serverUrl: https://mcp.ai.azure.com
toolName: my_tool
# Connection name is used in hosted scenarios to connect to a ProjectConnectionId in Foundry.
# Note: This feature is not fully supported yet.
connection:
name: my-foundry-connection
output:
result: Local.ToolResult
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
serverUrl |
Ja | URL för MCP-servern |
serverLabel |
Nej. | Läsbar etikett för servern |
toolName |
Ja | Namnet på verktyget som ska anropas |
conversationId |
Nej. | Konversationskontextidentifierare |
requireApproval |
Nej. | Om du vill kräva användargodkännande |
arguments |
Nej. | Argument som ska skickas till verktyget |
headers |
Nej. | Anpassade HTTP-huvuden för begäran |
connection.name |
Nej. | Namngiven anslutning för värdbaserade scenarier (ansluter till ProjectConnectionId i Foundry, stöds inte fullt ut ännu) |
output.result |
Nej. | Sökväg för att spara verktygsresultat |
output.messages |
Nej. | Sökväg för att lagra resultatmeddelanden |
output.autoSend |
Nej. | Skicka resultatet automatiskt till användaren |
C#-installation för InvokeMcpTool:
Konfigurera McpToolHandler i din arbetsflödesfabrik.
using Azure.Core;
using Azure.Identity;
using Microsoft.Agents.AI.Workflows.Declarative;
// Create MCP tool handler with authentication callback
DefaultAzureCredential credential = new();
DefaultMcpToolHandler mcpToolHandler = new(
httpClientProvider: async (serverUrl, cancellationToken) =>
{
if (serverUrl.StartsWith("https://mcp.ai.azure.com", StringComparison.OrdinalIgnoreCase))
{
// Acquire token for Azure MCP server
AccessToken token = await credential.GetTokenAsync(
new TokenRequestContext(["https://mcp.ai.azure.com/.default"]),
cancellationToken);
HttpClient httpClient = new();
httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token.Token);
return httpClient;
}
// Return null for servers that don't require authentication
return null;
});
// Configure workflow factory with MCP handler
WorkflowFactory workflowFactory = new("workflow.yaml", foundryEndpoint)
{
McpToolHandler = mcpToolHandler
};
HttpRequestAction
Skickar en HTTP-begäran via den konfigurerade IHttpRequestHandler. Lyckade JSON-svar parsas före tilldelningen, och icke-2xx-svar resulterar i att åtgärden misslyckas.
- kind: HttpRequestAction
id: fetch_repo_info
method: GET
url: "https://api.github.com/repos/Microsoft/agent-framework"
headers:
Accept: application/vnd.github+json
User-Agent: agent-framework
queryParameters:
per_page: 10
response: Local.RepoInfo
responseHeaders: Local.RepoHeaders
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
url |
Ja | Absolut URL för begäran |
method |
Nej. | HTTP-metod; standardvärdet för GET |
headers |
Nej. | Förfrågningsrubriker |
queryParameters |
Nej. | Frågeparametrar som läggs till i URL:en |
body |
Nej. | Begärandetext; använda kind: json, raw, eller none |
requestTimeoutInMilliseconds |
Nej. | Tidsgräns per begäran |
conversationId |
Nej. | Lägger till en lyckad svarstext i konversationen |
response |
Nej. | Sökväg för att lagra den tolkade svarstexten |
responseHeaders |
Nej. | Sökväg för att lagra svarshuvuden |
C#-installation för HttpRequestAction:
Ange HttpRequestHandler när arbetsflödet skapas. Använd en anpassad hanterare när du behöver omförsök eller URL-tillåtslista.
DeclarativeWorkflowOptions options = new(agentProvider)
{
HttpRequestHandler = new DefaultHttpRequestHandler(),
};
Workflow workflow = DeclarativeWorkflowBuilder.Build<string>("workflow.yaml", options);
Människa-i-loopen-åtgärder
Question
Ställer en fråga till användaren och lagrar svaret.
- kind: Question
id: ask_name
displayName: Ask for user name
question:
text: "What is your name?"
variable: Local.userName
default: "Guest"
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
question.text |
Ja | Frågan att ställa |
variable |
Ja | Sökväg för att lagra svaret |
default |
Nej. | Standardvärde om inget svar |
RequestExternalInput
Begär indata från ett externt system eller en process.
- kind: RequestExternalInput
id: request_approval
displayName: Request manager approval
prompt:
text: "Please provide approval for this request."
variable: Local.approvalResult
default: "pending"
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
prompt.text |
Ja | Beskrivning av nödvändiga indata |
variable |
Ja | Sökväg för att lagra indata |
default |
Nej. | Standardvärde |
Åtgärder för arbetsflödeskontroll
EndWorkflow
Avslutar arbetsflödeskörningen.
- kind: EndWorkflow
id: finish
displayName: End workflow
SlutSamtal
Avslutar den aktuella konversationen.
- kind: EndConversation
id: end_chat
displayName: End conversation
SkapaKonversation
Skapar en ny konversationskontext.
- kind: CreateConversation
id: create_new_conv
displayName: Create new conversation
conversationId: Local.NewConversationId
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
conversationId |
Ja | Sökväg för att lagra det nya konversations-ID:t |
Konversationsåtgärder (endast C#)
LäggTillKonversationsMeddelande
Lägger till ett meddelande i en konversationstråd.
- kind: AddConversationMessage
id: add_system_message
displayName: Add system context
conversationId: =System.ConversationId
message:
role: system
content: =Local.contextInfo
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
conversationId |
Ja | Målkonversationsidentifierare |
message |
Ja | Meddelande att lägga till |
message.role |
Ja | Meddelanderoll (system, användare, assistent) |
message.content |
Ja | Meddelandeinnehåll |
KopieraKonversationsmeddelanden
Kopierar meddelanden från en konversation till en annan.
- kind: CopyConversationMessages
id: copy_context
displayName: Copy conversation context
sourceConversationId: =Local.SourceConversation
targetConversationId: =System.ConversationId
limit: 10
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
sourceConversationId |
Ja | Källkonversationsidentifierare |
targetConversationId |
Ja | Målkonversationsidentifierare |
limit |
Nej. | Maximalt antal meddelanden att kopiera |
HämtaKonversationsMeddelande
Hämtar ett specifikt meddelande från en konversation.
- kind: RetrieveConversationMessage
id: get_message
displayName: Get specific message
conversationId: =System.ConversationId
messageId: =Local.targetMessageId
variable: Local.retrievedMessage
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
conversationId |
Ja | Identifierare för konversation |
messageId |
Ja | Meddelandeidentifierare för att hämta |
variable |
Ja | Sökväg för lagring av det hämtade meddelandet |
HämtaSamtalsMeddelanden
Hämtar flera meddelanden från en konversation.
- kind: RetrieveConversationMessages
id: get_history
displayName: Get conversation history
conversationId: =System.ConversationId
limit: 20
newestFirst: true
variable: Local.conversationHistory
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
conversationId |
Ja | Identifierare för konversation |
limit |
Nej. | Maximalt antal meddelanden att hämta (standard: 20) |
newestFirst |
Nej. | Returnera i fallande ordning |
after |
Nej. | Markör för sidnumrering |
before |
Nej. | Markör för sidnumrering |
variable |
Ja | Sökväg för att lagra hämtade meddelanden |
Snabbreferens för åtgärder
| Åtgärd | Kategori | C# | python | Description |
|---|---|---|---|---|
SetVariable |
Variable | ✅ | ✅ | Ange en enskild variabel |
SetMultipleVariables |
Variable | ✅ | ✅ | Ange flera variabler |
SetTextVariable |
Variable | ✅ | ✅ | Ställ in en textvariabel |
ResetVariable |
Variable | ✅ | ✅ | Rensa en variabel |
ClearAllVariables |
Variable | ✅ | ✅ | Rensa alla variabler |
ParseValue |
Variable | ✅ | ✅ | Parsa/transformera data |
EditTableV2 |
Variable | ✅ | ✅ | Ändra tabelldata |
If |
Kontrollflöde | ✅ | ✅ | Villkorlig grenning |
ConditionGroup |
Kontrollflöde | ✅ | ✅ | Växel för flera grener |
Foreach |
Kontrollflöde | ✅ | ✅ | Iterera över samlingar |
BreakLoop |
Kontrollflöde | ✅ | ✅ | Avsluta nuvarande loop |
ContinueLoop |
Kontrollflöde | ✅ | ✅ | Hoppa till nästa iteration |
GotoAction |
Kontrollflöde | ✅ | ✅ | Hoppa till åtgärd med ID |
SendActivity |
Utgång | ✅ | ✅ | Skicka meddelande till användaren |
InvokeAzureAgent |
Handläggare | ✅ | ✅ | Anropa Azure AI-agent |
InvokeFunctionTool |
Verktyg | ✅ | ✅ | Anropa funktionen direkt |
InvokeMcpTool |
Verktyg | ✅ | ✅ | Anropa MCP-serververktyget |
HttpRequestAction |
HTTP | ✅ | ✅ | Anropa HTTP-slutpunkt |
Question |
Human-in-the-Loop (mänsklig interaktion i processen) | ✅ | ✅ | Ställ en fråga till användaren |
RequestExternalInput |
Human-in-the-Loop (mänsklig interaktion i processen) | ✅ | ✅ | Begära externa indata |
EndWorkflow |
Arbetsflödeskontroll | ✅ | ✅ | Avsluta arbetsflöde |
EndConversation |
Arbetsflödeskontroll | ✅ | ✅ | Avsluta konversationen |
CreateConversation |
Arbetsflödeskontroll | ✅ | ✅ | Skapa ny konversation |
AddConversationMessage |
Konversation | ✅ | ❌ | Lägg till meddelande i tråden |
CopyConversationMessages |
Konversation | ✅ | ❌ | Kopiera meddelanden |
RetrieveConversationMessage |
Konversation | ✅ | ❌ | Hämta ett enskilt meddelande |
RetrieveConversationMessages |
Konversation | ✅ | ❌ | Hämta flera meddelanden |
Avancerade mönster
Orkestrering med flera agenter
Sekventiell agent-pipeline
Skicka arbete genom flera agenter i följd.
#
# Sequential agent pipeline for content creation
#
kind: Workflow
trigger:
kind: OnConversationStart
id: content_workflow
actions:
# First agent: Research
- kind: InvokeAzureAgent
id: invoke_researcher
displayName: Research phase
conversationId: =System.ConversationId
agent:
name: ResearcherAgent
# Second agent: Write draft
- kind: InvokeAzureAgent
id: invoke_writer
displayName: Writing phase
conversationId: =System.ConversationId
agent:
name: WriterAgent
# Third agent: Edit
- kind: InvokeAzureAgent
id: invoke_editor
displayName: Editing phase
conversationId: =System.ConversationId
agent:
name: EditorAgent
C#-installation:
using Azure.AI.Projects;
using Azure.AI.Projects.OpenAI;
using Azure.Identity;
// Ensure agents exist in Foundry
AIProjectClient aiProjectClient = new(foundryEndpoint, new DefaultAzureCredential());
await aiProjectClient.CreateAgentAsync(
agentName: "ResearcherAgent",
agentDefinition: new DeclarativeAgentDefinition(modelName)
{
Instructions = "You are a research specialist..."
},
agentDescription: "Research agent for content pipeline");
// Create and run workflow
WorkflowFactory workflowFactory = new("content-pipeline.yaml", foundryEndpoint);
WorkflowRunner runner = new();
await runner.ExecuteAsync(workflowFactory.CreateWorkflow, "Create content about AI");
Routning av villkorsstyrd agent
Dirigera begäranden till olika agenter baserat på villkor.
#
# Route to specialized support agents based on category
#
kind: Workflow
trigger:
kind: OnConversationStart
id: support_router
actions:
# Capture category from user input or set via another action
- kind: SetVariable
id: set_category
variable: Local.category
value: =System.LastMessage.Text
- kind: ConditionGroup
id: route_request
displayName: Route to appropriate agent
conditions:
- condition: =Local.category = "billing"
id: billing_route
actions:
- kind: InvokeAzureAgent
id: billing_agent
agent:
name: BillingAgent
conversationId: =System.ConversationId
- condition: =Local.category = "technical"
id: technical_route
actions:
- kind: InvokeAzureAgent
id: technical_agent
agent:
name: TechnicalAgent
conversationId: =System.ConversationId
elseActions:
- kind: InvokeAzureAgent
id: general_agent
agent:
name: GeneralAgent
conversationId: =System.ConversationId
Verktygsintegreringsmönster
Förhämtning av data med InvokeFunctionTool
Hämta data innan du anropar en agent:
#
# Pre-fetch menu data before agent interaction
#
kind: Workflow
trigger:
kind: OnConversationStart
id: menu_workflow
actions:
# Pre-fetch today's specials
- kind: InvokeFunctionTool
id: get_specials
functionName: GetSpecials
requireApproval: true
output:
autoSend: true
result: Local.Specials
# Agent uses pre-fetched data
- kind: InvokeAzureAgent
id: menu_agent
conversationId: =System.ConversationId
agent:
name: MenuAgent
input:
messages: =UserMessage("Describe today's specials: " & Local.Specials)
MCP-verktygsintegrering
Anropa extern server med MCP:
#
# Search documentation using MCP
#
kind: Workflow
trigger:
kind: OnConversationStart
id: docs_search
actions:
- kind: SetVariable
variable: Local.SearchQuery
value: =System.LastMessage.Text
# Search Microsoft Learn
- kind: InvokeMcpTool
id: search_docs
serverUrl: https://learn.microsoft.com/api/mcp
toolName: microsoft_docs_search
conversationId: =System.ConversationId
arguments:
query: =Local.SearchQuery
output:
result: Local.SearchResults
autoSend: true
# Summarize results with agent
- kind: InvokeAzureAgent
id: summarize
agent:
name: SummaryAgent
conversationId: =System.ConversationId
input:
messages: =UserMessage("Summarize these search results")
Förutsättningar
Kontrollera att du har följande innan du börjar:
- Python 3.10– 3.13 (Python 3.14 stöds inte ännu på grund av PowerFx-kompatibilitet)
- Agent Framework-deklarativt paket installerat:
pip install agent-framework-declarative --pre
Det här paketet hämtar den underliggande agent-framework-core filen automatiskt.
- Grundläggande kunskaper om YAML-syntax
- Förstå arbetsflödesbegrepp
Ditt första deklarativa arbetsflöde
Nu ska vi skapa ett enkelt arbetsflöde som hälsar en användare med namn.
Steg 1: Skapa YAML-filen
Skapa en fil med namnet greeting-workflow.yaml:
name: greeting-workflow
description: A simple workflow that greets the user
inputs:
name:
type: string
description: The name of the person to greet
actions:
# Set a greeting prefix
- kind: SetVariable
id: set_greeting
displayName: Set greeting prefix
variable: Local.greeting
value: Hello
# Build the full message using an expression
- kind: SetVariable
id: build_message
displayName: Build greeting message
variable: Local.message
value: =Concat(Local.greeting, ", ", Workflow.Inputs.name, "!")
# Send the greeting to the user
- kind: SendActivity
id: send_greeting
displayName: Send greeting to user
activity:
text: =Local.message
# Store the result in outputs
- kind: SetVariable
id: set_output
displayName: Store result in outputs
variable: Workflow.Outputs.greeting
value: =Local.message
Steg 2: Läs in och kör arbetsflödet
Skapa en Python-fil för att köra arbetsflödet:
import asyncio
from pathlib import Path
from agent_framework.declarative import WorkflowFactory
async def main() -> None:
"""Run the greeting workflow."""
# Create a workflow factory
factory = WorkflowFactory()
# Load the workflow from YAML
workflow_path = Path(__file__).parent / "greeting-workflow.yaml"
workflow = factory.create_workflow_from_yaml_path(workflow_path)
print(f"Loaded workflow: {workflow.name}")
print("-" * 40)
# Run with a name input
result = await workflow.run({"name": "Alice"})
for output in result.get_outputs():
print(f"Output: {output}")
for output in result.get_intermediate_outputs():
print(f"Intermediate: {output}")
if __name__ == "__main__":
asyncio.run(main())
Förväntade utdata
Loaded workflow: greeting-workflow
----------------------------------------
Output: Hello, Alice!
Grundläggande begrepp
Variabelnamnområden
Deklarativa arbetsflöden använder namnområdesvariabler för att ordna tillstånd:
| Namespace | Description | Example |
|---|---|---|
Local.* |
Variabler som är lokala för arbetsflödet | Local.message |
Workflow.Inputs.* |
Indataparametrar | Workflow.Inputs.name |
Workflow.Outputs.* |
Utdatavärden | Workflow.Outputs.result |
System.* |
Systembaserade värden | System.ConversationId |
Uttrycksspråk
Värden som är prefixade med = utvärderas som uttryck.
# Literal value (no evaluation)
value: Hello
# Expression (evaluated at runtime)
value: =Concat("Hello, ", Workflow.Inputs.name)
Vanliga funktioner är:
-
Concat(str1, str2, ...)– Sammanfoga strängar -
If(condition, trueValue, falseValue)– Villkorsuttryck -
IsBlank(value)– Kontrollera om värdet är tomt
Åtgärdstyper
Deklarativa arbetsflöden stöder olika åtgärdstyper:
| Kategori | Åtgärder |
|---|---|
| Variabelhantering |
SetVariable, , SetMultipleVariablesResetVariable |
| Kontrollflöde |
If, ConditionGroup, Foreach, BreakLoop, , , ContinueLoopGotoAction |
| Utgång | SendActivity |
| Agentanrop | InvokeAzureAgent |
| Anrop av verktyg |
InvokeFunctionTool, InvokeMcpTool |
| HTTP | HttpRequestAction |
| Human-in-the-Loop (mänsklig interaktion i processen) |
Question, RequestExternalInput |
| Arbetsflödeskontroll |
EndWorkflow, , EndConversationCreateConversation |
Åtgärdsreferens
Åtgärder är byggstenarna i deklarativa arbetsflöden. Varje åtgärd utför en specifik åtgärd och åtgärderna körs sekventiellt i den ordning de visas i YAML-filen.
Åtgärdsstruktur
Alla åtgärder har gemensamma egenskaper:
- kind: ActionType # Required: The type of action
id: unique_id # Optional: Unique identifier for referencing
displayName: Name # Optional: Human-readable name for logging
# Action-specific properties...
Åtgärder för variabelhantering
SetVariable
Anger en variabel till ett angivet värde.
- kind: SetVariable
id: set_greeting
displayName: Set greeting message
variable: Local.greeting
value: Hello World
Med ett uttryck:
- kind: SetVariable
variable: Local.fullName
value: =Concat(Workflow.Inputs.firstName, " ", Workflow.Inputs.lastName)
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
variable |
Ja | Variabelsökväg (t.ex. Local.name, Workflow.Outputs.result) |
value |
Ja | Värde som ska anges (literal eller uttryck) |
Anmärkning
Python stöder också åtgärdstypen SetValue, som använder path i stället för variable för målegenskapen. Både SetVariable (med variable) och SetValue (med path) uppnår samma resultat. Som exempel:
- kind: SetValue
id: set_greeting
path: Local.greeting
value: Hello World
SetMultipleVariables
Anger flera variabler i en enda åtgärd.
- kind: SetMultipleVariables
id: initialize_vars
displayName: Initialize variables
variables:
Local.counter: 0
Local.status: pending
Local.message: =Concat("Processing order ", Workflow.Inputs.orderId)
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
variables |
Ja | Kartläggning av variabelsökvägar till värden |
ResetVariable
Rensar en variabels värde.
- kind: ResetVariable
id: clear_counter
variable: Local.counter
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
variable |
Ja | Variabel sökväg för återställning |
Kontrollera flödesåtgärder
If
Utför åtgärder villkorligt baserat på ett villkor.
- kind: If
id: check_age
displayName: Check user age
condition: =Workflow.Inputs.age >= 18
then:
- kind: SendActivity
activity:
text: "Welcome, adult user!"
else:
- kind: SendActivity
activity:
text: "Welcome, young user!"
Kapslade villkor:
- kind: If
condition: =Workflow.Inputs.role = "admin"
then:
- kind: SendActivity
activity:
text: "Admin access granted"
else:
- kind: If
condition: =Workflow.Inputs.role = "user"
then:
- kind: SendActivity
activity:
text: "User access granted"
else:
- kind: SendActivity
activity:
text: "Access denied"
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
condition |
Ja | Uttryck som utvärderas till sant/falskt |
then |
Ja | Åtgärder som ska köras om villkoret är sant |
else |
Nej. | Åtgärder som ska köras om villkoret är falskt |
ConditionGroup
Utvärderar flera villkor som en switch/case-instruktion.
- kind: ConditionGroup
id: route_by_category
displayName: Route based on category
conditions:
- condition: =Workflow.Inputs.category = "electronics"
id: electronics_branch
actions:
- kind: SetVariable
variable: Local.department
value: Electronics Team
- condition: =Workflow.Inputs.category = "clothing"
id: clothing_branch
actions:
- kind: SetVariable
variable: Local.department
value: Clothing Team
- condition: =Workflow.Inputs.category = "food"
id: food_branch
actions:
- kind: SetVariable
variable: Local.department
value: Food Team
elseActions:
- kind: SetVariable
variable: Local.department
value: General Support
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
conditions |
Ja | Lista över villkor/åtgärdspar (första matchningen vinner) |
elseActions |
Nej. | Åtgärder om inget villkor matchar |
Foreach
Itererar över en samling.
- kind: Foreach
id: process_items
displayName: Process each item
source: =Workflow.Inputs.items
itemName: item
indexName: index
actions:
- kind: SendActivity
activity:
text: =Concat("Processing item ", index, ": ", item)
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
source |
Ja | Uttryck som returnerar en samling |
itemName |
Nej. | Variabelnamn för aktuellt objekt (standard: item) |
indexName |
Nej. | Variabelnamn för aktuellt index (standard: index) |
actions |
Ja | Åtgärder som ska köras för varje objekt |
BreakLoop
Avslutar den aktuella loopen omedelbart.
- kind: Foreach
source: =Workflow.Inputs.items
actions:
- kind: If
condition: =item = "stop"
then:
- kind: BreakLoop
- kind: SendActivity
activity:
text: =item
ContinueLoop
Hoppar till nästa iteration av loopen.
- kind: Foreach
source: =Workflow.Inputs.numbers
actions:
- kind: If
condition: =item < 0
then:
- kind: ContinueLoop
- kind: SendActivity
activity:
text: =Concat("Positive number: ", item)
GotoAction
Hoppar till en specifik åtgärd med ID.
- kind: SetVariable
id: start_label
variable: Local.attempts
value: =Local.attempts + 1
- kind: SendActivity
activity:
text: =Concat("Attempt ", Local.attempts)
- kind: If
condition: =And(Local.attempts < 3, Not(Local.success))
then:
- kind: GotoAction
actionId: start_label
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
actionId |
Ja | ID för åtgärden att hoppa till |
Utdataåtgärder
SendActivity
Skickar ett meddelande till användaren.
- kind: SendActivity
id: send_welcome
displayName: Send welcome message
activity:
text: "Welcome to our service!"
Med ett uttryck:
- kind: SendActivity
activity:
text: =Concat("Hello, ", Workflow.Inputs.name, "! How can I help you today?")
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
activity |
Ja | Aktiviteten som ska skickas |
activity.text |
Ja | Meddelandetext (literal eller uttryck) |
Åtgärder vid agentanrop
AnropaAzureAgent
Anropar en Azure AI-agent.
Grundläggande anrop:
- kind: InvokeAzureAgent
id: call_assistant
displayName: Call assistant agent
agent:
name: AssistantAgent
conversationId: =System.ConversationId
Med konfiguration av indata och utdata:
- kind: InvokeAzureAgent
id: call_analyst
displayName: Call analyst agent
agent:
name: AnalystAgent
conversationId: =System.ConversationId
input:
messages: =Local.userMessage
arguments:
topic: =Workflow.Inputs.topic
output:
responseObject: Local.AnalystResult
messages: Local.AnalystMessages
autoSend: true
Med en extern slinga som fortsätter tills villkoret är uppfyllt:
- kind: InvokeAzureAgent
id: support_agent
agent:
name: SupportAgent
input:
externalLoop:
when: =Not(Local.IsResolved)
output:
responseObject: Local.SupportResult
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
agent.name |
Ja | Namnet på den registrerade agenten |
conversationId |
Nej. | Konversationskontextidentifierare |
input.messages |
Nej. | Meddelanden som ska skickas till agenten |
input.arguments |
Nej. | Ytterligare argument för agenten |
input.externalLoop.when |
Nej. | Villkor för att fortsätta agentloopen |
output.responseObject |
Nej. | Sökväg för att spara agentens svar |
output.messages |
Nej. | Sökväg för att lagra konversationsmeddelanden |
output.autoSend |
Nej. | Skicka automatiskt svar till användaren |
Verktyg och HTTP-åtgärder
InvokeFunctionTool
Anropar en registrerad Python-funktion direkt från arbetsflödet utan att gå igenom en AI-agent.
- kind: InvokeFunctionTool
id: invoke_weather
displayName: Get weather data
functionName: get_weather
arguments:
location: =Local.location
unit: =Local.unit
output:
result: Local.weatherInfo
messages: Local.weatherToolCallItems
autoSend: true
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
functionName |
Ja | Namnet på den registrerade funktion som ska anropas |
arguments |
Nej. | Argument som ska skickas till funktionen |
output.result |
Nej. | Sökväg för att lagra funktionsresultatet |
output.messages |
Nej. | Sökväg för att lagra funktionsmeddelanden |
output.autoSend |
Nej. | Skicka resultatet automatiskt till användaren |
Python-installation för InvokeFunctionTool:
Funktioner måste registreras med hjälp av WorkflowFactoryregister_tool:
from agent_framework.declarative import WorkflowFactory
# Define your functions
def get_weather(location: str, unit: str = "F") -> dict:
"""Get weather information for a location."""
# Your implementation here
return {"location": location, "temp": 72, "unit": unit}
def format_message(template: str, data: dict) -> str:
"""Format a message template with data."""
return template.format(**data)
# Register functions with the factory
factory = (
WorkflowFactory()
.register_tool("get_weather", get_weather)
.register_tool("format_message", format_message)
)
# Load and run the workflow
workflow = factory.create_workflow_from_yaml_path("workflow.yaml")
result = await workflow.run({"location": "Seattle", "unit": "F"})
AnropaMcpTool
Anropar ett verktyg på en MCP-server via den konfigurerade MCPToolHandler.
- kind: InvokeMcpTool
id: search_docs
serverUrl: https://learn.microsoft.com/api/mcp
serverLabel: microsoft_docs
toolName: microsoft_docs_search
arguments:
query: =Local.searchQuery
output:
result: Local.searchResults
messages: Local.toolMessage
autoSend: true
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
serverUrl |
Ja | URL för MCP-server |
toolName |
Ja | Verktygsnamn på MCP-servern |
serverLabel |
Nej. | Mänsklig läsbar serveretikett |
arguments |
Nej. | Argument som skickas till verktyget |
headers |
Nej. | Förfrågningshuvuden; tomma värden ignoreras |
connection.name |
Nej. | Namngiven anslutning för anpassade hanterare |
conversationId |
Nej. | Lägger till lyckade verktygsutdata i konversationen |
requireApproval |
Nej. | Begär godkännande innan verktyget anropas |
output.result |
Nej. | Sökväg för att lagra utdata från parsade verktyg |
output.messages |
Nej. | Sökväg för att spara verktygsmeddelandet |
output.autoSend |
Nej. | Sänder verktygsutdata till arbetsflödesresultatet; standardvärdet för true. |
Python-inställning för InvokeMcpTool:
Skicka en MCP-verktygshanterare till WorkflowFactory. Använd en anpassad hanterare när du behöver autentisering, hanterade anslutningar eller URL-tillåtna listor.
from agent_framework.declarative import DefaultMCPToolHandler, WorkflowFactory
factory = WorkflowFactory(mcp_tool_handler=DefaultMCPToolHandler())
workflow = factory.create_workflow_from_yaml_path("workflow.yaml")
HttpRequestAction
Skickar en HTTP-begäran via den konfigurerade HttpRequestHandler. Lyckade JSON-svar parsas före tilldelningen, och icke-2xx-svar resulterar i att åtgärden misslyckas.
- kind: HttpRequestAction
id: fetch_repo_info
method: GET
url: =Concat("https://api.github.com/repos/", Local.repoName)
headers:
Accept: application/vnd.github+json
User-Agent: agent-framework
queryParameters:
per_page: 10
response: Local.repoInfo
responseHeaders: Local.repoHeaders
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
url |
Ja | Absolut URL för begäran |
method |
Nej. | HTTP-metod; standardvärdet för GET |
headers |
Nej. | Förfrågningsrubriker |
queryParameters |
Nej. | Frågeparametrar som läggs till i URL:en |
body |
Nej. | Begärandetext; använda kind: json, raw, eller none |
requestTimeoutInMilliseconds |
Nej. | Tidsgräns per begäran |
connection.name |
Nej. | Namngiven anslutning för anpassade hanterare |
conversationId |
Nej. | Lägger till en lyckad svarstext i konversationen |
response |
Nej. | Sökväg för att lagra den tolkade svarstexten |
responseHeaders |
Nej. | Sökväg för att lagra svarshuvuden |
Python-inställning för HttpRequestAction:
Skicka en HTTP-begärandehanterare till WorkflowFactory. Använd en anpassad hanterare när du behöver autentisering, återförsök eller URL-tillåtelselista.
from agent_framework.declarative import DefaultHttpRequestHandler, WorkflowFactory
factory = WorkflowFactory(http_request_handler=DefaultHttpRequestHandler())
workflow = factory.create_workflow_from_yaml_path("workflow.yaml")
Människa-i-loopen-åtgärder
Question
Ställer en fråga till användaren och lagrar svaret.
- kind: Question
id: ask_name
displayName: Ask for user name
question:
text: "What is your name?"
variable: Local.userName
default: "Guest"
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
question.text |
Ja | Frågan att ställa |
variable |
Ja | Sökväg för att lagra svaret |
default |
Nej. | Standardvärde om inget svar |
RequestExternalInput
Begär indata från ett externt system eller en process.
- kind: RequestExternalInput
id: request_approval
displayName: Request manager approval
prompt:
text: "Please provide approval for this request."
variable: Local.approvalResult
default: "pending"
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
prompt.text |
Ja | Beskrivning av nödvändiga indata |
variable |
Ja | Sökväg för att lagra indata |
default |
Nej. | Standardvärde |
Åtgärder för arbetsflödeskontroll
EndWorkflow
Avslutar arbetsflödeskörningen.
- kind: EndWorkflow
id: finish
displayName: End workflow
SlutSamtal
Avslutar den aktuella konversationen.
- kind: EndConversation
id: end_chat
displayName: End conversation
SkapaKonversation
Skapar en ny konversationskontext.
- kind: CreateConversation
id: create_new_conv
displayName: Create new conversation
conversationId: Local.NewConversationId
Egenskaper:
| Fastighet | Krävs | Description |
|---|---|---|
conversationId |
Ja | Sökväg för att lagra det nya konversations-ID:t |
Snabbreferens för åtgärder
| Åtgärd | Kategori | Description |
|---|---|---|
SetVariable |
Variable | Ange en enskild variabel |
SetMultipleVariables |
Variable | Ange flera variabler |
ResetVariable |
Variable | Rensa en variabel |
If |
Kontrollflöde | Villkorlig grenning |
ConditionGroup |
Kontrollflöde | Växel för flera grener |
Foreach |
Kontrollflöde | Iterera över samlingar |
BreakLoop |
Kontrollflöde | Avsluta nuvarande loop |
ContinueLoop |
Kontrollflöde | Hoppa till nästa iteration |
GotoAction |
Kontrollflöde | Hoppa till åtgärd med ID |
SendActivity |
Utgång | Skicka meddelande till användaren |
InvokeAzureAgent |
Handläggare | Anropa Azure AI-agent |
InvokeFunctionTool |
Verktyg | Anropa registrerad funktion |
InvokeMcpTool |
Verktyg | Anropa MCP-serververktyget |
HttpRequestAction |
HTTP | Anropa HTTP-slutpunkt |
Question |
Human-in-the-Loop (mänsklig interaktion i processen) | Ställ en fråga till användaren |
RequestExternalInput |
Human-in-the-Loop (mänsklig interaktion i processen) | Begära externa indata |
EndWorkflow |
Arbetsflödeskontroll | Avsluta arbetsflöde |
EndConversation |
Arbetsflödeskontroll | Avsluta konversationen |
CreateConversation |
Arbetsflödeskontroll | Skapa ny konversation |
Uttryckssyntax
Deklarativa arbetsflöden använder ett PowerFx-liknande uttrycksspråk för att hantera tillstånd och beräkna dynamiska värden. Värden som föregås av = utvärderas som uttryck vid körning.
Information om variabelnamnområde
| Namespace | Description | Åtkomst |
|---|---|---|
Local.* |
Arbetsflödeslokala variabler | Läsa/skriva |
Workflow.Inputs.* |
Indataparametrar som skickas till arbetsflödet | Read-only |
Workflow.Outputs.* |
Värden som returneras från arbetsflödet | Läsa/skriva |
System.* |
Systembaserade värden | Read-only |
Agent.* |
Resultat från agentanrop | Read-only |
Systemvariabler
| Variable | Description |
|---|---|
System.ConversationId |
Aktuellt konversations-ID |
System.LastMessage |
Det senaste meddelandet |
System.Timestamp |
Aktuell tidsstämpel |
Agentvariabler
När du har anropat en agent får du åtkomst till svarsdata via utdatavariabeln:
actions:
- kind: InvokeAzureAgent
id: call_assistant
agent:
name: MyAgent
output:
responseObject: Local.AgentResult
# Access agent response
- kind: SendActivity
activity:
text: =Local.AgentResult.text
Literala kontra uttrycksvärden
# Literal string (stored as-is)
value: Hello World
# Expression (evaluated at runtime)
value: =Concat("Hello ", Workflow.Inputs.name)
# Literal number
value: 42
# Expression returning a number
value: =Workflow.Inputs.quantity * 2
Strängoperationer
Concat
Sammanfoga flera strängar:
value: =Concat("Hello, ", Workflow.Inputs.name, "!")
# Result: "Hello, Alice!" (if Workflow.Inputs.name is "Alice")
value: =Concat(Local.firstName, " ", Local.lastName)
# Result: "John Doe" (if firstName is "John" and lastName is "Doe")
IsBlank
Kontrollera om ett värde är tomt eller odefinierat:
condition: =IsBlank(Workflow.Inputs.optionalParam)
# Returns true if the parameter is not provided
value: =If(IsBlank(Workflow.Inputs.name), "Guest", Workflow.Inputs.name)
# Returns "Guest" if name is blank, otherwise returns the name
Villkorsstyrda uttryck
If-funktion
Returnera olika värden baserat på ett villkor:
value: =If(Workflow.Inputs.age < 18, "minor", "adult")
value: =If(Local.count > 0, "Items found", "No items")
# Nested conditions
value: =If(Workflow.Inputs.role = "admin", "Full access", If(Workflow.Inputs.role = "user", "Limited access", "No access"))
Jämförelseoperatorer
| Operatör | Description | Example |
|---|---|---|
= |
Lika med | =Workflow.Inputs.status = "active" |
<> |
Inte lika med | =Workflow.Inputs.status <> "deleted" |
< |
Mindre än | =Workflow.Inputs.age < 18 |
> |
Större än | =Workflow.Inputs.count > 0 |
<= |
Mindre än eller lika med | =Workflow.Inputs.score <= 100 |
>= |
Större än eller lika med | =Workflow.Inputs.quantity >= 1 |
Booleska funktioner
# Or - returns true if any condition is true
condition: =Or(Workflow.Inputs.role = "admin", Workflow.Inputs.role = "moderator")
# And - returns true if all conditions are true
condition: =And(Workflow.Inputs.age >= 18, Workflow.Inputs.hasConsent)
# Not - negates a condition
condition: =Not(IsBlank(Workflow.Inputs.email))
Matematiska operationer
# Addition
value: =Workflow.Inputs.price + Workflow.Inputs.tax
# Subtraction
value: =Workflow.Inputs.total - Workflow.Inputs.discount
# Multiplication
value: =Workflow.Inputs.quantity * Workflow.Inputs.unitPrice
# Division
value: =Workflow.Inputs.total / Workflow.Inputs.count
Exempel på praktiska uttryck
Användarkategorisering
name: categorize-user
inputs:
age:
type: integer
description: User's age
actions:
- kind: SetVariable
variable: Local.age
value: =Workflow.Inputs.age
- kind: SetVariable
variable: Local.category
value: =If(Local.age < 13, "child", If(Local.age < 20, "teenager", If(Local.age < 65, "adult", "senior")))
- kind: SendActivity
activity:
text: =Concat("You are categorized as: ", Local.category)
- kind: SetVariable
variable: Workflow.Outputs.category
value: =Local.category
Villkorsstyrd hälsning
name: smart-greeting
inputs:
name:
type: string
description: User's name (optional)
timeOfDay:
type: string
description: morning, afternoon, or evening
actions:
# Set the greeting based on time of day
- kind: SetVariable
variable: Local.timeGreeting
value: =If(Workflow.Inputs.timeOfDay = "morning", "Good morning", If(Workflow.Inputs.timeOfDay = "afternoon", "Good afternoon", "Good evening"))
# Handle optional name
- kind: SetVariable
variable: Local.userName
value: =If(IsBlank(Workflow.Inputs.name), "friend", Workflow.Inputs.name)
# Build the full greeting
- kind: SetVariable
variable: Local.fullGreeting
value: =Concat(Local.timeGreeting, ", ", Local.userName, "!")
- kind: SendActivity
activity:
text: =Local.fullGreeting
Indataverifiering
name: validate-order
inputs:
quantity:
type: integer
description: Number of items to order
email:
type: string
description: Customer email
actions:
# Check if inputs are valid
- kind: SetVariable
variable: Local.isValidQuantity
value: =And(Workflow.Inputs.quantity > 0, Workflow.Inputs.quantity <= 100)
- kind: SetVariable
variable: Local.hasEmail
value: =Not(IsBlank(Workflow.Inputs.email))
- kind: SetVariable
variable: Local.isValid
value: =And(Local.isValidQuantity, Local.hasEmail)
- kind: If
condition: =Local.isValid
then:
- kind: SendActivity
activity:
text: "Order validated successfully!"
else:
- kind: SendActivity
activity:
text: =If(Not(Local.isValidQuantity), "Invalid quantity (must be 1-100)", "Email is required")
Avancerade mönster
När dina arbetsflöden växer i komplexitet behöver du mönster som hanterar processer i flera steg, agentsamordning och interaktiva scenarier.
Orkestrering med flera agenter
Sekventiell agent-pipeline
Skicka arbete genom flera agenter i följd, där varje agent bygger på den tidigare agentens utdata.
Användningsfall: Produktionsflöden för att skapa innehåll där olika specialister hanterar forskning, skrivande och redigering.
name: content-pipeline
description: Sequential agent pipeline for content creation
kind: Workflow
trigger:
kind: OnConversationStart
id: content_workflow
actions:
# First agent: Research and analyze
- kind: InvokeAzureAgent
id: invoke_researcher
displayName: Research phase
conversationId: =System.ConversationId
agent:
name: ResearcherAgent
# Second agent: Write draft based on research
- kind: InvokeAzureAgent
id: invoke_writer
displayName: Writing phase
conversationId: =System.ConversationId
agent:
name: WriterAgent
# Third agent: Edit and polish
- kind: InvokeAzureAgent
id: invoke_editor
displayName: Editing phase
conversationId: =System.ConversationId
agent:
name: EditorAgent
Python-installation:
from agent_framework.declarative import WorkflowFactory
# Create factory and register agents
factory = WorkflowFactory()
factory.register_agent("ResearcherAgent", researcher_agent)
factory.register_agent("WriterAgent", writer_agent)
factory.register_agent("EditorAgent", editor_agent)
# Load and run
workflow = factory.create_workflow_from_yaml_path("content-pipeline.yaml")
result = await workflow.run({"topic": "AI in healthcare"})
Routning av villkorsstyrd agent
Dirigera begäranden till olika agenter baserat på indata eller mellanliggande resultat.
Användningsfall: Stödsystem som dirigeras till specialiserade agenter baserat på problemtyp.
name: support-router
description: Route to specialized support agents
inputs:
category:
type: string
description: Support category (billing, technical, general)
actions:
- kind: ConditionGroup
id: route_request
displayName: Route to appropriate agent
conditions:
- condition: =Workflow.Inputs.category = "billing"
id: billing_route
actions:
- kind: InvokeAzureAgent
id: billing_agent
agent:
name: BillingAgent
conversationId: =System.ConversationId
- condition: =Workflow.Inputs.category = "technical"
id: technical_route
actions:
- kind: InvokeAzureAgent
id: technical_agent
agent:
name: TechnicalAgent
conversationId: =System.ConversationId
elseActions:
- kind: InvokeAzureAgent
id: general_agent
agent:
name: GeneralAgent
conversationId: =System.ConversationId
Agent med extern loop
Fortsätt agentinteraktion tills ett villkor uppfylls, till exempel problemet som löses.
Användningsfall: Stöd för konversationer som fortsätter tills användarens problem har lösts.
name: support-conversation
description: Continue support until resolved
actions:
- kind: SetVariable
variable: Local.IsResolved
value: false
- kind: InvokeAzureAgent
id: support_agent
displayName: Support agent with external loop
agent:
name: SupportAgent
conversationId: =System.ConversationId
input:
externalLoop:
when: =Not(Local.IsResolved)
output:
responseObject: Local.SupportResult
- kind: SendActivity
activity:
text: "Thank you for contacting support. Your issue has been resolved."
Mönster för loopkontroll
Iterativ agentkonversation
Skapa fram och tillbaka-konversationer mellan agenter med kontrollerad iteration.
Användningsfall: Scenarier för elever och lärare, debattsimuleringar eller iterativ förfining.
name: student-teacher
description: Iterative learning conversation between student and teacher
kind: Workflow
trigger:
kind: OnConversationStart
id: learning_session
actions:
# Initialize turn counter
- kind: SetVariable
id: init_counter
variable: Local.TurnCount
value: 0
- kind: SendActivity
id: start_message
activity:
text: =Concat("Starting session for: ", Workflow.Inputs.problem)
# Student attempts solution (loop entry point)
- kind: SendActivity
id: student_label
activity:
text: "\n[Student]:"
- kind: InvokeAzureAgent
id: student_attempt
conversationId: =System.ConversationId
agent:
name: StudentAgent
# Teacher reviews
- kind: SendActivity
id: teacher_label
activity:
text: "\n[Teacher]:"
- kind: InvokeAzureAgent
id: teacher_review
conversationId: =System.ConversationId
agent:
name: TeacherAgent
output:
messages: Local.TeacherResponse
# Increment counter
- kind: SetVariable
id: increment
variable: Local.TurnCount
value: =Local.TurnCount + 1
# Check completion conditions
- kind: ConditionGroup
id: check_completion
conditions:
# Success: Teacher congratulated student
- condition: =Not(IsBlank(Find("congratulations", Local.TeacherResponse)))
id: success_check
actions:
- kind: SendActivity
activity:
text: "Session complete - student succeeded!"
- kind: SetVariable
variable: Workflow.Outputs.result
value: success
# Continue: Under turn limit
- condition: =Local.TurnCount < 4
id: continue_check
actions:
- kind: GotoAction
actionId: student_label
elseActions:
# Timeout: Reached turn limit
- kind: SendActivity
activity:
text: "Session ended - turn limit reached."
- kind: SetVariable
variable: Workflow.Outputs.result
value: timeout
Räknarbaserade Loopar
Implementera traditionella inventeringsloopar med hjälp av variabler och GotoAction.
name: counter-loop
description: Process items with a counter
actions:
- kind: SetVariable
variable: Local.counter
value: 0
- kind: SetVariable
variable: Local.maxIterations
value: 5
# Loop start
- kind: SetVariable
id: loop_start
variable: Local.counter
value: =Local.counter + 1
- kind: SendActivity
activity:
text: =Concat("Processing iteration ", Local.counter)
# Your processing logic here
- kind: SetVariable
variable: Local.result
value: =Concat("Result from iteration ", Local.counter)
# Check if should continue
- kind: If
condition: =Local.counter < Local.maxIterations
then:
- kind: GotoAction
actionId: loop_start
else:
- kind: SendActivity
activity:
text: "Loop complete!"
Tidig avslut med BreakLoop
Använd BreakLoop för att avsluta iterationer tidigt när ett villkor uppfylls.
name: search-workflow
description: Search through items and stop when found
actions:
- kind: SetVariable
variable: Local.found
value: false
- kind: Foreach
source: =Workflow.Inputs.items
itemName: currentItem
actions:
# Check if this is the item we're looking for
- kind: If
condition: =currentItem.id = Workflow.Inputs.targetId
then:
- kind: SetVariable
variable: Local.found
value: true
- kind: SetVariable
variable: Local.result
value: =currentItem
- kind: BreakLoop
- kind: SendActivity
activity:
text: =Concat("Checked item: ", currentItem.name)
- kind: If
condition: =Local.found
then:
- kind: SendActivity
activity:
text: =Concat("Found: ", Local.result.name)
else:
- kind: SendActivity
activity:
text: "Item not found"
Människa-i-slingan-mönster
Interaktiv undersökning
Samla in flera informationsdelar från användaren.
name: customer-survey
description: Interactive customer feedback survey
actions:
- kind: SendActivity
activity:
text: "Welcome to our customer feedback survey!"
# Collect name
- kind: Question
id: ask_name
question:
text: "What is your name?"
variable: Local.userName
default: "Anonymous"
- kind: SendActivity
activity:
text: =Concat("Nice to meet you, ", Local.userName, "!")
# Collect rating
- kind: Question
id: ask_rating
question:
text: "How would you rate our service? (1-5)"
variable: Local.rating
default: "3"
# Respond based on rating
- kind: If
condition: =Local.rating >= 4
then:
- kind: SendActivity
activity:
text: "Thank you for the positive feedback!"
else:
- kind: Question
id: ask_improvement
question:
text: "What could we improve?"
variable: Local.feedback
# Collect additional feedback
- kind: RequestExternalInput
id: additional_comments
prompt:
text: "Any additional comments? (optional)"
variable: Local.comments
default: ""
# Summary
- kind: SendActivity
activity:
text: =Concat("Thank you, ", Local.userName, "! Your feedback has been recorded.")
- kind: SetVariable
variable: Workflow.Outputs.survey
value:
name: =Local.userName
rating: =Local.rating
feedback: =Local.feedback
comments: =Local.comments
Arbetsflöde för godkännande
Begär godkännande innan du fortsätter med en åtgärd.
name: approval-workflow
description: Request approval before processing
inputs:
requestType:
type: string
description: Type of request
amount:
type: number
description: Request amount
actions:
- kind: SendActivity
activity:
text: =Concat("Processing ", Workflow.Inputs.requestType, " request for $", Workflow.Inputs.amount)
# Check if approval is needed
- kind: If
condition: =Workflow.Inputs.amount > 1000
then:
- kind: SendActivity
activity:
text: "This request requires manager approval."
- kind: Question
id: get_approval
question:
text: =Concat("Do you approve this ", Workflow.Inputs.requestType, " request for $", Workflow.Inputs.amount, "? (yes/no)")
variable: Local.approved
- kind: If
condition: =Local.approved = "yes"
then:
- kind: SendActivity
activity:
text: "Request approved. Processing..."
- kind: SetVariable
variable: Workflow.Outputs.status
value: approved
else:
- kind: SendActivity
activity:
text: "Request denied."
- kind: SetVariable
variable: Workflow.Outputs.status
value: denied
else:
- kind: SendActivity
activity:
text: "Request auto-approved (under threshold)."
- kind: SetVariable
variable: Workflow.Outputs.status
value: auto_approved
Komplex orkestrering
Arbetsflöde för supportbegäran
Ett omfattande exempel som kombinerar flera mönster: agentroutning, villkorslogik och konversationshantering.
name: support-ticket-workflow
description: Complete support ticket handling with escalation
kind: Workflow
trigger:
kind: OnConversationStart
id: support_workflow
actions:
# Initial self-service agent
- kind: InvokeAzureAgent
id: self_service
displayName: Self-service agent
agent:
name: SelfServiceAgent
conversationId: =System.ConversationId
input:
externalLoop:
when: =Not(Local.ServiceResult.IsResolved)
output:
responseObject: Local.ServiceResult
# Check if resolved by self-service
- kind: If
condition: =Local.ServiceResult.IsResolved
then:
- kind: SendActivity
activity:
text: "Issue resolved through self-service."
- kind: SetVariable
variable: Workflow.Outputs.resolution
value: self_service
- kind: EndWorkflow
id: end_resolved
# Create support ticket
- kind: SendActivity
activity:
text: "Creating support ticket..."
- kind: SetVariable
variable: Local.TicketId
value: =Concat("TKT-", System.ConversationId)
# Route to appropriate team
- kind: ConditionGroup
id: route_ticket
conditions:
- condition: =Local.ServiceResult.Category = "technical"
id: technical_route
actions:
- kind: InvokeAzureAgent
id: technical_support
agent:
name: TechnicalSupportAgent
conversationId: =System.ConversationId
output:
responseObject: Local.TechResult
- condition: =Local.ServiceResult.Category = "billing"
id: billing_route
actions:
- kind: InvokeAzureAgent
id: billing_support
agent:
name: BillingSupportAgent
conversationId: =System.ConversationId
output:
responseObject: Local.BillingResult
elseActions:
# Escalate to human
- kind: SendActivity
activity:
text: "Escalating to human support..."
- kind: SetVariable
variable: Workflow.Outputs.resolution
value: escalated
- kind: SendActivity
activity:
text: =Concat("Ticket ", Local.TicketId, " has been processed.")
Metodtips
Namnkonventioner
Använd tydliga, beskrivande namn för åtgärder och variabler:
# Good
- kind: SetVariable
id: calculate_total_price
variable: Local.orderTotal
# Avoid
- kind: SetVariable
id: sv1
variable: Local.x
Organisera stora arbetsflöden
Dela upp komplexa arbetsflöden i logiska avsnitt med kommentarer:
actions:
# === INITIALIZATION ===
- kind: SetVariable
id: init_status
variable: Local.status
value: started
# === DATA COLLECTION ===
- kind: Question
id: collect_name
# ...
# === PROCESSING ===
- kind: InvokeAzureAgent
id: process_request
# ...
# === OUTPUT ===
- kind: SendActivity
id: send_result
# ...
Felhantering
Använd villkorliga kontroller för att hantera potentiella problem:
actions:
- kind: SetVariable
variable: Local.hasError
value: false
- kind: InvokeAzureAgent
id: call_agent
agent:
name: ProcessingAgent
output:
responseObject: Local.AgentResult
- kind: If
condition: =IsBlank(Local.AgentResult)
then:
- kind: SetVariable
variable: Local.hasError
value: true
- kind: SendActivity
activity:
text: "An error occurred during processing."
else:
- kind: SendActivity
activity:
text: =Local.AgentResult.message
Teststrategier
- Börja enkelt: Testa grundläggande flöden innan du lägger till komplexitet
- Använd standardvärden: Ange lämpliga standardvärden för indata
- Lägg till loggning: Använd SendActivity för felsökning under utveckling
- Test gränsfall: Verifiera beteende med saknade eller ogiltiga indata
# Debug logging example
- kind: SendActivity
id: debug_log
activity:
text: =Concat("[DEBUG] Current state: counter=", Local.counter, ", status=", Local.status)
Nästa steg
-
C# Deklarativa arbetsflödesexempel – Utforska fullständiga arbetsexempel, inklusive:
- StudentTeacher – konversation med flera agenter med iterativ inlärning
- InvokeMcpTool – MCP-serververktygsintegrering
- InvokeFunctionTool – Direkt funktionsanrop från arbetsflöden
- FunctionTools – Agent med funktionsverktyg
- ToolApproval – Mänskligt godkännande för verktygsutförande
- CustomerSupport – komplext arbetsflöde för supportärende
- DeepResearch – Undersöka arbetsflöde med flera agenter
- Python Deklarativa arbetsflödesexempel – Utforska fullständiga arbetsexempel
Anmärkning
Go-stöd för den här funktionen kommer snart. Se Agent Framework Go-lagringsplatsen för den senaste statusen.