Phase 13 - Lesson 13
Tareas Asíncronas (SEP-1686) — Chame Ahora, Busque Después para Trabajo de Larga Duración
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
El trabajo real del agente toma de minutos a horas: ejecuciones de CI, síntesis de investigación profunda, exportaciones por lotes. Las llamadas a herramientas síncronas caen conexiones, expiran o bloquean la interfaz de usuario. SEP-1686, fusionado el 25/11/2025, agrega una primitiva de Tareas: cualquier solicitud puede aumentarse para convertirse en una tarea, y el resultado puede obtenerse más tarde o transmitirse a través de notificaciones de estado. Nota de riesgo de desviación: las Tareas son experimentales hasta el primer semestre de 2026; la superficie del SDK aún se está diseñando en torno a la especificación.
Tipo: Build Idiomas: Python (stdlib, máquina de estados de tareas asíncronas) Prerrequisitos: Fase 13 · 07 (servidor MCP), Fase 13 · 09 (transportes) Tiempo: ~75 minutos
Objetivos de Aprendizaje
- Identificar cuándo promover una herramienta de síncrona a aumentada por tarea (>30 segundos de trabajo en el servidor).
- Recorrer el ciclo de vida de la tarea:
working→input_required→completed/failed/cancelled. - Persistir el estado de la tarea para que las fallas no pierdan el trabajo en progreso.
- Consultar
tasks/statusy obtenertasks/resultcorrectamente.
El Problema
Una herramienta generate_report ejecuta una canalización de extracción de varios minutos. Opciones bajo el modelo síncrono:
- Mantener la conexión abierta durante tres minutos. Los transportes remotos la caen; los clientes expiran; las interfaces de usuario se congelan.
- Retornar inmediatamente con un marcador de posición; requerir que el cliente consulte un punto de conexión personalizado. Rompe la uniformidad de MCP.
- Ejecutar y olvidar; sin resultado.
Ninguno es bueno. SEP-1686 agrega un cuarto: aumento de tarea. Cualquier solicitud (típicamente tools/call) puede etiquetarse como una tarea. El servidor devuelve un ID de tarea de inmediato. El cliente consulta tasks/status y obtiene tasks/result cuando termina. El estado en el servidor sobrevive a los reinicios.
El Concepto
Aumento de tarea
Una solicitud se convierte en una tarea al establecer params._meta.task.required: true (o optional: true, el servidor decide). El servidor responde de inmediato con:
{
"jsonrpc": "2.0", "id": 1,
"result": {
"_meta": {
"task": {
"id": "tsk_9f7b...",
"state": "working",
"ttl": 900000
}
}
}
}
ttl es la promesa del servidor de retener el estado; después de ttl, el resultado de la tarea se descarta.
Opción por herramienta
Las anotaciones de herramientas pueden declarar soporte para tareas:
taskSupport: "forbidden"— esta herramienta siempre se ejecuta sincrónicamente. Seguro para herramientas rápidas.taskSupport: "optional"— el cliente puede solicitar aumento de tarea.taskSupport: "required"— el cliente DEBE usar aumento de tarea.
Una herramienta generate_report sería required. Una herramienta notes_search sería forbidden.
Estados
working -> input_required -> working (loop via elicitation)
working -> completed
working -> failed
working -> cancelled
La máquina de estados es de tipo append-only: una vez que está en completed, failed o cancelled, la tarea es terminal.
Métodos
tasks/status {taskId}— devuelve el estado actual y una indicación de progreso.tasks/result {taskId}— bloquea o devuelve 404 si aún no se ha completado.tasks/cancel {taskId}— idempotente; los estados terminales lo ignoran.tasks/list— opcional; enumera las tareas activas y completadas recientemente.
Transmisión de cambios de estado
Cuando el servidor lo soporta, el cliente puede suscribirse a notificaciones de estado:
server -> notifications/tasks/updated {taskId, state, progress?}
Los clientes que transmiten en lugar de realizar consultas obtienen una mejor experiencia de usuario (UX). Las consultas siempre se admiten como la superficie mínima.
Estado durable
La especificación exige que los servidores que declaran soporte de tareas persistan el estado. Una falla no debe perder resultados completados dentro del ttl. Los almacenamientos varían desde SQLite a Redis hasta el sistema de archivos. El entorno de la Lección 13 utiliza el sistema de archivos.
Semántica de cancelación
tasks/cancel es idempotente. Si la tarea está a mitad de la ejecución, el servidor intenta detenerla (verificar la cancelación cooperativa del ejecutor). Si ya es terminal, la solicitud es una operación sin efecto (no-op).
Recuperación de fallas
Cuando el proceso del servidor se reinicia:
- Cargar todos los estados de tareas persistidos.
- Marcar cualquier tarea
workingcuyo proceso haya muerto comofailedcon el errorCRASH_RECOVERY. - Preservar
completed/failed/cancelledpara su ttl.
Tareas asíncronas más muestreo
Una tarea puede, por sí misma, llamar a sampling/createMessage. Así es como funcionan las tareas de investigación de larga duración: el hilo de la tarea del servidor muestrea el modelo del cliente según sea necesario, mientras la interfaz de usuario del cliente muestra la tarea como working con actualizaciones periódicas de progreso.
Por que esto es experimental
SEP-1686 se lanzó el 25/11/2025, pero la hoja de ruta más amplia señala tres problemas abiertos: primitivas de suscripción duraderas, subtareas (relaciones de tareas padre-hijo) y estandarización de TTL de resultados. Se espera que la especificación evoluya a lo largo de 2026. El código de producción debe tratar las Tareas como estables solo para el caso común y protegerse contra futuros cambios del SDK para subtareas.
Úsalo
code/main.py implementa un almacenamiento de tareas durable (respaldado por sistema de archivos) y una herramienta generate_report que se ejecuta en un hilo en segundo plano. Los clientes llaman a la herramienta, obtienen un ID de tarea de inmediato, consultan tasks/status mientras el ejecutor actualiza el progreso y obtienen tasks/result cuando termina. El cancelación funciona; la recuperación de fallas se simula matando el hilo del ejecutor y recargando el estado.
Qué observar:
- Estado de la tarea JSON persistido en
/tmp/lesson-13-tasks/<id>.json. - El hilo del ejecutor actualiza el campo
progress; la consulta muestra que avanza. - La cancelación desde el lado del cliente establece un evento; el ejecutor lo comprueba y sale temprano.
- La recarga del estado tras una "falla" marca la tarea en curso como
failedconCRASH_RECOVERY.
Entrégalo
Esta lección produce outputs/skill-task-store-designer.md. Dada una herramienta de larga duración (investigación, compilación, exportación), la habilidad diseña el almacenamiento de tareas (forma del estado, ttl, durabilidad), elige la bandera taskSupport correcta y esboza las notificaciones de progreso.
Ejercicios
- Ejecuta
code/main.py. Inicia una tareagenerate_report, consulta el status y luego obtén el resultado. - Agrega una llamada
tasks/cancela mitad de la ejecución. Verifica que el ejecutor la respete y el estado pase a sercancelled. - Simula la recuperación de fallas: mata el hilo del ejecutor, reinicia el cargador y observa el modo de falla
CRASH_RECOVERY. - Extiende el almacenamiento a SQLite. Los beneficios de durabilidad son los mismos; las opciones de consulta se amplían (listar todas las tareas de la sesión X).
- Lee la publicación de la hoja de ruta de MCP para 2026. Identifica el único problema abierto relacionado con las Tareas que tiene más probabilidades de afectar el diseño de la API del SDK en el próximo año.
Términos Clave
| Término | Lo que la gente dice | Lo que realmente significa |
|---|---|---|
| Task | "Llamada a herramienta de larga duración" | Solicitud aumentada con _meta.task para ejecución asíncrona |
| SEP-1686 | "Especificación de tareas" | Propuesta de Evolución de Especificación (SEP) que agregó Tareas el 25/11/2025 |
_meta.task |
"Sobre de la tarea" | Metadatos por solicitud que contienen id, state, ttl |
| taskSupport | "Bandera de la herramienta" | forbidden / optional / required por herramienta |
tasks/status |
"Método de consulta" | Obtiene el estado actual y una indicación de progreso opcional |
tasks/result |
"Obtener resultado" | Devuelve la carga útil completada o 404 si aún no se ha realizado |
tasks/cancel |
"Detenerlo" | Solicitud de cancelación idempotente |
| ttl | "Presupuesto de retención" | Milisegundos que el servidor promete mantener el estado de la tarea |
notifications/tasks/updated |
"Envio de estado" | Evento de cambio de estado iniciado por el servidor |
| Almacenamiento durable | "Estado a prueba de fallas" | Capa de persistencia en sistema de archivos / SQLite / Redis |
Lectura Adicional
- MCP — GitHub SEP-1686 issue — la propuesta original y discusión completa
- WorkOS — MCP async tasks for AI agent workflows — recorrido de diseño con justificación
- DeepWiki — MCP task system and async operations — mecánica y máquina de estados
- FastMCP — Tasks — patrones de implementación de tareas a nivel de SDK
- MCP blog — 2026 roadmap — problemas abiertos y prioridades para 2026, incluidas las subtareas |