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 elemento central de um agente criado com o SDK Agents. 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 é, no seu cerne, um AgentApplication. Configuras o sistema com handlers que especificam o que o teu agente faz. O SDK trata do encaminhamento, da gestão de estados e da infraestrutura necessária para executá-lo.
Como funciona o AgentApplication
Cada agente tem um ciclo de vida que começa quando um canal (Microsoft Teams, um serviço de bots ou um cliente personalizado) entrega uma atividade ao endpoint do seu agente.
AgentApplication está no centro desse ciclo de vida:
Channel → Hosting layer → AgentApplication → Your handlers
As camadas de processamento num agente construído com o SDK dos Agentes funcionam da seguinte forma:
- A camada de alojamento recebe o pedido HTTP e autentica-o.
- O
AgentApplicationprocessa a atividade recebida 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 do Agente flui como uma atividade. Uma atividade é uma mensagem estruturada que representa algo que aconteceu. Uma atividade tem um tipo, como mensagem, evento, invocação, atualização de conversa, e assim por diante. Transporta uma carga útil relevante para esse tipo.
AgentApplication recebe as atividades e encaminha-as para o gestor adequado.
Routes
Uma rota emparelha um seletor com um handler. O seletor determina se uma rota corresponde à atividade atual. O manipulador executa a sua lógica quando a rota coincide.
Registe rotas quando configurares o teu agente. Podem combinar:
- Uma mensagem contendo texto específico ou correspondendo a uma expressão regular
- Qualquer atividade de um dado tipo
- Eventos do ciclo de vida da conversa (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 | Description |
|---|---|
| Conversação | Partilhado entre todos os utilizadores numa conversação, persistindo entre turnos |
| Utilizador | Limitado a um usuário específico em todas as conversas |
| Temporário | Só no turno atual - nunca persiste |
O sistema carrega automaticamente o estado antes de os teus handlers executarem e guarda-o automaticamente depois.
Contexto do turno
Quando um manipulador é 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 curto-circuitar o fluxo de atividade. Utilizações comuns incluem registos, verificações de autenticação e normalização de pedidos.
Criar um agente
Subclasse AgentApplication e registe os seus handlers no construtor. O framework de alojamento injeta automaticamente AgentApplicationOptions.
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();
Registar manipuladores de atividade
Tratar mensagens
Corresponder mensagens por texto exato (sem distinção entre 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);
});
Lidar com atualizações de conversas
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
});
Usa ActivityTypes constantes em vez de cadeias codificadas fixamente.
Ordem de avaliação da rota de controlo
O sistema ordena as rotas numa ordem fixa de avaliação quando as registas, não em tempo de execução. A ordenação utiliza dois níveis:
Tipo de rota: O sistema agrupa as rotas por tipo e avalia sempre os tipos de prioridade superior antes dos de prioridade inferior, independentemente da classificação:
Prioridade Tipo de rota 1 (mais alto) Rotas de invocação de agente 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 baixo) Todas as outras rotas Classificação: Dentro de 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 RouteRank constantes para definir o ranking ao registar um manipulador:
| Constante | Value | Significado |
|---|---|---|
RouteRank.First |
0 |
Avaliado antes de todas as outras rotas do seu grupo |
RouteRank.Unspecified |
32767 |
Padrão quando não é especificado nenhum posto |
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 regressa 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 estado de turno passado aos teus manipuladores dá-te acesso aos diferentes escopos para que possas 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 todas as fases de uma conversa
- Âmbito do utilizador: Para dados por 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);
});
Observação
Uso MemoryStorage para desenvolvimento local e testes. Para implementações em produção, especialmente em múltiplas instâncias, utilize um fornecedor de armazenamento persistente como o Azure Cosmos DB ou o Armazenamento de Blobs do Azure. Veja Utilizar fornecedores de armazenamento no seu agente.