Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
AgentApplication es el bloque de creación central de un agente compilado con el SDK de agentes.
AgentApplication es el punto de entrada de toda la actividad entrante, incluidos los mensajes de los usuarios, los eventos del ciclo de vida de la conversación, las interacciones de tarjetas adaptativas, las devoluciones de llamada de OAuth.
Un agente es, en esencia, un AgentApplication. Se configura con controladores que describen lo que hace su agente. El SDK se encarga del enrutamiento, la gestión del estado y la infraestructura necesaria para ejecutarlo.
Cómo funciona AgentApplication
Cada agente tiene un ciclo de vida que comienza cuando un canal (Microsoft Teams, un Bot Service o un cliente personalizado) entrega una actividad al punto final de tu agente.
AgentApplication está en el centro de ese ciclo de vida:
Channel → Hosting layer → AgentApplication → Your handlers
Las capas de procesamiento en un agente construido con el SDK de Agentes funcionan de la siguiente manera:
- La capa de alojamiento recibe la solicitud HTTP y la autentica.
- El
AgentApplicationprocesa la actividad entrante a través de su flujo de procesamiento. - Se llama a los controladores en función de las rutas coincidentes.
El agente carga el estado de turno antes de que se ejecuten los controladores. Después, el agente guarda el estado del turno.
Conceptos principales
Actividades
Todo en el SDK de agentes fluye como una actividad. Una actividad es un mensaje estructurado que representa algo que ocurrió. Una actividad tiene un tipo, como mensaje, evento, invocar, conversationUpdate, entre otros. Lleva una carga útil relevante para ese tipo.
AgentApplication recibe actividades y las enruta al controlador adecuado.
Rutas
Una ruta empareja un selector con un controlador. El selector determina si una ruta coincide con la actividad actual. El controlador ejecuta la lógica cuando la ruta coincide.
Registra rutas cuando configures tu agente. Pueden coincidir con:
- Un mensaje que contiene texto específico o que coincide con una expresión regular
- Cualquier actividad de un tipo específico
- Eventos del ciclo de vida de la conversación (miembro añadido, miembro eliminado)
- Acciones de la tarjeta adaptable
- Condiciones personalizadas
Cuando llega una actividad, el sistema evalúa las rutas en orden hasta que encuentra una coincidencia. Por defecto, solo se ejecuta una ruta.
Estado de turno
AgentApplication gestiona _turn estado—almacenamiento estructurado particionado en ámbitos:
| Tipo de ámbito | Description |
|---|---|
| Conversación | Compartido para todos los usuarios de una conversación, guardado entre turnos |
| Usuario | Limitado a un usuario individual en todas las conversaciones |
| Temperatura | Solo turno actual: nunca se conserva |
El sistema carga automáticamente el estado antes de que los controladores se ejecuten y lo guarde automáticamente después.
Contexto de turno
Cuando un controlador se ejecuta, recibe un contexto de turno. El contexto de turno es una instantánea de la actividad actual, la conexión del adaptador y las utilidades para enviar respuestas. El contexto del turno es tu interfaz con la interacción actual.
Middleware
AgentApplication admite una canalización de middleware. El middleware es una cadena de componentes que procesan cada turno antes y después de que se ejecuten los controladores. El middleware puede inspeccionar, transformar o cortocircuitar el flujo de actividad. Los usos comunes incluyen el registro de actividades, comprobaciones de autenticación y la normalización de solicitudes.
Crear un agente
Subclasifique AgentApplication y registre los controladores en el constructor. El marco de hosting inyecta automáticamente 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);
}
}
Registre el agente en 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();
Registre controladores de actividad
Manejar mensajes
Buscar mensajes con texto exacto (sin distinguir entre mayúsculas y minúsculas):
OnMessage("help", async (context, state, ct) =>
{
await context.SendActivityAsync("Here's what I can do...", cancellationToken: ct);
});
Buscar los mensajes utilizando una expresión regular:
OnMessage(new Regex(@"^order\s+\d+$", RegexOptions.IgnoreCase), async (context, state, ct) =>
{
await context.SendActivityAsync("Looking up your order...", cancellationToken: ct);
});
Controlar actualizaciones de conversación
Registre los controladores para los eventos del ciclo de vida de la conversación, como la incorporación o salida de miembros.
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
});
Controlar cualquier tipo de actividad
Coincida con cualquier actividad mediante su cadena de tipo para tener un control total sobre el enrutamiento.
OnActivity(ActivityTypes.Message, async (context, state, ct) =>
{
// Handles all message activities
});
OnActivity(ActivityTypes.Event, async (context, state, ct) =>
{
// Handles event activities
});
Use constantes de ActivityTypes en lugar de cadenas codificadas de forma fija.
Controlar el orden de evaluación de rutas
El sistema ordena las rutas en un orden fijo de evaluación cuando las registras, no en tiempo de ejecución. La ordenación se realiza en dos niveles:
Tipo de ruta: El sistema agrupa las rutas por tipo y siempre evalúa los tipos de mayor prioridad antes que los de menor prioridad, independientemente del rango:
Prioridad Tipo de ruta 1 (el más alto) Rutas de invocación agénticas 2 Invocar rutas (acciones de tarjeta adaptables, devoluciones de llamada de OAuth y otras invocaciones sensibles al tiempo) 3 Rutas agénticas 4 (el más bajo) Todas las demás rutas Rango: Dentro de cada grupo de tipos de rutas, el sistema ordena las rutas por su valor de rango. Los valores numéricos más bajos se evalúan primero.
Use RouteRank constantes para establecer la clasificación al registrar un controlador:
| Constante | Valor | Significado |
|---|---|---|
RouteRank.First |
0 |
Se evalúa antes de todas las demás rutas de su grupo |
RouteRank.Unspecified |
32767 |
De forma predeterminada, cuando no se especifica ningún rango |
RouteRank.Last |
65535 |
Se evalúa después de todas las demás rutas de su grupo |
Por defecto, la evaluación se detiene en la primera ruta coincidente. Utilice RouteRank.Last como opción de reserva general que gestione todo aquello que no coincida con una ruta más 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);
Enlaces de ciclo de vida de turnos
Registrar lógica que se ejecuta en cada turno, antes o después del emparejamiento de rutas. Estos enlaces son útiles para el registro, los problemas transversales y el control de errores.
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);
});
Cuando OnBeforeTurn devuelve false, el turno se aborta y no se ejecuta ninguna ruta. Cuando OnAfterTurn devuelve false, no se guarda el estado de turno.
Usar el estado del turno
El agente carga automáticamente el estado de turno antes de que los controladores se ejecuten y lo guarde después. El objeto de estado de turno que se pasa a sus controladores le permite tener acceso a los distintos ámbitos, de modo que puede leer y escribir datos que persisten entre turnos o que son efímeros para el turno actual:
- Ámbito de conversación: para los datos compartidos en todos los turnos de una conversación
- Ámbito de usuario: Para datos por usuario
- Ámbito temporal: Para datos que solo necesitan existir durante el turno actual
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
Use MemoryStorage para desarrollo y pruebas locales. Para despliegues en producción, especialmente aquellos que se ejecutan en múltiples instancias, utiliza un proveedor de almacenamiento persistente como Azure Cosmos DB o Azure Blob Storage. Consulte Usar proveedores de almacenamiento en el agente.