Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Fluxos de trabalho declarativos permitem definir a lógica de fluxo de trabalho usando arquivos de configuração YAML em vez de escrever código programático. Essa abordagem torna os fluxos de trabalho mais fáceis de ler, modificar e compartilhar entre equipes.
Visão geral
Com fluxos de trabalho declarativos, você descreve o que seu fluxo de trabalho deve fazer em vez de como implementá-lo. A estrutura manipula a execução subjacente, convertendo suas definições YAML em grafos de fluxo de trabalho executáveis.
Principais benefícios:
- Formato legível: a sintaxe YAML é fácil de entender, mesmo para não desenvolvedores
- Portátil: definições de fluxo de trabalho podem ser compartilhadas, com controle de versão e modificadas sem alterações de código
- Iteração rápida: modificar o comportamento do fluxo de trabalho editando arquivos de configuração
- Estrutura consistente: tipos de ação predefinidos garantem que os fluxos de trabalho sigam as práticas recomendadas
Quando usar fluxos de trabalho declarativos versus programáticos
| Scenario | Abordagem recomendada |
|---|---|
| Padrões de orquestração padrão | Declarativo |
| Fluxos de trabalho que mudam com frequência | Declarativo |
| Não desenvolvedores precisam modificar fluxos de trabalho | Declarativo |
| Lógica personalizada complexa | Programmatic |
| Máxima flexibilidade e controle | Programmatic |
| Integração com o código python existente | Programmatic |
Estrutura YAML básica
A estrutura YAML difere ligeiramente entre implementações de C# e Python. Confira as seções específicas do idioma abaixo para obter detalhes.
Tipos de ação
Fluxos de trabalho declarativos dão suporte a vários tipos de ação. A tabela a seguir mostra a disponibilidade por idioma:
| Categoria | Ações | C# | Python |
|---|---|---|---|
| Gerenciamento de variáveis |
SetVariable
SetMultipleVariables
ResetVariable
|
✅ | ✅ |
| Gerenciamento de variáveis | AppendValue |
❌ | ✅ |
| Gerenciamento de variáveis |
SetTextVariable, ClearAllVariables, , ParseValueEditTableV2 |
✅ | ❌ |
| Fluxo de controle |
If, ConditionGroup, Foreach, BreakLoop, ContinueLoop, , GotoAction |
✅ | ✅ |
| Fluxo de controle | RepeatUntil |
❌ | ✅ |
| Saída | SendActivity |
✅ | ✅ |
| Saída | EmitEvent |
❌ | ✅ |
| Invocação do Agente | InvokeAzureAgent |
✅ | ✅ |
| Invocação de Ferramenta | InvokeFunctionTool |
✅ | ✅ |
| Invocação de Ferramenta | InvokeMcpTool |
✅ | ❌ |
| Human-in-the-Loop |
Question, RequestExternalInput |
✅ | ✅ |
| Human-in-the-Loop |
Confirmation, WaitForInput |
❌ | ✅ |
| Controle de fluxo de trabalho |
EndWorkflow
EndConversation
CreateConversation
|
✅ | ✅ |
| Conversa |
AddConversationMessage, CopyConversationMessages, , RetrieveConversationMessageRetrieveConversationMessages |
✅ | ❌ |
Estrutura YAML do C#
Os fluxos de trabalho declarativos do C# usam uma estrutura baseada em gatilho:
#
# 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
Elementos de estrutura
| Elemento | Obrigatório | DESCRIÇÃO |
|---|---|---|
kind |
Yes | Deve ser Workflow |
trigger.kind |
Yes | Tipo de gatilho (normalmente OnConversationStart) |
trigger.id |
Yes | Identificador exclusivo para o fluxo de trabalho |
trigger.actions |
Yes | Lista de ações a serem executadas |
Estrutura YAML do Python
Os fluxos de trabalho declarativos do Python usam uma estrutura baseada em nome com entradas opcionais:
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
Elementos de estrutura
| Elemento | Obrigatório | DESCRIÇÃO |
|---|---|---|
name |
Yes | Identificador exclusivo para o fluxo de trabalho |
description |
Não | Descrição legível por humanos |
inputs |
Não | Parâmetros de entrada que o fluxo de trabalho aceita |
actions |
Yes | Lista de ações a serem executadas |
Pré-requisitos
Antes de começar, verifique se você tem:
- .NET 8.0 ou posterior
- Um projeto do Microsoft Foundry com pelo menos um agente implantado
- Os seguintes pacotes NuGet instalados:
dotnet add package Microsoft.Agents.AI.Workflows.Declarative --prerelease
dotnet add package Microsoft.Agents.AI.Workflows.Declarative.AzureAI --prerelease
- Se você pretende adicionar a ação de invocação da ferramenta MCP ao fluxo de trabalho, instale também o seguinte pacote NuGet:
dotnet add package Microsoft.Agents.AI.Workflows.Declarative.Mcp --prerelease
- Familiaridade básica com a sintaxe YAML
- Noções básicas sobre conceitos de fluxo de trabalho
Seu primeiro fluxo de trabalho declarativo
Vamos criar um fluxo de trabalho simples que receba um usuário com base em sua entrada.
Etapa 1: Criar o arquivo YAML
Crie um arquivo chamado 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
Etapa 2: Configurar o provedor de agente
Crie um aplicativo de console C# para executar o fluxo de trabalho. Primeiro, configure o provedor de agente que se conecta ao 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());
Etapa 3: compilar e executar o fluxo de trabalho
// 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!");
Saída esperada
Loaded workflow from: C:\path\to\greeting-workflow.yaml
----------------------------------------
Activity: Hello, Alice!
Workflow completed!
Conceitos principais
Namespaces de Variáveis
Os fluxos de trabalho declarativos em C# usam variáveis com espaçamento de nomes para organizar o estado:
| Namespace | DESCRIÇÃO | Example |
|---|---|---|
Local.* |
Variáveis locais para o fluxo de trabalho | Local.message |
System.* |
Valores fornecidos pelo sistema |
System.ConversationId, System.LastMessage |
Observação
Fluxos de trabalho declarativos em C# não usam Workflow.Inputs nem Workflow.Outputs namespaces. A entrada é recebida por meio System.LastMessage e a saída é enviada por meio de SendActivity ações.
Variáveis do sistema
| Variable | DESCRIÇÃO |
|---|---|
System.ConversationId |
Identificador de conversa atual |
System.LastMessage |
A mensagem de usuário mais recente |
System.LastMessage.Text |
Conteúdo de texto da última mensagem |
Linguagem de expressão
Os valores prefixados com = são avaliados como expressões usando a linguagem de expressão PowerFx:
# Literal value (no evaluation)
value: Hello
# Expression (evaluated at runtime)
value: =Concat("Hello, ", Local.userName)
# Access last message text
value: =System.LastMessage.Text
As funções comuns incluem:
-
Concat(str1, str2, ...)- Concatenar cadeias de caracteres -
If(condition, trueValue, falseValue)- Expressão condicional -
IsBlank(value)– Verificar se o valor está vazio -
Upper(text)/Lower(text)– Conversão de maiúsculas e minúsculas -
Find(searchText, withinText)- Localizar texto dentro da cadeia de caracteres -
MessageText(message)– Extrair texto de um objeto de mensagem -
UserMessage(text)- Criar uma mensagem de usuário com base no texto -
AgentMessage(text)- Criar uma mensagem de agente com base no texto
Opções de configuração
A DeclarativeWorkflowOptions classe fornece configuração para execução de fluxo de trabalho:
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,
// PowerFx expression limits (optional)
MaximumCallDepth = 50,
MaximumExpressionLength = 10000,
// Telemetry configuration (optional)
ConfigureTelemetry = opts => { /* configure telemetry */ },
TelemetryActivitySource = activitySource,
};
Instalação do provedor de agente
O AzureAgentProvider conecta seu fluxo de trabalho aos agentes do Foundry:
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,
};
Execução de fluxo de trabalho
Use InProcessExecution para executar fluxos de trabalho e manipular eventos:
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;
}
}
Retomada de Pontos de Verificação
Os fluxos de trabalho podem ser retomados a partir dos pontos de verificação para garantir a tolerância a falhas.
// 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...
}
Referência de ações
As ações são os blocos de construção de fluxos de trabalho declarativos. Cada ação executa uma operação específica e as ações são executadas sequencialmente na ordem em que aparecem no arquivo YAML.
Estrutura de ação
Todas as ações compartilham propriedades comuns:
- 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...
Ações de gerenciamento de variáveis
DefinirVariável
Define uma variável como um valor especificado.
- kind: SetVariable
id: set_greeting
displayName: Set greeting message
variable: Local.greeting
value: Hello World
Com uma expressão:
- kind: SetVariable
variable: Local.fullName
value: =Concat(Local.firstName, " ", Local.lastName)
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
variable |
Yes | Caminho da variável (por exemplo, Local.name, Workflow.Outputs.result) |
value |
Yes | Valor a ser definido (literal ou expressão) |
SetMultipleVariables
Define várias variáveis em uma única ação.
- kind: SetMultipleVariables
id: initialize_vars
displayName: Initialize variables
variables:
Local.counter: 0
Local.status: pending
Local.message: =Concat("Processing order ", Local.orderId)
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
variables |
Yes | Mapa de caminhos variáveis para valores |
SetTextVariable (somente C#)
Define uma variável de texto como um valor de cadeia de caracteres especificado.
- kind: SetTextVariable
id: set_text
displayName: Set text content
variable: Local.description
value: This is a text description
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
variable |
Yes | Caminho da variável para o valor de texto |
value |
Yes | Valor de texto a ser definido |
ResetVariable
Limpa o valor de uma variável.
- kind: ResetVariable
id: clear_counter
variable: Local.counter
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
variable |
Yes | Caminho da variável a ser redefinido |
ClearAllVariables (apenas para C#)
Redefine todas as variáveis no contexto atual.
- kind: ClearAllVariables
id: clear_all
displayName: Clear all workflow variables
ParseValue (somente C#)
Extrai ou converte dados em um formato utilizável.
- kind: ParseValue
id: parse_json
displayName: Parse JSON response
source: =Local.rawResponse
variable: Local.parsedData
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
source |
Yes | Expressão retornando o valor para analisar |
variable |
Yes | Caminho da variável para armazenar o resultado analisado |
EditTableV2 (somente C#)
Modifica dados em um formato de tabela estruturado.
- kind: EditTableV2
id: update_table
displayName: Update configuration table
table: Local.configTable
operation: update
row:
key: =Local.settingName
value: =Local.settingValue
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
table |
Yes | Caminho variável para a tabela |
operation |
Yes | Tipo de operação (adicionar, atualizar, excluir) |
row |
Yes | Dados de linha para a operação |
Ações de fluxo de controle
If
Executa ações condicionalmente com base em uma condição.
- 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!"
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
condition |
Yes | Expressão que é avaliada como verdadeiro/falso |
then |
Yes | Ações a serem executadas se a condição for verdadeira |
else |
Não | Ações a serem executadas se a condição for falsa |
ConditionGroup
Avalia várias condições, como uma instrução switch/case.
- 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
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
conditions |
Yes | Lista de pares de condição/ações (vitórias na primeira partida) |
elseActions |
Não | Ações caso nenhuma condição seja correspondente |
Foreach
Itera sobre uma coleção.
- 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)
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
source |
Yes | Expressão que retorna uma coleção |
itemName |
Não | Nome da variável para item atual (padrão: item) |
indexName |
Não | Nome da variável para o índice atual (padrão: index) |
actions |
Yes | Ações a serem executadas para cada item |
BreakLoop
Sai do loop atual imediatamente.
- kind: Foreach
source: =Local.items
actions:
- kind: If
condition: =item = "stop"
then:
- kind: BreakLoop
- kind: SendActivity
activity:
text: =item
ContinueLoop
Passa para a próxima iteração do loop.
- kind: Foreach
source: =Local.numbers
actions:
- kind: If
condition: =item < 0
then:
- kind: ContinueLoop
- kind: SendActivity
activity:
text: =Concat("Positive number: ", item)
GotoAction
Salta para uma ação específica usando o 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
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
actionId |
Yes | Identificador da ação para pular para |
Ações de saída
SendActivity
Envia uma mensagem ao usuário.
- kind: SendActivity
id: send_welcome
displayName: Send welcome message
activity:
text: "Welcome to our service!"
Com uma expressão:
- kind: SendActivity
activity:
text: =Concat("Hello, ", Local.userName, "! How can I help you today?")
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
activity |
Yes | A atividade a ser enviada |
activity.text |
Yes | Texto da mensagem (literal ou expressão) |
Ações de invocação do agente
InvokeAzureAgent
Invoca um agente do Foundry.
Invocação básica:
- kind: InvokeAzureAgent
id: call_assistant
displayName: Call assistant agent
agent:
name: AssistantAgent
conversationId: =System.ConversationId
Na configuração de entrada e saída:
- 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
Com loop externo (continua até que a condição seja atendida):
- kind: InvokeAzureAgent
id: support_agent
agent:
name: SupportAgent
input:
externalLoop:
when: =Not(Local.IsResolved)
output:
responseObject: Local.SupportResult
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
agent.name |
Yes | Nome do agente registrado |
conversationId |
Não | Identificador de contexto de conversa |
input.messages |
Não | Mensagens a serem enviadas ao agente |
input.arguments |
Não | Argumentos adicionais para o agente |
input.externalLoop.when |
Não | Condição para continuar o loop do agente |
output.responseObject |
Não | Caminho para armazenar a resposta do agente |
output.messages |
Não | Caminho para armazenar mensagens de conversa |
output.autoSend |
Não | Enviar resposta automaticamente ao usuário |
Ações de Invocação de Ferramentas (somente C#)
InvokeFunctionTool
Invoca uma ferramenta de função diretamente do fluxo de trabalho sem passar por um agente de IA.
- 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
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
functionName |
Yes | Nome da função a ser invocada |
conversationId |
Não | Identificador de contexto de conversa |
requireApproval |
Não | Se é necessário exigir aprovação do usuário antes da execução |
arguments |
Não | Argumentos a serem passados para a função |
output.result |
Não | Caminho para armazenar o resultado da função |
output.messages |
Não | Caminho para armazenar mensagens de função |
output.autoSend |
Não | Enviar automaticamente o resultado para o usuário |
Configuração do C# para InvokeFunctionTool:
As funções devem ser registradas com WorkflowRunner ou manipuladas por meio de entrada externa:
// 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);
InvokeMcpTool
Invoca uma ferramenta em um servidor MCP (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
Com o nome da conexão para cenários hospedados:
- 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
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
serverUrl |
Yes | URL do servidor MCP |
serverLabel |
Não | Rótulo legível para o servidor |
toolName |
Yes | Nome da ferramenta a ser invocada |
conversationId |
Não | Identificador de contexto de conversa |
requireApproval |
Não | Se é necessário exigir aprovação do usuário |
arguments |
Não | Argumentos a serem passados para a ferramenta |
headers |
Não | Cabeçalhos HTTP personalizados para a solicitação |
connection.name |
Não | Conexão nomeada para cenários hospedados (conecta-se ao ProjectConnectionId na Foundry; ainda não tem suporte total) |
output.result |
Não | Caminho para armazenar o resultado da ferramenta |
output.messages |
Não | Caminho para armazenar mensagens de resultado |
output.autoSend |
Não | Enviar automaticamente o resultado para o usuário |
Instalação do C# para InvokeMcpTool:
Configure o McpToolHandler na sua fábrica de fluxo de trabalho:
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
};
Ações com Intervenção Humana
Pergunta
Faz uma pergunta ao usuário e armazena a resposta.
- kind: Question
id: ask_name
displayName: Ask for user name
question:
text: "What is your name?"
variable: Local.userName
default: "Guest"
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
question.text |
Yes | A pergunta a ser feita |
variable |
Yes | Caminho para armazenar a resposta |
default |
Não | Valor padrão se nenhuma resposta |
SolicitarEntradaExterna
Solicita a entrada de um sistema ou processo externo.
- kind: RequestExternalInput
id: request_approval
displayName: Request manager approval
prompt:
text: "Please provide approval for this request."
variable: Local.approvalResult
default: "pending"
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
prompt.text |
Yes | Descrição da entrada necessária |
variable |
Yes | Caminho para armazenar a entrada |
default |
Não | Valor padrão |
Ações de controle de fluxo de trabalho
EndWorkflow
Encerra a execução do fluxo de trabalho.
- kind: EndWorkflow
id: finish
displayName: End workflow
EndConversation
Termina a conversa atual.
- kind: EndConversation
id: end_chat
displayName: End conversation
CreateConversation
Cria um novo contexto de conversa.
- kind: CreateConversation
id: create_new_conv
displayName: Create new conversation
conversationId: Local.NewConversationId
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
conversationId |
Yes | Caminho para armazenar a nova ID de conversa |
Ações de Conversa (somente C#)
AdicionarMensagemConversa
Adiciona uma mensagem a um thread de conversa.
- kind: AddConversationMessage
id: add_system_message
displayName: Add system context
conversationId: =System.ConversationId
message:
role: system
content: =Local.contextInfo
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
conversationId |
Yes | Identificador de conversação de destino |
message |
Yes | Mensagem a ser adicionada |
message.role |
Yes | Função de mensagem (sistema, usuário, assistente) |
message.content |
Yes | Conteúdo da mensagem |
CopiarMensagensDaConversa
Copia mensagens de uma conversa para outra.
- kind: CopyConversationMessages
id: copy_context
displayName: Copy conversation context
sourceConversationId: =Local.SourceConversation
targetConversationId: =System.ConversationId
limit: 10
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
sourceConversationId |
Yes | Identificador da conversa de origem |
targetConversationId |
Yes | Identificador de conversação de destino |
limit |
Não | Número máximo de mensagens a serem copiadas |
RecuperarMensagemDeConversa
Recupera uma mensagem específica de uma conversa.
- kind: RetrieveConversationMessage
id: get_message
displayName: Get specific message
conversationId: =System.ConversationId
messageId: =Local.targetMessageId
variable: Local.retrievedMessage
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
conversationId |
Yes | Identificador de conversa |
messageId |
Yes | Identificador de mensagem a ser recuperado |
variable |
Yes | Caminho para armazenar a mensagem recuperada |
RecuperarMensagensDeConversa
Recupera várias mensagens de uma conversa.
- kind: RetrieveConversationMessages
id: get_history
displayName: Get conversation history
conversationId: =System.ConversationId
limit: 20
newestFirst: true
variable: Local.conversationHistory
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
conversationId |
Yes | Identificador de conversa |
limit |
Não | Máximo de mensagens a serem recuperadas (padrão: 20) |
newestFirst |
Não | Retornar em ordem decrescente |
after |
Não | Cursor para paginação |
before |
Não | Cursor para paginação |
variable |
Yes | Caminho para armazenar mensagens recuperadas |
Referência rápida de ações
| Ação | Categoria | C# | Python | DESCRIÇÃO |
|---|---|---|---|---|
SetVariable |
Variable | ✅ | ✅ | Definir uma única variável |
SetMultipleVariables |
Variable | ✅ | ✅ | Definir várias variáveis |
SetTextVariable |
Variable | ✅ | ❌ | Definir uma variável de texto |
AppendValue |
Variable | ❌ | ✅ | Acrescentar à lista/string |
ResetVariable |
Variable | ✅ | ✅ | Limpar uma variável |
ClearAllVariables |
Variable | ✅ | ❌ | Limpar todas as variáveis |
ParseValue |
Variable | ✅ | ❌ | Analisar/transformar dados |
EditTableV2 |
Variable | ✅ | ❌ | Modificar dados da tabela |
If |
Fluxo de controle | ✅ | ✅ | Ramificação condicional |
ConditionGroup |
Fluxo de controle | ✅ | ✅ | Comutador de várias ramificações |
Foreach |
Fluxo de controle | ✅ | ✅ | Iterar pela coleção |
RepeatUntil |
Fluxo de controle | ❌ | ✅ | Repita o loop enquanto a condição for verdadeira |
BreakLoop |
Fluxo de controle | ✅ | ✅ | Sair do loop atual |
ContinueLoop |
Fluxo de controle | ✅ | ✅ | Pular para a próxima iteração |
GotoAction |
Fluxo de controle | ✅ | ✅ | Saltar para a ação por ID |
SendActivity |
Saída | ✅ | ✅ | Enviar mensagem ao usuário |
EmitEvent |
Saída | ❌ | ✅ | Emitir evento personalizado |
InvokeAzureAgent |
Agente | ✅ | ✅ | Chamar o agente de IA do Azure |
InvokeFunctionTool |
Tool | ✅ | ✅ | Invocar função diretamente |
InvokeMcpTool |
Tool | ✅ | ❌ | Invocar ferramenta de servidor MCP |
Question |
Human-in-the-Loop | ✅ | ✅ | Fazer uma pergunta ao usuário |
Confirmation |
Human-in-the-Loop | ❌ | ✅ | Confirmação sim/não |
RequestExternalInput |
Human-in-the-Loop | ✅ | ✅ | Solicitar entrada externa |
WaitForInput |
Human-in-the-Loop | ❌ | ✅ | Aguarde a entrada |
EndWorkflow |
Controle de fluxo de trabalho | ✅ | ✅ | Encerrar fluxo de trabalho |
EndConversation |
Controle de fluxo de trabalho | ✅ | ✅ | Encerrar conversa |
CreateConversation |
Controle de fluxo de trabalho | ✅ | ✅ | Criar uma nova conversa |
AddConversationMessage |
Conversa | ✅ | ❌ | Adicionar mensagem ao thread |
CopyConversationMessages |
Conversa | ✅ | ❌ | Copiar mensagens |
RetrieveConversationMessage |
Conversa | ✅ | ❌ | Obter uma única mensagem |
RetrieveConversationMessages |
Conversa | ✅ | ❌ | Obter várias mensagens |
Padrões Avançados
Orquestração de múltiplos agentes
Pipeline do Agente Sequencial
Passe o trabalho por vários agentes em sequência.
#
# 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
Instalação do C#:
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");
Roteamento de Agente Condicional
Encaminhe solicitações para diferentes agentes com base nas condições.
#
# 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
Padrões de integração de ferramentas
Pré-carregamento de dados com InvokeFunctionTool
Buscar dados antes de chamar um agente:
#
# 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)
Integração de ferramentas do MCP
Chame o servidor externo usando o 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")
Pré-requisitos
Antes de começar, verifique se você tem:
- O Python 3.10 – 3.13 (o Python 3.14 ainda não tem suporte devido à compatibilidade do PowerFx)
- O pacote declarativo do Agent Framework instalado:
pip install agent-framework-declarative --pre
Este pacote incorpora o subjacente automaticamente agent-framework-core.
- Familiaridade básica com a sintaxe YAML
- Noções básicas sobre conceitos de fluxo de trabalho
Seu primeiro fluxo de trabalho declarativo
Vamos criar um fluxo de trabalho simples que receba um usuário pelo nome.
Etapa 1: Criar o arquivo YAML
Crie um arquivo chamado 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
Etapa 2: Carregar e executar o fluxo de trabalho
Crie um arquivo Python para executar o fluxo de trabalho:
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}")
if __name__ == "__main__":
asyncio.run(main())
Saída esperada
Loaded workflow: greeting-workflow
----------------------------------------
Output: Hello, Alice!
Conceitos principais
Namespaces de Variáveis
Fluxos de trabalho declarativos usam variáveis com espaçamento de nomes para organizar o estado:
| Namespace | DESCRIÇÃO | Example |
|---|---|---|
Local.* |
Variáveis locais para o fluxo de trabalho | Local.message |
Workflow.Inputs.* |
Parâmetros de entrada | Workflow.Inputs.name |
Workflow.Outputs.* |
Valores de saída | Workflow.Outputs.result |
System.* |
Valores fornecidos pelo sistema | System.ConversationId |
Linguagem de expressão
Os valores prefixados com = são avaliados como expressões:
# Literal value (no evaluation)
value: Hello
# Expression (evaluated at runtime)
value: =Concat("Hello, ", Workflow.Inputs.name)
As funções comuns incluem:
-
Concat(str1, str2, ...)- Concatenar cadeias de caracteres -
If(condition, trueValue, falseValue)- Expressão condicional -
IsBlank(value)– Verificar se o valor está vazio
Tipos de ação
Os fluxos de trabalho declarativos dão suporte a vários tipos de ação:
| Categoria | Ações |
|---|---|
| Gerenciamento de variáveis |
SetVariable, SetMultipleVariables, , AppendValueResetVariable |
| Fluxo de controle |
If, ConditionGroup, Foreach, RepeatUntil, , BreakLoop, ContinueLoop, GotoAction |
| Saída |
SendActivity, EmitEvent |
| Invocação do Agente | InvokeAzureAgent |
| Invocação de Ferramenta | InvokeFunctionTool |
| Human-in-the-Loop |
Question, Confirmation, , RequestExternalInputWaitForInput |
| Controle de fluxo de trabalho |
EndWorkflow
EndConversation
CreateConversation
|
Referência de ações
As ações são os blocos de construção de fluxos de trabalho declarativos. Cada ação executa uma operação específica e as ações são executadas sequencialmente na ordem em que aparecem no arquivo YAML.
Estrutura de ação
Todas as ações compartilham propriedades comuns:
- 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...
Ações de gerenciamento de variáveis
DefinirVariável
Define uma variável como um valor especificado.
- kind: SetVariable
id: set_greeting
displayName: Set greeting message
variable: Local.greeting
value: Hello World
Com uma expressão:
- kind: SetVariable
variable: Local.fullName
value: =Concat(Workflow.Inputs.firstName, " ", Workflow.Inputs.lastName)
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
variable |
Yes | Caminho da variável (por exemplo, Local.name, Workflow.Outputs.result) |
value |
Yes | Valor a ser definido (literal ou expressão) |
Observação
Python também dá suporte ao tipo de ação SetValue, que usa path em vez da propriedade-alvo variable. Ambos SetVariable (com variable) e SetValue (com path) alcançam o mesmo resultado. Por exemplo:
- kind: SetValue
id: set_greeting
path: Local.greeting
value: Hello World
SetMultipleVariables
Define várias variáveis em uma única ação.
- kind: SetMultipleVariables
id: initialize_vars
displayName: Initialize variables
variables:
Local.counter: 0
Local.status: pending
Local.message: =Concat("Processing order ", Workflow.Inputs.orderId)
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
variables |
Yes | Mapa de caminhos variáveis para valores |
AppendValue
Acrescenta um valor a uma lista ou concatena a uma string.
- kind: AppendValue
id: add_item
variable: Local.items
value: =Workflow.Inputs.newItem
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
variable |
Yes | Caminho de variável a anexar |
value |
Yes | Valor a ser acrescentado |
ResetVariable
Limpa o valor de uma variável.
- kind: ResetVariable
id: clear_counter
variable: Local.counter
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
variable |
Yes | Caminho da variável a ser redefinido |
Ações de fluxo de controle
If
Executa ações condicionalmente com base em uma condição.
- 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!"
Condições aninhadas:
- 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"
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
condition |
Yes | Expressão que é avaliada como verdadeiro/falso |
then |
Yes | Ações a serem executadas se a condição for verdadeira |
else |
Não | Ações a serem executadas se a condição for falsa |
ConditionGroup
Avalia várias condições, como uma instrução switch/case.
- 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
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
conditions |
Yes | Lista de pares de condição/ações (vitórias na primeira partida) |
elseActions |
Não | Ações caso nenhuma condição seja correspondente |
Foreach
Itera sobre uma coleção.
- 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)
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
source |
Yes | Expressão que retorna uma coleção |
itemName |
Não | Nome da variável para item atual (padrão: item) |
indexName |
Não | Nome da variável para o índice atual (padrão: index) |
actions |
Yes | Ações a serem executadas para cada item |
RepeatUntil
Repete ações até que uma condição se torne verdadeira.
- kind: SetVariable
variable: Local.counter
value: 0
- kind: RepeatUntil
id: count_loop
displayName: Count to 5
condition: =Local.counter >= 5
actions:
- kind: SetVariable
variable: Local.counter
value: =Local.counter + 1
- kind: SendActivity
activity:
text: =Concat("Counter: ", Local.counter)
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
condition |
Yes | O loop continua até que isso seja verdadeiro |
actions |
Yes | Ações a serem repetidas |
BreakLoop
Sai do loop atual imediatamente.
- kind: Foreach
source: =Workflow.Inputs.items
actions:
- kind: If
condition: =item = "stop"
then:
- kind: BreakLoop
- kind: SendActivity
activity:
text: =item
ContinueLoop
Passa para a próxima iteração do loop.
- kind: Foreach
source: =Workflow.Inputs.numbers
actions:
- kind: If
condition: =item < 0
then:
- kind: ContinueLoop
- kind: SendActivity
activity:
text: =Concat("Positive number: ", item)
GotoAction
Salta para uma ação específica usando o 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
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
actionId |
Yes | Identificador da ação para pular para |
Ações de saída
SendActivity
Envia uma mensagem ao usuário.
- kind: SendActivity
id: send_welcome
displayName: Send welcome message
activity:
text: "Welcome to our service!"
Com uma expressão:
- kind: SendActivity
activity:
text: =Concat("Hello, ", Workflow.Inputs.name, "! How can I help you today?")
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
activity |
Yes | A atividade a ser enviada |
activity.text |
Yes | Texto da mensagem (literal ou expressão) |
EmitirEvento
Emite um evento personalizado.
- kind: EmitEvent
id: emit_status
displayName: Emit status event
eventType: order_status_changed
data:
orderId: =Workflow.Inputs.orderId
status: =Local.newStatus
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
eventType |
Yes | Identificador de tipo para o evento |
data |
Não | Dados de carga útil do evento |
Ações de invocação do agente
InvokeAzureAgent
Invoca um agente de IA do Azure.
Invocação básica:
- kind: InvokeAzureAgent
id: call_assistant
displayName: Call assistant agent
agent:
name: AssistantAgent
conversationId: =System.ConversationId
Na configuração de entrada e saída:
- 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
Com loop externo (continua até que a condição seja atendida):
- kind: InvokeAzureAgent
id: support_agent
agent:
name: SupportAgent
input:
externalLoop:
when: =Not(Local.IsResolved)
output:
responseObject: Local.SupportResult
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
agent.name |
Yes | Nome do agente registrado |
conversationId |
Não | Identificador de contexto de conversa |
input.messages |
Não | Mensagens a serem enviadas ao agente |
input.arguments |
Não | Argumentos adicionais para o agente |
input.externalLoop.when |
Não | Condição para continuar o loop do agente |
output.responseObject |
Não | Caminho para armazenar a resposta do agente |
output.messages |
Não | Caminho para armazenar mensagens de conversa |
output.autoSend |
Não | Enviar resposta automaticamente ao usuário |
Ações de Invocação de Ferramentas
InvokeFunctionTool
Invoca uma função Python registrada diretamente do fluxo de trabalho sem passar por um agente de IA.
- 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
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
functionName |
Yes | Nome da função registrada a ser invocada |
arguments |
Não | Argumentos a serem passados para a função |
output.result |
Não | Caminho para armazenar o resultado da função |
output.messages |
Não | Caminho para armazenar mensagens de função |
output.autoSend |
Não | Enviar automaticamente o resultado para o usuário |
Configuração do Python para InvokeFunctionTool:
As funções devem ser registradas com o WorkflowFactory usando register_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"})
Ações com Intervenção Humana
Pergunta
Faz uma pergunta ao usuário e armazena a resposta.
- kind: Question
id: ask_name
displayName: Ask for user name
question:
text: "What is your name?"
variable: Local.userName
default: "Guest"
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
question.text |
Yes | A pergunta a ser feita |
variable |
Yes | Caminho para armazenar a resposta |
default |
Não | Valor padrão se nenhuma resposta |
Confirmação
Solicita ao usuário uma confirmação sim/não.
- kind: Confirmation
id: confirm_delete
displayName: Confirm deletion
question:
text: "Are you sure you want to delete this item?"
variable: Local.confirmed
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
question.text |
Yes | A pergunta de confirmação |
variable |
Yes | Caminho para armazenar o resultado booliano |
SolicitarEntradaExterna
Solicita a entrada de um sistema ou processo externo.
- kind: RequestExternalInput
id: request_approval
displayName: Request manager approval
prompt:
text: "Please provide approval for this request."
variable: Local.approvalResult
default: "pending"
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
prompt.text |
Yes | Descrição da entrada necessária |
variable |
Yes | Caminho para armazenar a entrada |
default |
Não | Valor padrão |
WaitForInput
Pausa o fluxo de trabalho e aguarda a entrada externa.
- kind: WaitForInput
id: wait_for_response
variable: Local.externalResponse
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
variable |
Yes | Caminho para armazenar os dados de entrada quando recebidos |
Ações de controle de fluxo de trabalho
EndWorkflow
Encerra a execução do fluxo de trabalho.
- kind: EndWorkflow
id: finish
displayName: End workflow
EndConversation
Termina a conversa atual.
- kind: EndConversation
id: end_chat
displayName: End conversation
CreateConversation
Cria um novo contexto de conversa.
- kind: CreateConversation
id: create_new_conv
displayName: Create new conversation
conversationId: Local.NewConversationId
Propriedades:
| Propriedade | Obrigatório | DESCRIÇÃO |
|---|---|---|
conversationId |
Yes | Caminho para armazenar a nova ID de conversa |
Referência rápida de ações
| Ação | Categoria | DESCRIÇÃO |
|---|---|---|
SetVariable |
Variable | Definir uma única variável |
SetMultipleVariables |
Variable | Definir várias variáveis |
AppendValue |
Variable | Acrescentar à lista/string |
ResetVariable |
Variable | Limpar uma variável |
If |
Fluxo de controle | Ramificação condicional |
ConditionGroup |
Fluxo de controle | Comutador de várias ramificações |
Foreach |
Fluxo de controle | Iterar pela coleção |
RepeatUntil |
Fluxo de controle | Repita o loop enquanto a condição for verdadeira |
BreakLoop |
Fluxo de controle | Sair do loop atual |
ContinueLoop |
Fluxo de controle | Pular para a próxima iteração |
GotoAction |
Fluxo de controle | Saltar para a ação por ID |
SendActivity |
Saída | Enviar mensagem ao usuário |
EmitEvent |
Saída | Emitir evento personalizado |
InvokeAzureAgent |
Agente | Chamar o agente de IA do Azure |
InvokeFunctionTool |
Tool | Invocar função registrada |
Question |
Human-in-the-Loop | Fazer uma pergunta ao usuário |
Confirmation |
Human-in-the-Loop | Confirmação sim/não |
RequestExternalInput |
Human-in-the-Loop | Solicitar entrada externa |
WaitForInput |
Human-in-the-Loop | Aguarde a entrada |
EndWorkflow |
Controle de fluxo de trabalho | Encerrar fluxo de trabalho |
EndConversation |
Controle de fluxo de trabalho | Encerrar conversa |
CreateConversation |
Controle de fluxo de trabalho | Criar uma nova conversa |
Sintaxe de expressão
Fluxos de trabalho declarativos usam uma linguagem de expressão semelhante ao PowerFx para gerenciar valores dinâmicos de computação e de estado. Os valores prefixados com = são avaliados como expressões em runtime.
Detalhes do namespace da variável
| Namespace | DESCRIÇÃO | Acesso |
|---|---|---|
Local.* |
Variáveis locais de fluxo de trabalho | Leitura/gravação |
Workflow.Inputs.* |
Parâmetros de entrada passados para o fluxo de trabalho | Somente leitura |
Workflow.Outputs.* |
Valores retornados do fluxo de trabalho | Leitura/gravação |
System.* |
Valores fornecidos pelo sistema | Somente leitura |
Agent.* |
Resultados de invocações de agente | Somente leitura |
Variáveis do sistema
| Variable | DESCRIÇÃO |
|---|---|
System.ConversationId |
Identificador de conversa atual |
System.LastMessage |
A mensagem mais recente |
System.Timestamp |
Data/hora atual |
Variáveis de agente
Depois de invocar um agente, acesse os dados de resposta por meio da variável de saída:
actions:
- kind: InvokeAzureAgent
id: call_assistant
agent:
name: MyAgent
output:
responseObject: Local.AgentResult
# Access agent response
- kind: SendActivity
activity:
text: =Local.AgentResult.text
Valores literais vs. de expressão
# 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
Operações de cadeia de caracteres
Concat
Concatenar várias cadeias de caracteres:
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
Verifique se um valor está vazio ou indefinido:
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
Expressões condicionais
Função If
Retornar valores diferentes com base em uma condição:
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"))
Operadores de comparação
| Operador | DESCRIÇÃO | Example |
|---|---|---|
= |
Igual a | =Workflow.Inputs.status = "active" |
<> |
Não é igual a | =Workflow.Inputs.status <> "deleted" |
< |
Menor que | =Workflow.Inputs.age < 18 |
> |
Maior que | =Workflow.Inputs.count > 0 |
<= |
Inferior ou igual | =Workflow.Inputs.score <= 100 |
>= |
Maior ou igual | =Workflow.Inputs.quantity >= 1 |
Funções boolianas
# 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))
Operações matemáticas
# 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
Exemplos de expressão prática
Categorização de usuário
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
Saudação condicional
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
Validação de entrada
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")
Padrões Avançados
À medida que seus fluxos de trabalho aumentam em complexidade, você precisará de padrões que lidem com processos de várias etapas, coordenação de agente e cenários interativos.
Orquestração de múltiplos agentes
Pipeline do Agente Sequencial
Passe o trabalho por vários agentes em sequência, em que cada agente se baseia no resultado do agente anterior.
Caso de uso: fluxos de criação de conteúdo em que diferentes especialistas trabalham com pesquisa, escrita e edição.
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
Configuração do Python:
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"})
Roteamento de Agente Condicional
Encaminhe solicitações para agentes diferentes com base nos resultados intermediários ou de entrada.
Caso de uso: sistemas de suporte que roteiam para agentes especializados com base no tipo de problema.
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
Agente com Laço Externo
Continue a interação do agente até que uma condição seja atendida, como a resolução do problema.
Caso de uso: suporte a conversas que continuam até que o problema do usuário seja resolvido.
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."
Padrões de controle de loop
Conversa de um agente iterativo
Crie conversas de ida e volta entre agentes com iteração controlada.
Caso de uso: cenários de aluno-professor, simulações de debate ou refinamento iterativo.
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
Laços Baseados em Contador
Implemente loops de contagem tradicionais usando variáveis e 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!"
Saída Antecipada com BreakLoop
Utilize BreakLoop para sair das iterações mais cedo quando uma condição é atendida.
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"
Padrões de Intervenção Humana no Processo
Pesquisa Interativa
Colete várias informações do usuário.
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
Fluxo de trabalho de aprovação
Solicite aprovação antes de prosseguir com uma ação.
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: Confirmation
id: get_approval
question:
text: =Concat("Do you approve this ", Workflow.Inputs.requestType, " request for $", Workflow.Inputs.amount, "?")
variable: Local.approved
- kind: If
condition: =Local.approved
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
Orquestração complexa
Fluxo de Trabalho de Tíquetes de Suporte
Um exemplo abrangente que combina vários padrões: roteamento de agente, lógica condicional e gerenciamento de conversa.
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.")
Práticas recomendadas
Convenções de nomenclatura
Use nomes claros e descritivos para ações e variáveis:
# Good
- kind: SetVariable
id: calculate_total_price
variable: Local.orderTotal
# Avoid
- kind: SetVariable
id: sv1
variable: Local.x
Organizando fluxos de trabalho grandes
Dividir fluxos de trabalho complexos em seções lógicas com comentários:
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
# ...
Tratamento de erros
Use verificações condicionais para lidar com possíveis problemas:
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
Estratégias de teste
- Inicie simples: teste os fluxos básicos antes de adicionar complexidade
- Usar valores padrão: fornecer padrões sensatos para entradas
- Adicionar registro em log: usar o SendActivity para depurar durante o desenvolvimento
- Casos limite de teste: Verificar o comportamento com entradas ausentes ou inválidas
# Debug logging example
- kind: SendActivity
id: debug_log
activity:
text: =Concat("[DEBUG] Current state: counter=", Local.counter, ", status=", Local.status)
Próximas etapas
-
Exemplos de fluxo de trabalho declarativo do C# – explore exemplos de trabalho completos, incluindo:
- StudentTeacher – Conversa de vários agentes com aprendizado iterativo
- InvokeMcpTool – Integração de ferramentas do servidor MCP
- InvokeFunctionTool – Invocação de função direta de fluxos de trabalho
- FunctionTools – Agente com ferramentas de função
- ToolApproval – Aprovação humana para execução da ferramenta
- CustomerSupport – Fluxo de trabalho complexo do tíquete de suporte
- DeepResearch – Fluxo de trabalho de pesquisa com vários agentes
- Exemplos de fluxo de trabalho declarativo do Python – Explorar exemplos de trabalho completos