Desarrollo práctico de agentes de IA: diseño de arquitectura e implementación

Un agente ReAct corrió veinte minutos en bucle invocando la misma herramienta: faltaba maxIterations. Trampas: bucles ReAct, multiagente sin convergencia, Plan-and-Execute rígido.
Tres niveles: modelo directo; agente + herramientas; multiagente con cautela. Azure: ≤3 en group chat.
Dos años de lecciones: patrones, orquestación, frameworks y agente con Claude Agent SDK.
1. Tres niveles de arquitectura
Principio clave: si una solución simple basta, no añadas complejidad.
Azure divide la arquitectura en tres niveles; clasificación muy práctica:
1.1 Llamada directa al modelo
Nivel más simple: envías la tarea y obtienes respuesta.
// Invocación básica
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Resume este texto...' }]
});
Escenarios: un paso, determinista, sin herramientas (resumen, traducción, autocompletado).
Ventajas: simple, barato. Desventajas: sin razonamiento multipaso ni herramientas.
1.2 Agente único + herramientas
Opción por defecto empresarial. Invoca herramientas y tareas multipaso.
// Ejemplo LangChain
import { ChatAnthropic } from '@langchain/anthropic';
import { AgentExecutor, createToolCallingAgent } from 'langchain/agents';
import { tool } from '@langchain/core/tools';
import { z } from 'zod';
// Herramienta clima
const weatherTool = tool(
async ({ city }) => {
// Simular API
return `${city} soleado hoy, 22 °C`;
},
{
name: 'get_weather',
description: 'Clima de una ciudad',
schema: z.object({
city: z.string().describe('Ciudad'),
}),
}
);
const model = new ChatAnthropic({
model: 'claude-sonnet-4-20250514',
temperature: 0,
});
const agent = await createToolCallingAgent({
llm: model,
tools: [weatherTool],
prompt: 'Eres un asistente útil.',
});
const executor = AgentExecutor.fromAgentAndTools({
agent,
tools: [weatherTool],
});
// Run
const result = await executor.invoke({
input: '¿Tiempo en Pekín hoy?',
});
Escenarios: herramientas, tareas descomponibles, análisis, APIs.
1.3 Orquestación multiagente
Nivel más complejo: agentes especializados colaboran.
Menos escenarios reales de los que parece; costo de coordinación y depuración exponencial.
Escenarios: tareas transversales, pipelines de desarrollo, decisiones complejas.
1.4 Tabla de decisión
| Escenario | Nivel | Motivo |
|---|---|---|
| Q&A simple | Modelo directo | Sin sobreingeniería |
| BD/API | Agente + tools | Estable |
| Pasos inciertos | ReAct | Auto-planifica |
| Varios roles | Multiagente | Con cautela |
Resumen: empieza simple.
2. Tres patrones de arquitectura
Tras el nivel, elige patrón; a menudo se combinan.
2.1 ReAct
ReAct: razonar mientras actúa.
Flujo:
Entrada → Pensamiento → Acción → Observación → Bucle/fin
Ejemplo: deporte al aire libre mañana en Pekín:
- Pensamiento: consultar clima de mañana en Pekín
- Acción: invocar
get_weatherconcity: "Pekín" - Observación: nublado, 18-25 °C, 10% lluvia
- Pensamiento: temperatura moderada, apto para deporte
- Respuesta: apto; chaqueta ligera
Implementación (LangChain):
import { ChatAnthropic } from '@langchain/anthropic';
import { AgentExecutor, createReactAgent } from 'langchain/agents';
import { pull } from 'langchain/hub';
// Plantilla ReAct
const prompt = await pull('hwchase17/react');
const agent = await createReactAgent({
llm: model,
tools: [weatherTool, searchTool], // Herramientas
prompt,
});
// Limitar iteraciones
const executor = AgentExecutor.fromAgentAndTools({
agent,
tools: [weatherTool, searchTool],
maxIterations: 10, // Evitar bucles
verbose: true, // Log de razonamiento
});
Pros y contras:
| Ventajas | Desventajas |
|---|---|
| Flexible | Riesgo de bucle |
| Transparente | Mayor costo |
| Sin pasos fijos | Planificación limitada |
Aviso: define maxIterations; mi primer ReAct corrió toda la noche.
2.2 Plan-and-Execute
ReAct va paso a paso; Plan-and-Execute planifica primero.
Flujo:
Entrada → Plan → Ejecución → Resultado
Implementación (LangGraph):
import { ChatAnthropic } from '@langchain/anthropic';
import { StateGraph, END } from '@langchain/langgraph';
// Estado
interface AgentState {
input: string;
plan: string[];
pastSteps: string[];
response: string;
}
// Planificación
async function planNode(state: AgentState): Promise<AgentState> {
const plannerPrompt = `Objetivo: ${state.input}
Plan detallado en JSON array.`;
const response = await model.invoke(plannerPrompt);
const plan = JSON.parse(response.content as string);
return { ...state, plan };
}
// Ejecutar paso
async function executeNode(state: AgentState): Promise<AgentState> {
const currentStep = state.plan[0];
const result = await executor.invoke({ input: currentStep });
return {
...state,
plan: state.plan.slice(1), // Quitar paso
pastSteps: [...state.pastSteps, `${currentStep}: ${result.output}`],
};
}
// Grafo
const workflow = new StateGraph<AgentState>({
channels: {
input: { value: null },
plan: { value: null },
pastSteps: { value: null, default: () => [] },
response: { value: null },
},
});
workflow.addNode('planner', planNode);
workflow.addNode('executor', executeNode);
// Tras planificar
workflow.addEdge('planner', 'executor');
// ¿Quedan pasos?
workflow.addConditionalEdges('executor', (state) => {
return state.plan.length > 0 ? 'executor' : END;
});
Pros y contras:
| Ventajas | Desventajas |
|---|---|
| Estable | Plan rígido |
| Determinista | Poco adaptable |
| Monitorizable | Depende del planner |
Experiencia: ideal para pasos previsibles; ReAct si la estrategia cambia.
2.3 Multi-Agent
Cuando un agente no alcanza, multiagente.
Idea: un dominio por agente.
Code Implementation (Claude Agent SDK style):
import { ClaudeAgent } from '@anthropic-ai/claude-agent-sdk';
// Agentes
const researchAgent = new ClaudeAgent({
name: 'researcher',
model: 'claude-sonnet-4-20250514',
systemPrompt: 'Experto en investigación.',
tools: ['WebSearch', 'WebFetch'],
});
const writerAgent = new ClaudeAgent({
name: 'writer',
model: 'claude-sonnet-4-20250514',
systemPrompt: 'Experto en contenido.',
tools: ['Read', 'Write', 'Edit'],
});
const reviewerAgent = new ClaudeAgent({
name: 'reviewer',
model: 'claude-sonnet-4-20250514',
systemPrompt: 'Experto en calidad.',
tools: ['Read'],
});
// Colaboración
async function collaborativeWriting(topic: string) {
// Step 1: Research
const research = await researchAgent.run(`Tema: ${topic}`);
// Step 2: Writing
const draft = await writerAgent.run(
`Redacta con esta investigación:\n${research}`
);
// Step 3: Review
const review = await reviewerAgent.run(
`Revisa y sugiere:\n${draft}`
);
// Step 4: Revision
const final = await writerAgent.run(
`Corrige según revisión:\nOriginal: ${draft}\nComentarios: ${review}`
);
return final;
}
Cuándo usar multiagente:
- Varias especialidades (código, diseño, copy)
- Ventana de contexto insuficiente
- División clara del trabajo
Advertencia: depuración exponencial; no fuerces multiagente si uno basta.
3. Cinco modos de orquestación
Si necesitas multiagente, elige modo de orquestación; Azure resume cinco patrones.
3.1 Sequential
Salida de A es entrada de B, como pipeline.
[Agent A] → [Agent B] → [Agent C] → Resultado
Escenarios: documentos (investigación → borrador → revisión), código.
Code Example:
// Secuencial
async function sequentialPipeline(input: string) {
const step1 = await researchAgent.run(input);
const step2 = await writerAgent.run(step1.output);
const step3 = await editorAgent.run(step2.output);
return step3.output;
}
Nota: acuerda formato de salida por paso.
3.2 Concurrent
Varios agentes en paralelo, luego agregación.
→ [Agent A] →
[Input] → → [Agent B] → → [Agregador] → Resultado
→ [Agent C] →
Escenarios: análisis multiperspectiva, acciones, revisión de código.
Code Example:
// Concurrente
async function concurrentAnalysis(code: string) {
const [security, performance, style] = await Promise.all([
securityAgent.run(`Seguridad:\n${code}`),
performanceAgent.run(`Rendimiento:\n${code}`),
styleAgent.run(`Estilo:\n${code}`),
]);
// Agregar
return {
security: security.output,
performance: performance.output,
style: style.output,
};
}
Nota: define arbitraje ante conflictos.
3.3 Group Chat
Debate hasta consenso o timeout.
[Agent A] ⇄ [Agent B] ⇄ [Agent C]
↑ ↓
[Moderator]
Escenarios: brainstorming, validación, decisiones por discusión.
Azure: máximo 3 agentes.
Code Example:
// Group chat (seudocódigo)
interface ChatMessage {
sender: string;
content: string;
}
async function groupChatDiscussion(
topic: string,
agents: ClaudeAgent[],
maxRounds: number = 5
) {
const history: ChatMessage[] = [];
for (let round = 0; round < maxRounds; round++) {
for (const agent of agents) {
const response = await agent.run(
`Tema: ${topic}\nHistorial: ${JSON.stringify(history)}\nTu punto de vista:`
);
history.push({ sender: agent.name, content: response.output });
// ¿Consenso?
if (checkConsensus(history)) {
return summarizeConsensus(history);
}
}
}
return 'Timeout sin consenso';
}
Trampa: maxRounds y moderador.
3.4 Handoff
Un agente transfiere al siguiente.
[Agent A] necesita B → traslado a [Agent B] → Continue processing
Escenarios: soporte (ventas → técnico → posventa), diagnóstico.
Code Example:
// Handoff
const supportAgent = new ClaudeAgent({
name: 'support',
systemPrompt: `Soporte: técnico → "HANDOFF:tech".
Posventa → "HANDOFF:after_sales".`,
});
const techAgent = new ClaudeAgent({
name: 'tech',
systemPrompt: 'Experto soporte técnico.',
});
async function handleWithHandoff(userInput: string) {
let currentAgent = supportAgent;
let response = await currentAgent.run(userInput);
// Señal HANDOFF
while (response.output.includes('HANDOFF:')) {
const targetAgent = response.output.match(/HANDOFF:(\w+)/)?.[1];
if (targetAgent === 'tech') currentAgent = techAgent;
else if (targetAgent === 'after_sales') currentAgent = afterSalesAgent;
response = await currentAgent.run(userInput);
}
return response.output;
}
Nota: evita traslados circulares.
3.5 Magentic
El planificador elige el agente más adecuado.
[Cola] → [Planificador] → Selección por tarea [Agent A/B/C]
Escenarios: tareas diversas, scheduling dinámico.
Implementation Approach:
// Magentic
interface Task {
type: string;
priority: number;
content: string;
}
async function magenticScheduling(task: Task) {
// Mejor agente
const agentScores = await Promise.all(
agents.map(async (agent) => {
const score = await evaluateAgentFit(agent, task);
return { agent, score };
})
);
// Mayor puntuación
const bestAgent = agentScores.sort((a, b) => b.score - a.score)[0].agent;
return bestAgent.run(task.content);
}
Nota: evalúa ajuste tarea-agente.
3.6 Tabla rápida
| Modo | Escenario | Complejidad | Riesgo |
|---|---|---|---|
| Sequential | Pipeline | Baja | Bloqueos |
| Concurrent | Paralelo | Media | Conflictos |
| Group Chat | Debate | Alta | Sin convergencia |
| Handoff | Dinámico | Media | Ciclo |
| Magentic | Diverso | Alta | Scheduling |
4. Frameworks
Tras patrones, ¿qué framework? LangChain, AutoGen, CrewAI, Claude Agent SDK.
No hay mejor framework, solo el más adecuado.
4.1 Posicionamiento
| Framework | Posición | Fortalezas | Escenarios |
|---|---|---|---|
| LangChain | General | Herramientas, ReAct | Prototipos y producción |
| AutoGen | Multiagente | Conversación, HITL | Sistemas complejos |
| CrewAI | Roles | API limpia | Equipos |
| Claude Agent SDK | Claude nativo | Código, archivos | Ecosistema Claude |
4.2 Detalle
LangChain: ecosistema maduro.
- Soporte completo en TypeScript y Python
- Herramientas e integraciones integradas de forma extensa
- Implementaciones listas de ReAct y Plan-and-Execute
- ¿Contras? La API cambia con frecuencia y la documentación a veces no alcanza a seguir el ritmo
AutoGen: Microsoft, multiagente.
- El concepto central es la “conversación”: los agents colaboran mediante mensajes
- Soporta human-in-the-loop
- Adecuado para escenarios con varias rondas de discusión y decisión
- ¿Contras? Curva de aprendizaje pronunciada; depurar sistemas multiagente es doloroso
CrewAI: simple y directo.
- Modela con conceptos de “roles”, “tareas” y “equipos”, muy intuitivo
- API limpia y arranque rápido
- Ideal para prototipos multiagente en poco tiempo
- ¿Contras? El ecosistema y la integración de herramientas no son tan ricos como en LangChain
Claude Agent SDK: oficial Anthropic 2026.
- Integración profunda con modelos Claude
- Lectura/escritura de archivos, edición de código y ejecución de comandos integradas
- Soporta
permissionModepara controlar permisos de operación - Si tu modelo principal es Claude, esta es la primera opción
4.3 Guía de selección
Pregúntate:
-
¿Cuál es tu modelo principal?
- Claude → Prioriza Claude Agent SDK
- OpenAI → El ecosistema LangChain es más maduro
- Multi-modelo → LangChain o AutoGen
-
¿Qué tan compleja es la tarea?
- Un agent + herramientas → LangChain basta
- Colaboración multiagente → AutoGen o CrewAI
- Tareas de código → Claude Agent SDK
-
¿Cuál es el stack de tu equipo?
- Principalmente Python → Todos los frameworks están soportados
- Principalmente TypeScript → LangChain y Claude Agent SDK tienen mejor soporte
-
¿Necesitas colaboración humano-máquina?
- Sí → El human-in-the-loop de AutoGen está bien diseñado
- No → Cualquier otro framework funciona
4.4 Recomendación
En la mayoría de escenarios, LangChain basta. Su integración de herramientas y la implementación de ReAct son maduras, con buen soporte de la comunidad.
Si estás seguro de que necesitas multiagente y la tarea es lo bastante compleja como para requerir varios agents especializados, AutoGen merece la pena. Pero recuerda: depurar multiagente cuesta caro; no lo uses solo por “avance técnico”.
Si eres usuario intensivo de Claude, Claude Agent SDK es hoy la mejor opción: es oficial y encaja mejor con los modelos Claude.
5. Práctica con Claude Agent SDK
Dicho esto, vamos a la práctica: usa Claude Agent SDK para escribir un agent de refactorización de código que funcione de verdad.
5.1 Entorno
# Instalar
npm install @anthropic-ai/claude-agent-sdk
# API Key
export ANTHROPIC_API_KEY=your_api_key_here
5.2 Básico
import { ClaudeAgent } from '@anthropic-ai/claude-agent-sdk';
// Agente refactor
const refactorAgent = new ClaudeAgent({
model: 'claude-sonnet-4-20250514',
tools: ['Read', 'Write', 'Edit', 'Bash'],
permissionMode: 'acceptEdits', // Aceptar ediciones
workingDirectory: './src', // Directorio
});
// Ejecutar
async function refactorCode(task: string) {
const result = await refactorAgent.run(task);
console.log('Resultado:', result);
return result;
}
// Ejemplo de uso
refactorCode('Refactorizar auth.ts a async/await');
5.3 Configuración
permissionMode:
'acceptEdits': Acepta automáticamente operaciones de edición de archivos'interactive': Cada operación requiere confirmación manual'planOnly': Solo genera el plan, no ejecuta
tools:
Read: Leer archivosWrite: Crear archivos nuevosEdit: Editar archivos existentesBash: Ejecutar comandos de terminalGlob: Coincidencia de patrones de archivosGrep: Búsqueda de contenido
5.4 Con restricciones
const cautiousAgent = new ClaudeAgent({
model: 'claude-sonnet-4-20250514',
tools: ['Read', 'Write', 'Edit', 'Bash'],
permissionMode: 'interactive', // Cauteloso
maxIterations: 20, // Límite
timeout: 300000, // 5 min
// systemPrompt límites
systemPrompt: `Experto en refactorización.
Reglas:
1. No borrar tests
2. No tocar package.json
3. Backup antes de editar
4. Tests tras cambios`,
});
async function safeRefactor(filePath: string) {
try {
const result = await cautiousAgent.run(
`Refactoriza ${filePath}, optimiza estructura y legibilidad.`
);
return result;
} catch (error) {
console.error('Falló:', error);
// Lógica de rollback...
}
}
5.5 Buenas prácticas
- Iteraciones: evitar bucles infinitos
- Timeout: tareas largas con límite de tiempo
- Permisos: modo
interactivepara operaciones sensibles - Backup: respaldar archivos importantes antes de editar
- Tests: ejecutar pruebas tras los cambios
5.6 Depuración
// Log detallado
const debugAgent = new ClaudeAgent({
model: 'claude-sonnet-4-20250514',
tools: ['Read', 'Write', 'Edit'],
verbose: true, // Proceso
});
// Eventos
debugAgent.on('toolCall', (tool, args) => {
console.log(`Herramienta: ${tool}, parámetros: ${JSON.stringify(args)}`);
});
debugAgent.on('thinking', (thought) => {
console.log(`Pensamiento: ${thought}`);
});
Cierre
Tras todo esto, la idea central al elegir arquitectura de agent se resume en una frase: Empieza simple, añade lo necesario.
Complejidad:
- Un paso → modelo
- Herramientas → agente
- Varios roles → multiagente
Patrón:
- Dinámico → ReAct
- Previsible → Plan-and-Execute
- Especialización → Multi-Agent
Framework:
- Claude → SDK
- Multi-modelo → LangChain
- Multiagente → AutoGen/CrewAI
Practica en un proyecto pequeño; los fallos enseñan.
Artículos relacionados: MCP Server e invocación de herramientas — trilogía coherente.
Construir agente con Claude Agent SDK
Del entorno al primer agente
⏱️ Estimated time: 30 min
- 1
Step 1: Instalar dependencias
Ejecuta los comandos:
```bash
npm install @anthropic-ai/claude-agent-sdk
export ANTHROPIC_API_KEY=your_api_key_here
```
API Key desde Anthropic; usar variables de entorno. - 2
Step 2: Crear instancia básica
Tres parámetros al crear el agente:
```typescript
const agent = new ClaudeAgent({
model: 'claude-sonnet-4-20250514',
tools: ['Read', 'Write', 'Edit', 'Bash'],
permissionMode: 'acceptEdits'
});
```
• model: versión Claude
• tools: herramientas
• permissionMode: permisos - 3
Step 3: Ejecutar tarea
Invoca run:
```typescript
const result = await agent.run('Refactorizar auth.ts');
```
Añade errores y logs. - 4
Step 4: Protecciones
En producción:
• maxIterations: ~20
• timeout: ~5 min
• systemPrompt: límites
• permissionMode: 'interactive' en sensibles
FAQ
¿ReAct, Plan-and-Execute o Multi-Agent?
¿Por qué Azure limita group chat a 3?
¿LangChain o AutoGen/CrewAI?
¿Claude Agent SDK?
¿Evitar bucles infinitos?
10 min de lectura · Publicado el: 21 mar 2026 · Actualizado el: 21 ago 2026
Guía de ingeniería de AI Agents
Si llegaste desde búsqueda, lo más rápido es ir al artículo anterior o siguiente de esta misma serie.
Anterior
Guía de Agent Sandbox: solución completa para ejecutar código de IA con seguridad
Guía para construir entornos sandbox de AI Agent: comparativa gVisor vs Firecracker y despliegue desde desarrollo local hasta clústeres Kubernetes
Parte 1 de 16
Siguiente
Diseño de sistemas de memoria para agentes: de la sesión a la memoria a largo plazo
Construye un sistema de memoria para agentes desde cero: cuatro tipos de memoria, pipeline en cinco fases, comparación Mem0/Zep/LangMem y estrategias de optimización de costos en producción
Parte 3 de 16



Comentarios
Inicia sesión con GitHub para dejar un comentario