El Problema Real que Nadie Menciona
Cuando empecé a construir agentes con claude-agent-sdk, cometí el error que cometen todos: tiré todo el contexto posible al agente y esperé que Claude "lo entendiera".
Resultado: agentes lentos, costosos (en tokens), y que tomaban decisiones erráticas.
El problema no era Claude. Era que estaba alimentando al agente como si fuera un basural de información. Sin estructura. Sin propósito.
Luego lo entendí: la arquitectura de tus archivos y cómo los cargas es lo que determina si tu agente es inteligente o simplemente ruidoso.
Context Engineering: Más Que Prompt Engineering
Prompt engineering es lo que todos hacen. Context engineering es lo que funciona.
La diferencia:
- **Prompt engineering**: "Dale al agente las instrucciones correctas"
- **Context engineering**: "Dale al agente SOLO la información que necesita, en el momento exacto que la necesita"
Esto cambia todo.
En mi proyecto actual con claude-agent-sdk, estructuré los archivos así:
``` project/ ├── agents/ │ ├── analyzer.ts │ ├── decision-maker.ts │ └── executor.ts ├── context/ │ ├── rules/ │ │ ├── validation.txt │ │ ├── constraints.txt │ │ └── patterns.txt │ ├── data/ │ │ ├── user-profiles.json │ │ ├── historical-decisions.log │ │ └── edge-cases.md │ └── schemas/ │ ├── input.schema.json │ └── output.schema.json └── loaders/ ├── context-loader.ts └── selective-loader.ts ```
Pero la estructura no es suficiente. Cómo cargas esa información es lo que importa.
Bash Commands: Tu Filtro de Contexto
Aquí es donde la mayoría falla. Cargan archivos completos cuando deberían cargar fragmentos específicos.
Usando `grep` y `tail`, puedes ser quirúrgico:
Ejemplo 1: Cargar Solo Reglas Relevantes
```bash
En lugar de cargar todo validation.txt
grep -A 3 "payment_validation" context/rules/validation.txt ```
Esto te da solo las reglas de validación de pagos, no las 200 líneas del archivo completo.
Ejemplo 2: Últimas Decisiones Relevantes
```bash
Cargar solo las últimas 5 decisiones similares
tail -20 context/data/historical-decisions.log | grep "similar_case_type" ```
En tu agente con claude-agent-sdk, esto se vería así:
```typescript import { Anthropic } from "@anthropic-ai/sdk"; import { execSync } from "child_process";
const client = new Anthropic();
async function loadRelevantContext(caseType: string) { // Cargar solo reglas relevantes const rules = execSync( `grep -A 5 "${caseType}" context/rules/validation.txt` ).toString();
// Cargar decisiones históricas similares const history = execSync( `grep "${caseType}" context/data/historical-decisions.log | tail -3` ).toString();
return { rules, history }; }
async function runAgent(userInput: string, caseType: string) { const context = await loadRelevantContext(caseType);
const response = await client.messages.create({ model: "claude-3-5-sonnet-20241022", max_tokens: 1024, system: `You are a decision-making agent. Use ONLY this context:
Relevant Rules: ${context.rules}
Historical Decisions: ${context.history}
Make decisions based on these patterns. Be concise.`, messages: [ { role: "user", content: userInput, }, ], });
return response; } ```
Ejemplo 3: Cargar Esquemas Dinámicamente
```bash
Obtener solo los campos requeridos de un esquema
jq '.properties | keys' context/schemas/input.schema.json ```
Combinado con claude-agent-sdk:
```typescript async function validateInput(input: any, schemaType: string) { const requiredFields = execSync( `jq '.properties | keys' context/schemas/${schemaType}.schema.json` ).toString();
const response = await client.messages.create({ model: "claude-3-5-sonnet-20241022", max_tokens: 512, system: `Validate this input against required fields: ${requiredFields}`, messages: [ { role: "user", content: `Input to validate: ${JSON.stringify(input)}`, }, ], });
return response; } ```
Por Qué Esto Funciona
1. Menos tokens = Más rápido: No cargas contexto innecesario 2. Decisiones mejores: El agente se enfoca en lo relevante, no en ruido 3. Escalable: Añades más archivos sin que el agente se ralentice 4. Mantenible: Cambias reglas sin tocar el código del agente
El Pattern que Uso
En cada proyecto que construyo con claude-agent-sdk sigo este patrón:
```typescript class SelectiveContextLoader { private basePath: string;
constructor(basePath: string = "context") { this.basePath = basePath; }
loadByPattern(filePath: string, pattern: string): string { return execSync( `grep -i "${pattern}" ${this.basePath}/${filePath} | head -10` ).toString(); }
loadRecent(filePath: string, lines: number = 5): string { return execSync( `tail -${lines} ${this.basePath}/${filePath}` ).toString(); }
loadSchema(schemaName: string): object { const content = execSync( `cat ${this.basePath}/schemas/${schemaName}.schema.json` ).toString(); return JSON.parse(content); } }
// Uso const loader = new SelectiveContextLoader(); const paymentRules = loader.loadByPattern( "rules/validation.txt", "payment" ); const recentDecisions = loader.loadRecent( "data/historical-decisions.log", 3 ); ```
Lo Que Aprendí (y Tú También Deberías)
Trabajando con claude-agent-sdk durante varios meses, descubrí que:
- **La estructura importa más que el contenido**: Un archivo bien organizado es 10x mejor que contenido perfecto pero desordenado
- **Los agentes son perezosos**: Si pueden ignorar contexto, lo harán. Fuerza la relevancia
- **Bash es tu amigo**: Grep y tail te permiten hacer cosas que muchos developers no consideran
- **El contexto es dinámico**: Lo que necesita el agente hoy es diferente a mañana
Takeaway
No se trata de tener mejor contexto. Se trata de tener el contexto correcto.
La próxima vez que construyas un agente con claude-agent-sdk, antes de escribir el prompt, pregúntate:
- ¿Cuál es la información mínima que necesita?
- ¿Cómo puedo cargarla dinámicamente?
- ¿Qué puedo filtrar con bash?
Haz eso y verás la diferencia inmediatamente.
---
¿Cómo estructuras tu contexto en tus agentes? Comparte en los comentarios.