El bucle de un vistazo
Cada sesión de agente sigue el mismo ciclo:- Recibir prompt. Claude recibe su prompt, junto con el prompt del sistema, las definiciones de herramientas e historial de conversación. El SDK produce un
SystemMessagecon subtipo"init"que contiene metadatos de sesión. - Evaluar y responder. Claude evalúa el estado actual y determina cómo proceder. Puede responder con texto, solicitar una o más llamadas de herramientas, o ambas. El SDK produce uno o más objetos
AssistantMessage, uno para cada bloque de contenido, como un bloque de texto o una solicitud de llamada de herramienta. - Ejecutar herramientas. El SDK ejecuta cada herramienta solicitada y recopila los resultados. Cada conjunto de resultados de herramientas se retroalimenta a Claude para la siguiente decisión. Puede usar hooks para interceptar, modificar o bloquear llamadas de herramientas antes de que se ejecuten.
- Repetir. Los pasos 2 y 3 se repiten como un ciclo. Cada ciclo completo es un turno. Claude continúa llamando a herramientas y procesando resultados hasta que produce una respuesta sin llamadas de herramientas.
- Devolver resultado. El SDK produce un
AssistantMessagefinal con la respuesta de texto (sin llamadas de herramientas), seguido de unResultMessagecon el texto final, uso de tokens, costo e ID de sesión.
Glob y respondiendo con los resultados. Una tarea compleja (“refactorizar el módulo de autenticación y actualizar las pruebas”) puede encadenar docenas de llamadas de herramientas en muchos turnos, leyendo archivos, editando código y ejecutando pruebas, con Claude ajustando su enfoque basado en cada resultado.
Turnos y mensajes
Un turno es un viaje de ida y vuelta dentro del bucle: Claude produce una salida que incluye llamadas de herramientas, el SDK ejecuta esas herramientas y los resultados se devuelven a Claude automáticamente. Esto sucede sin ceder el control a su código. Los turnos continúan hasta que Claude produce una salida sin llamadas de herramientas, momento en el cual el bucle termina y se entrega el resultado final. Considere cómo podría verse una sesión completa para el prompt “Arregla las pruebas fallidas en auth.ts”. Primero, el SDK envía su prompt a Claude y produce unSystemMessage con los metadatos de sesión. Luego comienza el bucle:
- Turno 1: Claude llama a
Bashpara ejecutarnpm test. El SDK produce unAssistantMessagecon la llamada de herramienta, ejecuta el comando, luego produce unUserMessagecon la salida (tres fallos). - Turno 2: Claude llama a
Readenauth.tsyauth.test.ts. El SDK produce unAssistantMessagepara cada llamada y devuelve el contenido del archivo. - Turno 3: Claude llama a
Editpara arreglarauth.ts, luego llama aBashpara volver a ejecutarnpm test. Las tres pruebas pasan. El SDK produce unAssistantMessagepara cada llamada. - Turno final: Claude produce una respuesta solo de texto sin llamadas de herramientas: “Arreglé el error de autenticación, las tres pruebas pasan ahora.” El SDK produce un
AssistantMessagefinal con este texto, luego unResultMessagecon el mismo texto más costo y uso.
max_turns / maxTurns, que cuenta solo los turnos de uso de herramientas. Por ejemplo, max_turns=2 en el bucle anterior se habría detenido antes del paso de edición. También puede usar max_budget_usd / maxBudgetUsd para limitar los turnos basándose en un umbral de gasto.
Sin límites, el bucle se ejecuta hasta que Claude termine por su cuenta, lo cual está bien para tareas bien delimitadas pero puede ejecutarse durante mucho tiempo en prompts abiertos (“mejora esta base de código”). Establecer un presupuesto es un buen valor predeterminado para agentes de producción. Vea Turnos y presupuesto a continuación para la referencia de opciones.
Tipos de mensajes
A medida que se ejecuta el bucle, el SDK produce un flujo de mensajes. Cada mensaje lleva un tipo que le indica en qué etapa del bucle se originó. Los cinco tipos principales son:-
SystemMessage: eventos del ciclo de vida de la sesión. El camposubtypelos distingue:"init": metadatos de sesión para la ejecución. Cuando un hookSessionStartoSetupse ejecuta durante el inicio de la sesión, sus mensajes del ciclo de vida del hook llegan antes del mensajeinit"compact_boundary": se dispara después de compactación"informational": banners de estado de texto sin formato del bucle"worker_shutting_down": el host se está cerrando o Remote Control se desconectó
"init"es su propio tipo en la uniónSDKMessageen lugar de un subtipo deSDKSystemMessage. -
AssistantMessage: emitido para cada bloque de contenido en las respuestas de Claude, incluido el final solo de texto. Cada uno lleva un único bloque de contenido, como texto o una llamada de herramienta, y los mensajes de una respuesta comparten un ID de mensaje. -
UserMessage: emitido después de cada ejecución de herramienta con el contenido del resultado de la herramienta enviado de vuelta a Claude. También se emite para cualquier entrada de usuario que transmita a mitad del bucle. -
StreamEvent: solo se emite cuando los mensajes parciales están habilitados. Contiene eventos de transmisión de API sin procesar (deltas de texto, fragmentos de entrada de herramientas). Vea Respuestas de transmisión. -
ResultMessage: marca el final del bucle del agente. Contiene el resultado de texto final, uso de tokens, costo e ID de sesión. Verifique el camposubtypepara determinar si la tarea tuvo éxito o alcanzó un límite. Un pequeño número de eventos del sistema finales, comoprompt_suggestion, pueden llegar después, así que itere el flujo hasta completarse en lugar de romper en el resultado. Vea Manejar el resultado.
Manejar mensajes
Qué mensajes maneja depende de lo que esté construyendo:- Solo resultados finales: maneje
ResultMessagepara obtener la salida, el costo y si la tarea tuvo éxito o alcanzó un límite. - Actualizaciones de progreso: maneje
AssistantMessagepara ver qué está haciendo Claude en cada turno, incluidas las herramientas que llamó. - Transmisión en vivo: habilite mensajes parciales (
include_partial_messagesen Python,includePartialMessagesen TypeScript) para obtener mensajesStreamEventen tiempo real. Vea Respuestas de transmisión en tiempo real.
- Python: verifique los tipos de mensajes con
isinstance()contra clases importadas declaude_agent_sdk(por ejemplo,isinstance(message, ResultMessage)). - TypeScript: verifique el campo de cadena
type(por ejemplo,message.type === "result").AssistantMessageyUserMessageenvuelven el mensaje de API sin procesar en un campo.message, por lo que los bloques de contenido están enmessage.message.content, no enmessage.content.
Ejemplo: Verificar tipos de mensajes y manejar resultados
Ejemplo: Verificar tipos de mensajes y manejar resultados
Ejecución de herramientas
Las herramientas dan a su agente la capacidad de tomar acciones. Sin herramientas, Claude solo puede responder con texto. Con herramientas, Claude puede leer archivos, ejecutar comandos, buscar código e interactuar con servicios externos.Herramientas integradas
El SDK incluye las mismas herramientas que potencian Claude Code:
En los modelos que no obtienen las herramientas de seguimiento de tareas, Claude Code proporciona
TaskCreate y TaskUpdate solo cuando usted se suscribe.
Más allá de las herramientas integradas, puede:
- Conectar servicios externos con servidores MCP (bases de datos, navegadores, APIs)
- Definir herramientas personalizadas con manejadores de herramientas personalizadas
- Cargar skills del proyecto a través de fuentes de configuración para flujos de trabajo reutilizables
Permisos de herramientas
Claude determina qué herramientas llamar basándose en la tarea, pero usted controla si esas llamadas pueden ejecutarse. Puede aprobar automáticamente herramientas específicas, bloquear otras completamente o requerir aprobación para todo. Tres opciones funcionan juntas para determinar qué se ejecuta:allowed_tools/allowedToolsaprueba automáticamente las herramientas listadas. Un agente de solo lectura con["Read", "Glob", "Grep"]en su lista de herramientas permitidas ejecuta esas herramientas sin pedir confirmación, salvo las lecturas desde rutas de red. Las herramientas no listadas aún están disponibles, y las llamadas a ellas que necesitan aprobación se transfieren al modo de permisos y acanUseTool.disallowed_tools/disallowedToolsbloquea las herramientas listadas, independientemente de otras configuraciones. Vea Permisos para el orden en que se verifican las reglas antes de que se ejecute una herramienta.permission_mode/permissionModecontrola cuánta supervisión humana desea. El SDK evalúa el modo activo junto con sus reglas de permitir y denegar en un orden fijo, descrito en Cómo se evalúan los permisos. Vea Modo de permiso para los modos disponibles.
"Bash(npm *)" para permitir solo comandos específicos. Vea Permisos para la sintaxis completa de reglas.
Cuando se deniega una herramienta, Claude recibe un mensaje de rechazo como resultado de la herramienta e intenta típicamente un enfoque diferente o reporta que no pudo proceder.
Ejecución paralela de herramientas
Cuando Claude solicita múltiples llamadas de herramientas en un solo turno, ambos SDK pueden ejecutarlas concurrentemente o secuencialmente dependiendo de la herramienta. Las herramientas de solo lectura (comoRead, Glob, Grep y herramientas MCP marcadas como de solo lectura) pueden ejecutarse concurrentemente. Las herramientas que modifican estado (como Edit, Write y Bash) se ejecutan secuencialmente para evitar conflictos.
Las herramientas personalizadas tienen ejecución secuencial de forma predeterminada. Para habilitar la ejecución paralela para una herramienta personalizada, establezca readOnlyHint en sus anotaciones. Ambos SDK de TypeScript y Python usan este nombre de campo del SDK de MCP.
Controlar cómo se ejecuta el bucle
Puede limitar cuántos turnos toma el bucle, cuánto cuesta, cuán profundamente razona Claude y si las herramientas requieren aprobación antes de ejecutarse. Todos estos son campos enClaudeAgentOptions (Python) / Options (TypeScript).
Turnos y presupuesto
Cuando se alcanza cualquiera de los límites, el SDK devuelve un
ResultMessage con un subtipo de error correspondiente (error_max_turns o error_max_budget_usd). Vea Manejar el resultado para cómo verificar estos subtipos y ClaudeAgentOptions / Options para la sintaxis.
El límite de presupuesto cubre subagentes: su gasto cuenta hacia el total. Una vez que el gasto alcanza el límite, generar otro subagente falla con Budget limit reached, y Claude Code detiene cualquier subagente de fondo que aún se esté ejecutando. Los comportamientos de cumplimiento del límite requieren Claude Code v2.1.217 o posterior.
Con entrada de transmisión, un mensaje que aún está en cola cuando un turno termina en el límite de máximo de turnos permanece en cola. Claude Code no lo agrega a la última llamada del modelo de ese turno. Inicia un nuevo turno para el mensaje, y el conteo de máximo de turnos comienza de nuevo para ese turno. El total de presupuesto sigue acumulándose entre mensajes, y una vez que el gasto alcanza maxBudgetUsd, los mensajes posteriores en la misma conversación terminan con el resultado error_max_budget_usd. Un /clear reinicia el presupuesto.
Margen del presupuesto
Claude Code compara el gasto con el límitemax_budget_usd / maxBudgetUsd después de que llegan las respuestas del modelo, porque el costo de cada respuesta proviene del uso de tokens que la API devuelve con ella. La respuesta que alcanza el límite aún se completa y cuenta para total_cost_usd. Por lo tanto, el gasto puede superar el límite hasta en el costo de esa respuesta, más lo que gasten los subagentes que aún se estén ejecutando en ese momento antes de detenerse. Deja un margen para esto cuando establezcas el límite.
Nivel de esfuerzo
La opcióneffort controla cuánto razonamiento aplica Claude. Los niveles de esfuerzo más bajos usan menos tokens por turno y reducen el costo. No todos los modelos soportan el parámetro de esfuerzo. Vea Esfuerzo para qué modelos lo soportan.
Si no establece
effort, Claude Code resuelve el nivel de esfuerzo por sí mismo, en el orden que Ajustar nivel de esfuerzo describe.
effort intercambia latencia y costo de token por profundidad de razonamiento dentro de cada respuesta. Extended thinking es una característica separada que produce bloques de thinking en la salida, y el campo display en ThinkingConfig para Python o TypeScript controla si recibe su texto. Son independientes: puede establecer effort: "low" con extended thinking habilitado, o effort: "max" sin él.effort en las opciones de nivel superior query() para toda la sesión, o por subagente con el campo effort en AgentDefinition para anular el nivel de sesión.
Modo de permiso
La opción de modo de permiso (permission_mode en Python, permissionMode en TypeScript) controla si el agente solicita aprobación antes de usar herramientas:
Para aplicaciones interactivas, use
"default" con una devolución de llamada de aprobación de herramienta para mostrar solicitudes de aprobación. Para agentes autónomos en una máquina de desarrollo, "acceptEdits" aprueba automáticamente ediciones de archivo y comandos comunes del sistema de archivos (mkdir, touch, mv, cp, etc.) mientras aún controla otros comandos de Bash detrás de reglas de permitir. Reserve "bypassPermissions" para CI, contenedores u otros entornos aislados. Vea Permisos para detalles completos.
Modelo
Establezca la opciónmodel para elegir qué modelo ejecuta la sesión. Para más información, vea Elegir un modelo.
La ventana de contexto
La ventana de contexto es la cantidad total de información disponible para Claude durante una sesión. No se reinicia entre turnos dentro de una sesión. Todo se acumula: el prompt del sistema, definiciones de herramientas, historial de conversación, entradas de herramientas y salidas de herramientas. El contenido que permanece igual en todos los turnos (prompt del sistema, definiciones de herramientas, CLAUDE.md) se almacena automáticamente en caché de prompt, lo que reduce el costo y la latencia para prefijos repetidos. Para saber cómo un prompt del sistema personalizado o textoappend afecta la reutilización de caché entre sesiones, vea Modificar prompts del sistema.
Qué consume contexto
Aquí está cómo cada componente afecta el contexto en el SDK:
Las salidas de herramientas grandes consumen contexto significativo. Leer un archivo grande o ejecutar un comando con salida detallada puede usar miles de tokens en un solo turno. El contexto se acumula en turnos, así que sesiones más largas con muchas llamadas de herramientas acumulan significativamente más contexto que las cortas.
Compactación automática
Cuando la ventana de contexto se acerca a su límite, el SDK compacta automáticamente la conversación: resume el historial anterior para liberar espacio, manteniendo intactos sus intercambios más recientes y decisiones clave. El SDK emite un mensaje contype: "system" y subtype: "compact_boundary" en el flujo cuando esto sucede (en Python esto es un SystemMessage; en TypeScript es un tipo separado SDKCompactBoundaryMessage).
La compactación reemplaza mensajes anteriores con un resumen, así que instrucciones específicas del inicio de la conversación pueden no preservarse. Las reglas persistentes pertenecen a CLAUDE.md (cargado a través de settingSources) en lugar de en el prompt inicial, porque el contenido de CLAUDE.md se reinyecta en cada solicitud.
Puede personalizar el comportamiento de compactación de varias maneras:
- Instrucciones de resumen en CLAUDE.md: El compactador lee su CLAUDE.md como cualquier otro contexto, así que puede incluir una sección diciéndole qué preservar al resumir. El compactador coincide en intención, así que el encabezado de la sección es de forma libre.
- Hook
PreCompact: Ejecute lógica personalizada antes de que ocurra la compactación, por ejemplo para archivar la transcripción completa. El hook recibe un campotrigger(manualoauto). Vea hooks. - Compactación manual: Envíe
/compactcomo una cadena de prompt para activar la compactación bajo demanda. Los comandos enviados de esta manera son entradas de SDK ordinarias. Vea dispatch commands by name.
Ejemplo: Instrucciones de resumen en CLAUDE.md
Ejemplo: Instrucciones de resumen en CLAUDE.md
Agregue una sección al CLAUDE.md de su proyecto diciéndole al compactador qué preservar. El nombre del encabezado no es especial; use cualquier etiqueta clara.
CLAUDE.md
Mantener el contexto eficiente
Algunas estrategias para agentes de larga duración:- Usa subagentes para subtareas. Cada subagente comienza con una conversación nueva (sin historial de mensajes anterior, aunque carga su propio prompt del sistema y contexto a nivel de proyecto como CLAUDE.md). No ve los turnos del padre, y solo su respuesta final regresa al padre. El contexto del agente principal crece por ese resumen, no por la transcripción completa de la subtarea. Consulta Qué heredan los subagentes para más detalles.
- Sea selectivo con herramientas. Cada definición de herramienta toma espacio de contexto. Use el campo
toolsenAgentDefinitionpara limitar subagentes al conjunto mínimo que necesitan. - Observe costos de servidor MCP. Búsqueda de herramientas MCP difiere esquemas de herramientas MCP por defecto y los carga bajo demanda. Cuando la búsqueda de herramientas está desactivada o ha retrocedido a carga anticipada, cada servidor MCP agrega todos sus esquemas de herramientas a cada solicitud, así que algunos servidores con muchas herramientas pueden consumir contexto significativo antes de que el agente haga ningún trabajo. Vea Configurar búsqueda de herramientas para las configuraciones donde se aplica el retroceso.
- Use esfuerzo más bajo para tareas rutinarias. Establezca esfuerzo a
"low"para agentes que solo necesitan leer archivos o listar directorios. Esto reduce el uso de tokens y el costo.
Sesiones y continuidad
Cada interacción con el SDK crea o continúa una sesión. Capture el ID de sesión deResultMessage.session_id (disponible en ambos SDK) para reanudar más tarde. El SDK de TypeScript también lo expone como un campo directo en el SystemMessage de init; en Python está anidado en SystemMessage.data.
Cuando reanuda, el contexto completo de turnos anteriores se restaura: archivos que fueron leídos, análisis que fue realizado y acciones que fueron tomadas. También puede bifurcar una sesión para ramificarse en un enfoque diferente sin modificar el original.
Vea Gestión de sesiones para la guía completa en patrones de reanudar, continuar y bifurcar. Para reanudar sesiones en contenedores sin estado u hosts sin servidor, pase un adaptador session_store / sessionStore para que el SDK refleje transcripciones en su propio backend y otro host pueda reanudarlas. El subproceso Claude Code aún escribe en disco local primero. Vea Arquitectura de escritura dual para saber qué copia sobrevive a una sesión nueva versus una ejecución reanudada desde el almacén, y cómo mantener la copia local efímera.
En Python,
ClaudeSDKClient maneja IDs de sesión automáticamente en múltiples llamadas. Vea la referencia del SDK de Python para detalles.Manejar el resultado
Cuando el bucle termina, elResultMessage le dice qué sucedió y le proporciona la salida. El campo subtype (disponible en ambos SDK) es la forma principal de verificar el estado de terminación.
El campo
result contiene la salida de texto final y solo está presente en la variante success, así que siempre verifique el subtipo antes de leerlo.
Todos los subtipos de resultado llevan total_cost_usd, usage, num_turns e session_id para que pueda rastrear el costo y reanudar incluso después de errores. Protéjase para estos casos:
- Después de un bloqueo de sesión, el resultado final es un
error_during_executioncuyos campos de costo pueden estar en cero y cuyostop_reasonesnull, y el proceso sale después de emitirlo. Vea Recuperar totales después de un bloqueo de sesión. - En Python,
total_cost_usd,usageymodel_usagese escriben como opcionales, así que verifique que no seanNoneantes de leerlos.
usage cubre solo el bucle del agente principal. Use modelUsage, o model_usage en Python, para la contabilidad de tokens y costos de todo el árbol. Vea Rastrear costos y uso para detalles sobre la interpretación de los campos usage.
Cuando una consulta termina en un resultado de error:
- Una llamada
query()de un solo disparo produce el mensaje de resultado final y luego genera un error que incluye el texto de fallo, comoReached maximum number of turns. La generación es intencional. Envuelva el bucle en un bloque try si su código necesita continuar más allá de él. El proceso Claude Code subyacente también sale con un código distinto de cero. - Una sesión de entrada de transmisión permanece activa, y puede seguir enviando mensajes, excepto después de un bloqueo de sesión, que emite un resultado final
error_during_executiony sale del proceso.
stop_reason (string | null en TypeScript, str | None en Python) indicando por qué el modelo dejó de generar en su turno final. Los valores comunes son end_turn (modelo terminó normalmente), max_tokens (alcanzó el límite de token de salida) y refusal (el modelo rechazó la solicitud). En resultados de error que el bucle produjo, stop_reason lleva el valor de la última respuesta de asistente antes de que el bucle terminara; el resultado que Claude Code sintetiza después de un bloqueo de sesión lleva null.
Para detectar rechazos, verifique stop_reason === "refusal" (TypeScript) o stop_reason == "refusal" (Python). Vea SDKResultMessage (TypeScript) o ResultMessage (Python) para el tipo completo.
Hooks
Hooks son devoluciones de llamada que se disparan en puntos específicos del bucle: antes de que se ejecute una herramienta, después de que regresa, cuando el agente termina, y así sucesivamente. Algunos hooks comúnmente usados son:
Los hooks se ejecutan en su proceso de aplicación, no dentro de la ventana de contexto del agente, así que no consumen contexto. Los hooks también pueden cortocircuitar el bucle: un hook
PreToolUse que rechaza una llamada de herramienta evita que se ejecute, y Claude recibe el mensaje de rechazo en su lugar.
Ambos SDK soportan todos los eventos anteriores. El SDK de TypeScript incluye eventos adicionales que Python aún no soporta. Vea Controlar ejecución con hooks para la lista completa de eventos, disponibilidad por SDK y la API de devolución de llamada completa.
Ponerlo todo junto
Este ejemplo combina los conceptos clave de esta página en un único agente que arregla pruebas fallidas. Configura el agente con herramientas permitidas (aprobadas automáticamente para que el agente se ejecute autónomamente), configuración del proyecto y límites de seguridad en turnos y esfuerzo de razonamiento. A medida que se ejecuta el bucle, captura el ID de sesión para posible reanudación, maneja el resultado final e imprime el costo total. Debido a que una única llamadaquery() genera una excepción después de producir un resultado de error, el bucle se envuelve en un bloque try para que el script se cierre correctamente cuando se alcanza un límite.
Done: con el resumen del agente sobre la corrección, seguida de una línea como Cost: $0.0312.
Próximos pasos
Ahora que entiende el bucle, aquí está dónde ir dependiendo de lo que esté construyendo:- ¿Aún no ha ejecutado un agente? Comience con el inicio rápido para obtener el SDK instalado y ver un ejemplo completo ejecutándose de principio a fin.
- ¿Listo para conectarse a su proyecto? Cargue CLAUDE.md, skills y hooks del sistema de archivos para que el agente siga automáticamente las convenciones de su proyecto.
- ¿Construyendo una interfaz de usuario interactiva? Habilite transmisión para mostrar texto en vivo y llamadas de herramientas a medida que se ejecuta el bucle.
- ¿Necesita control más ajustado sobre lo que el agente puede hacer? Bloquee el acceso a herramientas con permisos y use hooks para auditar, bloquear o transformar llamadas de herramientas antes de que se ejecuten.
- ¿Ejecutando tareas largas o costosas? Descargue trabajo aislado a subagentes para mantener su contexto principal delgado.
- ¿Implementando como servicio? Vea Alojamiento del Agent SDK para orientación sobre contenedores y sin servidor, y Almacenamiento de sesión para persistir sesiones en su propio backend.