Deklarativa arbetsflöden – översikt

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

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.

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

  1. Börja enkelt: Testa grundläggande flöden innan du lägger till komplexitet
  2. Använd standardvärden: Ange lämpliga standardvärden för indata
  3. Lägg till loggning: Använd SendActivity för felsökning under utveckling
  4. 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

Anmärkning

Go-stöd för den här funktionen kommer snart. Se Agent Framework Go-lagringsplatsen för den senaste statusen.