Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
AgentApplication é o bloco modular central de um agente criado com o SDK de Agentes. O AgentApplication é o ponto de entrada para toda a atividade recebida, incluindo mensagens de utilizadores, eventos do ciclo de vida da conversação, interações com cartões adaptativos, chamada de retorno de OAuth.
Um agente é, na sua essência, um AgentApplication. Configura-se com processadores que descrevem o que o agente faz. O SDK cuida do encaminhamento, da gestão do estado e da infraestrutura necessária para o funcionamento do agente.
Funcionamento do AgentApplication
Cada agente inicia o seu ciclo de vida quando um canal (Microsoft Teams, um Bot Service ou um cliente personalizado) entrega uma atividade ao ponto final do seu agente.
AgentApplication está no centro deste ciclo de vida:
Channel → Hosting layer → AgentApplication → Your handlers
As camadas de processamento num agente criado com o SDK de Agentes funcionam da seguinte forma:
- A camada de alojamento recebe a requisição HTTP e autentica-a.
- O
AgentApplicationprocessa a atividade de entrada através do seu pipeline. - Os seus processadores são chamados com base nas rotas correspondentes.
O seu agente carrega o estado do turno antes de os processadores serem executados. Em seguida, o agente guarda o estado do turno.
Conceitos-chave
Atividades
Tudo no SDK de Agentes flui como uma atividade. Uma atividade é uma mensagem estruturada que representa algo que aconteceu. Uma atividade tem um tipo, como mensagem, evento, invocação, conversationUpdate e assim por diante. Transporta um payload relevante para esse tipo.
AgentApplication recebe as atividades e encaminha-as para o processador certo.
Rotas
Uma rota emparelha um seletor com um processador. O seletor determina se uma rota corresponde à atividade atual. O processador executa a sua lógica quando a rota corresponde.
Registe rotas ao configurar o agente. Podem combinar:
- Uma mensagem contendo texto específico ou correspondendo a uma expressão regular
- Qualquer atividade de um tipo específico
- Eventos do ciclo de vida da conversação (membro adicionado, membro removido)
- Ações do Cartão Adaptativo
- Condições personalizadas
Quando uma atividade chega, o sistema avalia as rotas sequencialmente até encontrar uma correspondência. Por predefinição, só é executada uma rota.
Estado do turno
O AgentApplication gere o _turn state—um armazenamento estruturado particionado em âmbitos:
| Tipo de âmbito | Descrição |
|---|---|
| Conversa | Partilhado entre todos os utilizadores numa conversação, persistindo entre turnos |
| Utilizador | Limitado a um utilizador em todas as conversas |
| Temp | Só no turno atual - nunca persiste |
O sistema carrega automaticamente o estado antes de os seus processadores serem executados e guarda‑o automaticamente depois.
Contexto do turno
Quando um processador é executado, recebe um contexto de turno. O contexto do turno é um instantâneo da atividade atual, da ligação do adaptador e dos utilitários para enviar respostas. O contexto do turno é a sua interface para a interação atual.
Middleware
AgentApplication suporta um pipeline de middleware. O middleware é uma cadeia de componentes que processa cada turno antes e depois da execução dos seus processadores. O middleware pode inspecionar, transformar ou interromper o fluxo de atividade. Utilizações comuns incluem registos, verificações de autenticação e normalização de pedidos.
Criar um agente
Crie uma subclasse de AgentApplication e registe os seus processadores no construtor. A estrutura de alojamento injeta AgentApplicationOptions automaticamente.
public class MyAgent : AgentApplication
{
public MyAgent(AgentApplicationOptions options) : base(options)
{
OnConversationUpdate(ConversationUpdateEvents.MembersAdded, WelcomeAsync);
OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
}
private async Task WelcomeAsync(ITurnContext context, ITurnState state, CancellationToken ct)
{
foreach (var member in context.Activity.MembersAdded)
{
if (member.Id != context.Activity.Recipient.Id)
{
await context.SendActivityAsync("Hello! How can I help you?", cancellationToken: ct);
}
}
}
private async Task OnMessageAsync(ITurnContext context, ITurnState state, CancellationToken ct)
{
await context.SendActivityAsync($"You said: {context.Activity.Text}", cancellationToken: ct);
}
}
Registe o seu agente em Program.cs:
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient();
builder.Services.AddSingleton<IStorage, MemoryStorage>();
builder.Services.AddAgent<MyAgent>();
builder.Services.AddAgentAspNetAuthentication(builder.Configuration);
WebApplication app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapAgentApplicationEndpoints(requireAuth: !app.Environment.IsDevelopment());
app.Run();
Registe os processadores de atividades
Processar mensagens
Compare mensagens por texto exato (sensível a maiúsculas e minúsculas):
OnMessage("help", async (context, state, ct) =>
{
await context.SendActivityAsync("Here's what I can do...", cancellationToken: ct);
});
Fazer corresponder mensagens através de uma expressão regular:
OnMessage(new Regex(@"^order\s+\d+$", RegexOptions.IgnoreCase), async (context, state, ct) =>
{
await context.SendActivityAsync("Looking up your order...", cancellationToken: ct);
});
Gerir atualizações de conversação
Registe processadores para eventos do ciclo de vida da conversação, como a entrada ou saída de membros.
OnConversationUpdate(ConversationUpdateEvents.MembersAdded, async (context, state, ct) =>
{
foreach (var member in context.Activity.MembersAdded)
{
if (member.Id != context.Activity.Recipient.Id)
{
await context.SendActivityAsync("Welcome!", cancellationToken: ct);
}
}
});
OnConversationUpdate(ConversationUpdateEvents.MembersRemoved, async (context, state, ct) =>
{
// Called when participants leave the conversation
});
Lidar com qualquer tipo de atividade
Faça corresponder qualquer atividade pelo sua cadeia de tipo para obter controlo total sobre o encaminhamento.
OnActivity(ActivityTypes.Message, async (context, state, ct) =>
{
// Handles all message activities
});
OnActivity(ActivityTypes.Event, async (context, state, ct) =>
{
// Handles event activities
});
Utilize ActivityTypes constantes em vez de cadeias de carateres codificadas.
Controlar a ordem de avaliação das rotas
O sistema ordena as rotas numa ordem fixa de avaliação quando as regista, não em runtime. A ordenação utiliza dois níveis:
Tipo de rota: o sistema agrupa as rotas por tipo e avalia sempre tipos de prioridade mais alta antes dos tipos de prioridade mais baixa, independentemente da classificação:
Prioridade Tipo de rota 1 (mais alta) Rotas de invocação por meio de agentes 2 Invocar rotas (ações de cartões adaptativos, chamadas de retorno de OAuth e outras invocações sensíveis ao tempo) 3 Rotas por meio de agentes 4 (mais baixa) Todas as outras rotas Classificação: em cada grupo de tipos de rotas, o sistema ordena as rotas pelo seu valor de classificação. Os valores numéricos mais baixos são avaliados primeiro.
Use as constantes RouteRank para definir a classificação ao registar um processador:
| Constante | valor | Significado |
|---|---|---|
RouteRank.First |
0 |
Avaliado antes de todas as outras rotas do seu grupo |
RouteRank.Unspecified |
32767 |
Predefinido quando não é especificado nenhuma classificação |
RouteRank.Last |
65535 |
Avaliado após todas as outras rotas do seu grupo |
Por predefinição, a avaliação termina na primeira rota correspondente. Utilize RouteRank.Last como uma contingência global que abrange tudo aquilo que não for correspondido por uma rota mais específica.
// Specific handlers use the default rank
OnMessage("status", HandleStatusAsync);
OnMessage("help", HandleHelpAsync);
// Catch-all — handles anything not matched above
OnActivity(ActivityTypes.Message, HandleUnknownMessageAsync, rank: RouteRank.Last);
Hooks do ciclo de vida do turno
Registe lógica que é executada em cada turno, antes ou depois da correspondência de rotas. Estes hooks são úteis para registo, preocupações transversais e processamento de erros.
OnBeforeTurn(async (context, state, ct) =>
{
logger.LogInformation("Turn started: {Type}", context.Activity.Type);
return true; // Return false to abort the turn
});
OnAfterTurn(async (context, state, ct) =>
{
logger.LogInformation("Turn completed");
return true; // Return false to skip state saving
});
OnTurnError(async (context, state, exception, ct) =>
{
logger.LogError(exception, "Turn error");
await context.SendActivityAsync("Something went wrong. Please try again.", cancellationToken: ct);
});
Quando OnBeforeTurn devolve false, o turno é abortado e nenhuma rota é executada. Quando OnAfterTurn devolve false, o estado de turno não é guardado.
Utilizar o estado do turno
O agente carrega automaticamente o estado do turno antes de os seus processadores serem executados e guarda‑o depois. O objeto de estado de turno passado aos seus processadores permite aceder aos diferentes âmbitos, para que possa ler e escrever dados que persistem ao longo dos turnos ou que são efémeros para o turno atual:
- Âmbito da conversa: para dados partilhados em todos os turnos de uma conversa
- Âmbito do utilizador: Para dados de cada utilizador
- Âmbito temporário: para dados que só precisam de existir durante o turno atual
OnActivity(ActivityTypes.Message, async (context, state, ct) =>
{
// Conversation scope — persisted per conversation
var count = state.Conversation.GetValue<int>("messageCount", () => 0);
state.Conversation.SetValue("messageCount", count + 1);
// User scope — persisted per user
var name = state.User.GetValue<string>("displayName");
// Temp scope — current turn only
state.Temp.SetValue("parsedInput", context.Activity.Text?.Trim());
await context.SendActivityAsync($"Message #{count + 1}: {context.Activity.Text}", cancellationToken: ct);
});
Nota
Utilize MemoryStorage para desenvolvimento e testes locais. Para implementações em produção, especialmente implementações a correr em múltiplas instâncias, utilize um fornecedor de armazenamento persistente como Azure Cosmos DB ou Armazenamento de Blobs do Azure. Consulte Utilizar fornecedores de armazenamento no agente