Was this page helpful?
Los subagentes son instancias de agente separadas que su agente principal puede generar para manejar subtareas enfocadas. Use subagentes para aislar contexto en subtareas enfocadas, ejecutar múltiples análisis en paralelo y aplicar instrucciones especializadas sin sobrecargar el prompt del agente principal.
Esta guía explica cómo definir y usar subagentes en el SDK usando el parámetro agents.
Puede crear subagentes de tres formas:
agents en sus opciones de query() (TypeScript, Python).claude/agents/ (vea definir subagentes como archivos)general-purpose en cualquier momento a través de la herramienta Task sin que usted defina nadaEsta guía se enfoca en el enfoque programático, que se recomienda para aplicaciones SDK.
Cuando define subagentes, Claude decide si invocarlos basándose en el campo description de cada subagente. Escriba descripciones claras que expliquen cuándo se debe usar el subagente, y Claude delegará automáticamente las tareas apropiadas. También puede solicitar explícitamente un subagente por nombre en su prompt (por ejemplo, "Usa el agente code-reviewer para...").
Los subagentes mantienen contexto separado del agente principal, previniendo sobrecarga de información y manteniendo las interacciones enfocadas. Este aislamiento asegura que las tareas especializadas no contaminen el contexto de la conversación principal con detalles irrelevantes.
Ejemplo: un subagente research-assistant puede explorar docenas de archivos y páginas de documentación sin saturar la conversación principal con todos los resultados de búsqueda intermedios, devolviendo solo los hallazgos relevantes.
Múltiples subagentes pueden ejecutarse concurrentemente, acelerando dramáticamente flujos de trabajo complejos.
Ejemplo: durante una revisión de código, puede ejecutar los subagentes style-checker, security-scanner y test-coverage simultáneamente, reduciendo el tiempo de revisión de minutos a segundos.
Cada subagente puede tener prompts de sistema personalizados con experiencia específica, mejores prácticas y restricciones.
Ejemplo: un subagente database-migration puede tener conocimiento detallado sobre mejores prácticas de SQL, estrategias de reversión y verificaciones de integridad de datos que serían ruido innecesario en las instrucciones del agente principal.
Los subagentes pueden limitarse a herramientas específicas, reduciendo el riesgo de acciones no intencionadas.
Ejemplo: un subagente doc-reviewer podría tener acceso solo a las herramientas Read y Grep, asegurando que pueda analizar pero nunca modificar accidentalmente sus archivos de documentación.
Defina subagentes directamente en su código usando el parámetro agents. Este ejemplo crea dos subagentes: un revisor de código con acceso de solo lectura y un ejecutor de pruebas que puede ejecutar comandos. La herramienta Task debe incluirse en allowedTools ya que Claude invoca subagentes a través de la herramienta Task.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
description | string | Sí | Descripción en lenguaje natural de cuándo usar este agente |
prompt | string | Sí | El prompt del sistema del agente que define su rol y comportamiento |
tools | string[] | No | Array de nombres de herramientas permitidas. Si se omite, hereda todas las herramientas |
model | 'sonnet' | 'opus' | 'haiku' | 'inherit' | No |
Los subagentes no pueden generar sus propios subagentes. No incluya Task en el array tools de un subagente.
También puede definir subagentes como archivos markdown en directorios .claude/agents/. Vea la documentación de subagentes de Claude Code para detalles sobre este enfoque. Los agentes definidos programáticamente tienen precedencia sobre los agentes basados en sistema de archivos con el mismo nombre.
Incluso sin definir subagentes personalizados, Claude puede generar el subagente integrado general-purpose cuando Task está en su allowedTools. Esto es útil para delegar tareas de investigación o exploración sin crear agentes especializados.
Claude decide automáticamente cuándo invocar subagentes basándose en la tarea y la description de cada subagente. Por ejemplo, si define un subagente performance-optimizer con la descripción "Performance optimization specialist for query tuning", Claude lo invocará cuando su prompt mencione optimizar consultas.
Escriba descripciones claras y específicas para que Claude pueda hacer coincidir las tareas con el subagente correcto.
Para garantizar que Claude use un subagente específico, mencione su nombre en su prompt:
"Use the code-reviewer agent to check the authentication module"Esto omite la coincidencia automática e invoca directamente el subagente nombrado.
Puede crear definiciones de agentes dinámicamente basándose en condiciones en tiempo de ejecución. Este ejemplo crea un revisor de seguridad con diferentes niveles de rigurosidad, usando un modelo más potente para revisiones estrictas.
Los subagentes se invocan a través de la herramienta Task. Para detectar cuándo se invoca un subagente, busque bloques tool_use con name: "Task". Los mensajes desde dentro del contexto de un subagente incluyen un campo parent_tool_use_id.
Este ejemplo itera a través de mensajes transmitidos, registrando cuándo se invoca un subagente y cuándo los mensajes posteriores se originan desde dentro del contexto de ejecución de ese subagente.
La estructura del mensaje difiere entre SDKs. En Python, los bloques de contenido se acceden directamente a través de message.content. En TypeScript, SDKAssistantMessage envuelve el mensaje de la API de Claude, por lo que el contenido se accede a través de message.message.content.
Los subagentes pueden reanudarse para continuar donde se quedaron. Los subagentes reanudados retienen su historial de conversación completo, incluyendo todas las llamadas de herramientas anteriores, resultados y razonamiento. El subagente continúa exactamente donde se detuvo en lugar de comenzar de nuevo.
Cuando un subagente se completa, Claude recibe su ID de agente en el resultado de la herramienta Task. Para reanudar un subagente programáticamente:
session_id de los mensajes durante la primera consultaagentId del contenido del mensajeresume: sessionId en las opciones de la segunda consulta e incluya el ID del agente en su promptDebe reanudar la misma sesión para acceder a la transcripción del subagente. Cada llamada a query() inicia una nueva sesión por defecto, así que pase resume: sessionId para continuar en la misma sesión.
Si está usando un agente personalizado (no uno integrado), también necesita pasar la misma definición de agente en el parámetro agents para ambas consultas.
El ejemplo a continuación demuestra este flujo: la primera consulta ejecuta un subagente y captura el ID de sesión e ID del agente, luego la segunda consulta reanuda la sesión para hacer una pregunta de seguimiento que requiere contexto del primer análisis.
Las transcripciones de subagentes persisten independientemente de la conversación principal:
cleanupPeriodDays (por defecto: 30 días).Los subagentes pueden tener acceso restringido a herramientas a través del campo tools:
Este ejemplo crea un agente de análisis de solo lectura que puede examinar código pero no puede modificar archivos o ejecutar comandos.
| Caso de uso | Herramientas | Descripción |
|---|---|---|
| Análisis de solo lectura | Read, Grep, Glob | Puede examinar código pero no modificar o ejecutar |
| Ejecución de pruebas | Bash, Read, Grep | Puede ejecutar comandos y analizar salida |
| Modificación de código | Read, Edit, Write, Grep, Glob | Acceso completo de lectura/escritura sin ejecución de comandos |
| Acceso completo | Todas las herramientas |
Si Claude completa tareas directamente en lugar de delegar a su subagente:
allowedToolsLos agentes definidos en .claude/agents/ se cargan solo al inicio. Si crea un nuevo archivo de agente mientras Claude Code está ejecutándose, reinicie la sesión para cargarlo.
En Windows, los subagentes con prompts muy largos pueden fallar debido a límites de longitud de línea de comandos (8191 caracteres). Mantenga los prompts concisos o use agentes basados en sistema de archivos para instrucciones complejas.
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
async def main():
async for message in query(
prompt="Review the authentication module for security issues",
options=ClaudeAgentOptions(
# Task tool is required for subagent invocation
allowed_tools=["Read", "Grep", "Glob", "Task"],
agents={
"code-reviewer": AgentDefinition(
# description tells Claude when to use this subagent
description="Expert code review specialist. Use for quality, security, and maintainability reviews.",
# prompt defines the subagent's behavior and expertise
prompt="""You are a code review specialist with expertise in security, performance, and best practices.
When reviewing code:
- Identify security vulnerabilities
- Check for performance issues
- Verify adherence to coding standards
- Suggest specific improvements
Be thorough but concise in your feedback.""",
# tools restricts what the subagent can do (read-only here)
tools=["Read", "Grep", "Glob"],
# model overrides the default model for this subagent
model="sonnet"
),
"test-runner": AgentDefinition(
description="Runs and analyzes test suites. Use for test execution and coverage analysis.",
prompt="""You are a test execution specialist. Run tests and provide clear analysis of results.
Focus on:
- Running test commands
- Analyzing test output
- Identifying failing tests
- Suggesting fixes for failures""",
# Bash access lets this subagent run test commands
tools=["Bash", "Read", "Grep"]
)
}
)
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())| Anulación de modelo para este agente. Por defecto es el modelo principal si se omite |
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
# Factory function that returns an AgentDefinition
# This pattern lets you customize agents based on runtime conditions
def create_security_agent(security_level: str) -> AgentDefinition:
is_strict = security_level == "strict"
return AgentDefinition(
description="Security code reviewer",
# Customize the prompt based on strictness level
prompt=f"You are a {'strict' if is_strict else 'balanced'} security reviewer...",
tools=["Read", "Grep", "Glob"],
# Key insight: use a more capable model for high-stakes reviews
model="opus" if is_strict else "sonnet"
)
async def main():
# The agent is created at query time, so each request can use different settings
async for message in query(
prompt="Review this PR for security issues",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob", "Task"],
agents={
# Call the factory with your desired configuration
"security-reviewer": create_security_agent("strict")
}
)
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
async def main():
async for message in query(
prompt="Use the code-reviewer agent to review this codebase",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep", "Task"],
agents={
"code-reviewer": AgentDefinition(
description="Expert code reviewer.",
prompt="Analyze code quality and suggest improvements.",
tools=["Read", "Glob", "Grep"]
)
}
)
):
# Check for subagent invocation in message content
if hasattr(message, 'content') and message.content:
for block in message.content:
if getattr(block, 'type', None) == 'tool_use' and block.name == 'Task':
print(f"Subagent invoked: {block.input.get('subagent_type')}")
# Check if this message is from within a subagent's context
if hasattr(message, 'parent_tool_use_id') and message.parent_tool_use_id:
print(" (running inside subagent)")
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())import { query, type SDKMessage } from '@anthropic-ai/claude-agent-sdk';
// Helper to extract agentId from message content
// Stringify to avoid traversing different block types (TextBlock, ToolResultBlock, etc.)
function extractAgentId(message: SDKMessage): string | undefined {
if (!('message' in message)) return undefined;
// Stringify the content so we can search it without traversing nested blocks
const content = JSON.stringify(message.message.content);
const match = content.match(/agentId:\s*([a-f0-9-]+)/);
return match?.[1];
}
let agentId: string | undefined;
let sessionId: string | undefined;
// First invocation - use the Explore agent to find API endpoints
for await (const message of query({
prompt: "Use the Explore agent to find all API endpoints in this codebase",
options: { allowedTools: ['Read', 'Grep', 'Glob', 'Task'] }
})) {
// Capture session_id from ResultMessage (needed to resume this session)
if ('session_id' in message) sessionId = message.session_id;
// Search message content for the agentId (appears in Task tool results)
const extractedId = extractAgentId(message);
if (extractedId) agentId = extractedId;
// Print the final result
if ('result' in message) console.log(message.result);
}
// Second invocation - resume and ask follow-up
if (agentId && sessionId) {
for await (const message of query({
prompt: `Resume agent ${agentId} and list the top 3 most complex endpoints`,
options: { allowedTools: ['Read', 'Grep', 'Glob', 'Task'], resume: sessionId }
})) {
if ('result' in message) console.log(message.result);
}
}import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
async def main():
async for message in query(
prompt="Analyze the architecture of this codebase",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob", "Task"],
agents={
"code-analyzer": AgentDefinition(
description="Static code analysis and architecture review",
prompt="""You are a code architecture analyst. Analyze code structure,
identify patterns, and suggest improvements without making changes.""",
# Read-only tools: no Edit, Write, or Bash access
tools=["Read", "Grep", "Glob"]
)
}
)
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())Hereda todas las herramientas del padre (omita el campo tools) |