Cómo Crear Tu Propio Código Claude

Ashley Innocent

Ashley Innocent

2 April 2026

Cómo Crear Tu Propio Código Claude

Apidog para empresas

Despliegue local

SSO & RBAC

Conforme con SOC 2

Explorar Apidog Enterprise

En resumen

La fuga del código fuente de Claude expuso una base de código TypeScript de 512,000 líneas el 31 de marzo de 2026. La arquitectura se reduce a un bucle `while` que llama a la API de Claude, despacha las llamadas a herramientas y devuelve los resultados. Puedes construir tu propia versión con Python, el SDK de Anthropic y unas 200 líneas de código para el bucle principal. Esta guía desglosa cada componente y te muestra cómo recrearlos.

Introducción

El 31 de marzo de 2026, Anthropic lanzó un archivo de mapa de origen de 59.8 MB dentro de la versión 2.1.88 de su paquete npm `@anthropic-ai/claude-code`. Los mapas de origen son artefactos de depuración que revierten el JavaScript minificado a su código fuente original. Dado que la herramienta de compilación de Anthropic (el empaquetador de Bun) los genera por defecto, toda la base de código TypeScript fue recuperable.

En cuestión de horas, los desarrolladores habían replicado el código en docenas de repositorios de GitHub. La comunidad diseccionó rápidamente cada módulo, desde el bucle principal del agente hasta características ocultas como el “modo encubierto” y la inyección de herramientas falsas.

La reacción fue dividida. Algunos criticaron las prácticas de seguridad de Anthropic. Otros quedaron fascinados por la arquitectura. Pero la respuesta más productiva provino de desarrolladores que preguntaron: “¿Puedo construir esto yo mismo?”

La respuesta es sí. Los patrones centrales son sencillos. Esta guía recorre cada capa arquitectónica, explica por qué Anthropic tomó las decisiones que tomó y proporciona código funcional que puedes usar como punto de partida. También aprenderás cómo probar las interacciones de la API de tu agente personalizado con Apidog, lo que facilita mucho la depuración de conversaciones de API de múltiples turnos que los comandos curl sin procesar.

botón

Lo que la fuga reveló sobre la arquitectura de Claude Code

La base de código de un vistazo

Claude Code, con nombre en clave interno “Tengu”, abarca alrededor de 1,900 archivos. La organización de módulos se divide en capas claras:

cli/          - Interfaz de usuario de terminal (React + Ink)
tools/        - Más de 40 implementaciones de herramientas
core/         - Prompts del sistema, permisos, constantes
assistant/    - Orquestación del agente
services/     - Llamadas API, compactación, OAuth, telemetría

La propia CLI es una aplicación React renderizada a través de Ink, un renderizador de React para la salida de la terminal. Utiliza Yoga (un motor flexbox CSS) para el diseño y códigos de escape ANSI para el estilo. Cada vista de conversación, área de entrada, visualización de llamada a herramienta y diálogo de permisos es un componente de React.

Esto está sobredimensionado para la mayoría de los proyectos de bricolaje. No necesitas una interfaz de usuario de terminal basada en React para construir un agente de codificación funcional. Un simple bucle REPL funciona bien.

El bucle principal del agente

Si eliminas la interfaz de usuario, la telemetría y las banderas de características, el núcleo de Claude Code es un bucle `while`. Anthropic lo llama internamente “nO”. Esto es lo que hace:

  1. Enviar mensajes a la API de Claude (prompt del sistema + definiciones de herramientas)
  2. Recibir una respuesta que contenga texto y/o bloques `tool_use`
  3. Ejecutar cada herramienta solicitada a través de un mapa de despacho de nombre a manejador
  4. Añadir los resultados de las herramientas de nuevo a la lista de mensajes
  5. Si la respuesta contiene más llamadas a herramientas, volver al paso 1
  6. Si la respuesta es texto plano sin llamadas a herramientas, devolverlo al usuario

Un “turno” es un ciclo completo de ida y vuelta. Los turnos continúan hasta que Claude produce texto sin invocaciones de herramientas. Ese es el patrón completo del agente.

Aquí hay una versión mínima en Python que captura el núcleo:

import anthropic

client = anthropic.Anthropic()
MODEL = "claude-sonnet-4-6"

def agent_loop(system_prompt: str, tools: list, messages: list) -> str:
    """El bucle principal del agente: seguir llamando hasta que no haya más uso de herramientas."""
    while True:
        response = client.messages.create(
            model=MODEL,
            max_tokens=16384,
            system=system_prompt,
            tools=tools,
            messages=messages,
        )

        # Añadir respuesta del asistente a la conversación
        messages.append({"role": "assistant", "content": response.content})

        # Si el modelo se detuvo sin solicitar herramientas, hemos terminado
        if response.stop_reason != "tool_use":
            # Extraer el texto final
            return "".join(
                block.text for block in response.content
                if hasattr(block, "text")
            )

        # Ejecutar cada llamada a herramienta y recolectar resultados
        tool_results = []
        for block in response.content:
            if block.type == "tool_use":
                result = execute_tool(block.name, block.input)
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": result,
                })

        # Devolver los resultados como un mensaje de usuario
        messages.append({"role": "user", "content": tool_results})

Eso son unas 30 líneas. El resto de la complejidad de Claude Code proviene de las propias herramientas, el sistema de permisos, la gestión del contexto y la memoria.

Construyendo el sistema de herramientas

Por qué las herramientas dedicadas superan a un solo comando bash

Una de las decisiones arquitectónicas más claras en la fuga: Claude Code utiliza herramientas dedicadas para operaciones de archivos en lugar de enrutar todo a través de bash.

Hay una herramienta `Read` (no `cat`), una herramienta `Edit` (no `sed`), una herramienta `Grep` (no `grep`) y una herramienta `Glob` (no `find`). El prompt del sistema le dice explícitamente al modelo que prefiera estas en lugar de sus equivalentes de bash.

¿Por qué? Tres razones:

El conjunto de herramientas esenciales

De la fuga, Claude Code expone menos de 20 herramientas por defecto, con más de 60 detrás de banderas de características. Para un agente DIY, necesitas cinco:

TOOLS = [
    {
        "name": "read_file",
        "description": "Lee un archivo del sistema de archivos. Devuelve el contenido con números de línea.",
        "input_schema": {
            "type": "object",
            "properties": {
                "file_path": {
                    "type": "string",
                    "description": "Ruta absoluta al archivo"
                },
                "offset": {
                    "type": "integer",
                    "description": "Número de línea desde donde empezar a leer (base 0)"
                },
                "limit": {
                    "type": "integer",
                    "description": "Número máximo de líneas a leer. Por defecto 2000."
                }
            },
            "required": ["file_path"]
        }
    },
    {
        "name": "write_file",
        "description": "Escribe contenido en un archivo. Crea el archivo si no existe.",
        "input_schema": {
            "type": "object",
            "properties": {
                "file_path": {"type": "string", "description": "Ruta absoluta"},
                "content": {"type": "string", "description": "Contenido del archivo a escribir"}
            },
            "required": ["file_path", "content"]
        }
    },
    {
        "name": "edit_file",
        "description": "Reemplaza una cadena específica en un archivo. La cadena antigua debe ser única.",
        "input_schema": {
            "type": "object",
            "properties": {
                "file_path": {"type": "string", "description": "Ruta absoluta"},
                "old_string": {"type": "string", "description": "Texto a buscar"},
                "new_string": {"type": "string", "description": "Texto de reemplazo"}
            },
            "required": ["file_path", "old_string", "new_string"]
        }
    },
    {
        "name": "run_command",
        "description": "Ejecuta un comando de shell y devuelve stdout/stderr.",
        "input_schema": {
            "type": "object",
            "properties": {
                "command": {"type": "string", "description": "Comando de shell a ejecutar"},
                "timeout": {"type": "integer", "description": "Tiempo de espera en segundos. Por defecto 120."}
            },
            "required": ["command"]
        }
    },
    {
        "name": "search_code",
        "description": "Busca un patrón regex en archivos dentro de un directorio.",
        "input_schema": {
            "type": "object",
            "properties": {
                "pattern": {"type": "string", "description": "Patrón Regex"},
                "path": {"type": "string", "description": "Directorio donde buscar"},
                "file_glob": {"type": "string", "description": "Filtro de patrón de archivo, ej. '*.py'"}
            },
            "required": ["pattern"]
        }
    }
]

Despacho de manejadores de herramientas

La función de ejecución de herramientas mapea los nombres de las herramientas a las funciones manejadoras:

import subprocess
import os
import re

def execute_tool(name: str, params: dict) -> str:
    """Despacha las llamadas a herramientas a sus manejadores."""
    handlers = {
        "read_file": handle_read_file,
        "write_file": handle_write_file,
        "edit_file": handle_edit_file,
        "run_command": handle_run_command,
        "search_code": handle_search_code,
    }

    handler = handlers.get(name)
    if not handler:
        return f"Error: Herramienta desconocida '{name}'"

    try:
        return handler(params)
    except Exception as e:
        return f"Error: {str(e)}"


def handle_read_file(params: dict) -> str:
    path = params["file_path"]
    offset = params.get("offset", 0)
    limit = params.get("limit", 2000)

    with open(path, "r") as f:
        lines = f.readlines()

    selected = lines[offset:offset + limit]
    numbered = [f"{i + offset + 1}\t{line}" for i, line in enumerate(selected)]
    return "".join(numbered)


def handle_write_file(params: dict) -> str:
    path = params["file_path"]
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, "w") as f:
        f.write(params["content"])
    return f"Escrito correctamente en {path}"


def handle_edit_file(params: dict) -> str:
    path = params["file_path"]
    with open(path, "r") as f:
        content = f.read()

    old = params["old_string"]
    if content.count(old) == 0:
        return f"Error: '{old[:50]}...' no encontrado en {path}"
    if content.count(old) > 1:
        return f"Error: '{old[:50]}...' coincide con {content.count(old)} ubicaciones. Sea más específico."

    new_content = content.replace(old, params["new_string"], 1)
    with open(path, "w") as f:
        f.write(new_content)
    return f"Editado correctamente {path}"


def handle_run_command(params: dict) -> str:
    cmd = params["command"]
    timeout = params.get("timeout", 120)

    # Seguridad básica: bloquear patrones peligrosos
    blocked = ["rm -rf /", "mkfs", "> /dev/"]
    for pattern in blocked:
        if pattern in cmd:
            return f"Error: Patrón de comando peligroso bloqueado: {pattern}"

    result = subprocess.run(
        cmd, shell=True, capture_output=True, text=True,
        timeout=timeout, cwd=os.getcwd()
    )

    output = ""
    if result.stdout:
        output += result.stdout
    if result.stderr:
        output += f"\nSTDERR:\n{result.stderr}"
    if not output.strip():
        output = f"Comando completado con código de salida {result.returncode}"

    # Truncar grandes salidas para ahorrar tokens de contexto
    if len(output) > 30000:
        output = output[:15000] + "\n\n... [truncado] ...\n\n" + output[-15000:]

    return output


def handle_search_code(params: dict) -> str:
    pattern = params["pattern"]
    path = params.get("path", os.getcwd())
    file_glob = params.get("file_glob", "")

    cmd = ["grep", "-rn", "--include", file_glob, pattern, path] if file_glob else \
          ["grep", "-rn", pattern, path]

    result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)

    if not result.stdout.strip():
        return f"No se encontraron coincidencias para el patrón: {pattern}"

    lines = result.stdout.strip().split("\n")
    if len(lines) > 50:
        return "\n".join(lines[:50]) + f"\n\n... ({len(lines) - 50} coincidencias más)"
    return result.stdout

Gestión del contexto: el problema difícil

Por qué el contexto importa más que la ingeniería de prompts

El código fuente filtrado revela que Claude Code dedica más esfuerzo de ingeniería a la gestión del contexto que al propio prompt del sistema. El compresor de contexto (llamado internamente “wU2”) tiene cinco estrategias.

Para una construcción DIY, necesitas dos:

La autocompactación se activa cuando la conversación se acerca al límite de la ventana de contexto. Claude Code se activa aproximadamente al 92% de uso, reservando un búfer de 13,000 tokens para el propio resumen.

La reinyección de CLAUDE.md asegura que las directrices del proyecto no se desvíen durante sesiones largas. Claude Code reinjecta la configuración del proyecto en cada turno, no en la inicialización. Este es el patrón más impactante para mantener un agente de codificación en el camino correcto.

Construyendo un compresor simple

def maybe_compact(messages: list, system_prompt: str, max_tokens: int = 180000) -> list:
    """Compacta la conversación cuando se alarga demasiado."""
    # Estimación aproximada: 4 caracteres por token
    total_chars = sum(
        len(str(m.get("content", ""))) for m in messages
    )
    estimated_tokens = total_chars // 4

    if estimated_tokens < max_tokens * 0.85:
        return messages  # Aún no ha llegado al límite

    # Pedir al modelo que resuma la conversación hasta ahora
    summary_response = client.messages.create(
        model=MODEL,
        max_tokens=4096,
        system="Resume esta conversación. Mantén todas las rutas de archivo, decisiones tomadas, errores encontrados y el estado actual de la tarea. Sé específico sobre qué se cambió y por qué.",
        messages=messages,
    )

    summary_text = summary_response.content[0].text

    # Reemplazar conversación con resumen + mensajes recientes
    compacted = [
        {"role": "user", "content": f"[Resumen de la conversación]\n{summary_text}"},
        {"role": "assistant", "content": "Tengo el contexto de nuestra conversación anterior. ¿En qué debería trabajar ahora?"},
    ]

    # Mantener los últimos 4 mensajes para contexto inmediato
    compacted.extend(messages[-4:])

    return compacted

Reinyectando el contexto del proyecto

Claude Code lee `.claude/CLAUDE.md` y lo inyecta en cada turno. Así es como se replica:

def build_system_prompt(project_dir: str) -> str:
    """Construye un prompt del sistema con reinyección del contexto del proyecto."""
    base_prompt = """Eres un asistente de codificación que ayuda con tareas de ingeniería de software.
Tienes acceso a herramientas para leer, escribir, editar archivos, ejecutar comandos y buscar código.
Siempre lee los archivos antes de modificarlos. Prefiere edit_file sobre write_file para archivos existentes.
Mantén las respuestas concisas. Céntrate en el código, no en las explicaciones."""

    # Buscar directrices del proyecto
    claude_md_path = os.path.join(project_dir, ".claude", "CLAUDE.md")
    if os.path.exists(claude_md_path):
        with open(claude_md_path, "r") as f:
            project_context = f.read()
        base_prompt += f"\n\n# Directrices del proyecto\n{project_context}"

    # También buscar un CLAUDE.md raíz
    root_md = os.path.join(project_dir, "CLAUDE.md")
    if os.path.exists(root_md):
        with open(root_md, "r") as f:
            root_context = f.read()
        base_prompt += f"\n\n# Directrices del repositorio\n{root_context}"

    return base_prompt

El sistema de memoria de tres capas

El código fuente filtrado muestra que Claude Code utiliza una arquitectura de memoria de tres niveles. Esta es una de las partes más subestimadas del sistema.

Capa 1: MEMORY.md (siempre cargado)

Un índice ligero que permanece en el prompt del sistema en todo momento. Cada entrada es una línea, de menos de 150 caracteres. Actúa como una tabla de contenido que apunta a un conocimiento más profundo. Limitado a 200 líneas / 25KB.

- [Preferencias de usuario](memory/user-prefs.md) - prefiere TypeScript, usa atajos de teclado de Vim
- [Convenciones de API](memory/api-conventions.md) - REST con especificación JSON:API, snake_case
- [Proceso de despliegue](memory/deploy.md) - usa Acciones de GitHub, despliega en AWS EKS

Capa 2: archivos de tema (cargados bajo demanda)

Archivos de conocimiento detallados cargados cuando el índice sugiere relevancia. Estos contienen convenciones del proyecto, decisiones arquitectónicas y patrones aprendidos.

Capa 3: transcripciones de sesión (buscadas, nunca leídas)

Registros completos de sesión que nunca se cargan por completo. El agente los busca con `grep` para identificadores específicos. Esto evita la sobrecarga del contexto mientras se mantiene la capacidad de búsqueda.

Construyendo un sistema de memoria mínimo

import json

MEMORY_DIR = ".agent/memory"

def load_memory_index() -> str:
    """Carga el índice de memoria para la inyección del prompt del sistema."""
    index_path = os.path.join(MEMORY_DIR, "MEMORY.md")
    if os.path.exists(index_path):
        with open(index_path, "r") as f:
            return f.read()
    return ""


def save_memory(key: str, content: str, description: str):
    """Guarda una entrada de memoria y actualiza el índice."""
    os.makedirs(MEMORY_DIR, exist_ok=True)

    # Escribir el archivo de memoria
    filename = f"{key.replace(' ', '-').lower()}.md"
    filepath = os.path.join(MEMORY_DIR, filename)
    with open(filepath, "w") as f:
        f.write(f"---\nname: {key}\ndescription: {description}\n---\n\n{content}")

    # Actualizar el índice
    index_path = os.path.join(MEMORY_DIR, "MEMORY.md")
    index_lines = []
    if os.path.exists(index_path):
        with open(index_path, "r") as f:
            index_lines = f.readlines()

    # Añadir o actualizar entrada
    new_entry = f"- [{key}]({filename}) - {description}\n"
    updated = False
    for i, line in enumerate(index_lines):
        if filename in line:
            index_lines[i] = new_entry
            updated = True
            break
    if not updated:
        index_lines.append(new_entry)

    with open(index_path, "w") as f:
        f.writelines(index_lines)

Añade una herramienta `save_memory` a tu lista de herramientas para que el agente pueda persistir el conocimiento entre sesiones.

Añadiendo un sistema de permisos

La fuga revela cinco modos de permiso: `default` (prompts interactivos), `auto` (aprobación basada en ML), `bypass`, `yolo` (aprobar todo) y `deny`. Cada acción de herramienta se clasifica como de riesgo BAJO, MEDIO o ALTO.

Para un agente DIY, un sistema simple de tres niveles funciona:

# Niveles de riesgo para operaciones
RISK_LEVELS = {
    "read_file": "bajo",
    "search_code": "bajo",
    "edit_file": "medio",
    "write_file": "medio",
    "run_command": "alto",
}

def check_permission(tool_name: str, params: dict, auto_approve_low: bool = True) -> bool:
    """Verifica si el usuario aprueba esta llamada a herramienta."""
    risk = RISK_LEVELS.get(tool_name, "alto")

    if risk == "bajo" and auto_approve_low:
        return True

    # Mostrar al usuario lo que está a punto de suceder
    print(f"\n--- Verificación de permisos ({risk.upper()} riesgo) ---")
    print(f"Herramienta: {tool_name}")
    for key, value in params.items():
        display = str(value)[:200]
        print(f"  {key}: {display}")

    response = input("¿Permitir? [s/n/siempre]: ").strip().lower()
    if response == "siempre":
        RISK_LEVELS[tool_name] = "bajo"  # Aprobar automáticamente esta herramienta en el futuro
        return True
    return response == "s"

Probando las llamadas API de tu agente con Apidog

Construir un agente de codificación significa realizar cientos de llamadas API a Claude. Depurar estas interacciones, especialmente conversaciones de múltiples turnos con uso de herramientas, es doloroso con registros en bruto.

Apidog en acción, mostrando solicitudes API y respuestas

Apidog te ayuda a inspeccionar y probar las solicitudes API exactas que envía tu agente. Así es como se usa durante el desarrollo:

Capturar y reproducir solicitudes API

Configura Apidog como un proxy para interceptar las llamadas de tu agente a la API de Anthropic:

  1. Abre Apidog y crea un nuevo proyecto para tu agente
  2. Importa el endpoint de la API de Mensajes de Anthropic: `POST https://api.anthropic.com/v1/messages`
  3. Configura el cuerpo de la solicitud con tu prompt del sistema, array de herramientas y mensajes
  4. Prueba turnos individuales reproduciendo solicitudes capturadas con parámetros modificados

Esto te permite aislar turnos específicos de uso de herramientas sin ejecutar el bucle completo del agente. Cuando el modelo devuelve una llamada a herramienta inesperada o un parámetro alucinado, puedes modificar el cuerpo de la solicitud en el editor visual de Apidog y reenviarla para ver cómo diferentes entradas cambian la respuesta.

Depurar conversaciones de múltiples turnos

La parte más difícil de la depuración de agentes es reproducir el estado de una conversación. Las variables de entorno de Apidog te permiten guardar instantáneas de conversaciones:

Validar esquemas de herramientas

Tus definiciones de herramientas (los esquemas JSON que pasas a la API) determinan lo que el modelo puede solicitar. Los esquemas mal formados causan fallos silenciosos donde el modelo omite una herramienta o pasa parámetros incorrectos.

Importa tus esquemas de herramientas en Apidog y usa su validador de esquemas JSON para detectar problemas antes de que lleguen a la API. Descarga Apidog para empezar a depurar las interacciones de la API de tu agente.

botón

Poniéndolo todo junto: el REPL completo

Aquí tienes el agente completo unido como un REPL funcional:

#!/usr/bin/env python3
"""Un agente de codificación minimalista al estilo de Claude Code."""

import anthropic
import os
import sys

client = anthropic.Anthropic()
MODEL = "claude-sonnet-4-6"
PROJECT_DIR = os.getcwd()


def main():
    system_prompt = build_system_prompt(PROJECT_DIR)
    memory = load_memory_index()
    if memory:
        system_prompt += f"\n\n# Memoria\n{memory}"

    messages = []
    print("Agente de codificación listo. Escribe 'quit' para salir.\n")

    while True:
        user_input = input("> ").strip()
        if user_input.lower() in ("quit", "exit"):
            break
        if not user_input:
            continue

        messages.append({"role": "user", "content": user_input})

        # Compactar si es necesario
        messages = maybe_compact(messages, system_prompt)

        # Reinjectar contexto del proyecto (Claude Code lo hace en cada turno)
        current_system = build_system_prompt(PROJECT_DIR)
        memory = load_memory_index()
        if memory:
            current_system += f"\n\n# Memoria\n{memory}"

        # Ejecutar el bucle del agente
        result = agent_loop(current_system, TOOLS, messages)
        print(f"\n{result}\n")


if __name__ == "__main__":
    main()

Esto te proporciona un agente de codificación funcional en menos de 300 líneas de Python. Lee archivos, edita código, ejecuta comandos, busca en bases de código, gestiona el contexto y persiste la memoria entre sesiones.

Qué añadir a continuación

El código fuente filtrado revela varias características que vale la pena construir una vez que tu bucle principal funcione:

Sub-agentes para trabajo paralelo

Claude Code genera sub-agentes (llamados agentes “bifurcados”) para tareas independientes. El sub-agente obtiene una copia del contexto padre, ejecuta su tarea y devuelve un resultado. Esto evita contaminar la conversación principal con trabajo exploratorio.

El patrón: generar un nuevo `agent_loop()` con una descripción de tarea enfocada y un subconjunto de herramientas. Devolver el resultado como una cadena.

Deduplicación de lectura de archivos

Claude Code rastrea qué archivos se leyeron y sus tiempos de modificación. Si un archivo no ha cambiado desde la última lectura, omite la lectura y le dice al modelo “archivo sin cambios desde la última lectura”. Esto ahorra tokens en re-lecturas durante sesiones largas.

Truncamiento y muestreo de salida

Cuando una herramienta devuelve una salida masiva (por ejemplo, más de 10,000 líneas de resultados de grep), Claude Code la trunca y le dice al modelo cuántos resultados fueron omitidos. Sin esto, un resultado grande de una herramienta puede consumir toda tu ventana de contexto.

Autocompactación con reinyección de archivos

El compresor filtrado no descarta el contenido de los archivos. Después de resumir la conversación, reinjecta el contenido de los archivos accedidos recientemente (hasta 5,000 tokens por archivo). Esto significa que el modelo mantiene el conocimiento funcional de la base de código incluso después de la compactación.

Lo que aprendimos de la fuga

La fuga de Claude Code confirmó varios patrones que la comunidad de agentes de IA había teorizado:

El bucle principal es simple. Todo el patrón del agente cabe en 30 líneas. La complejidad reside en las herramientas y la gestión del contexto, no en la ingeniería de prompts.

Las herramientas dedicadas superan a bash. Las herramientas estructuradas y construidas para un propósito específico le dan al modelo una mejor densidad de información por token que la canalización de comandos bash.

La memoria necesita capas. Un índice siempre cargado, archivos de tema bajo demanda y transcripciones solo para grep equilibran la recuperación con los costos de contexto.

La gestión del contexto es el verdadero producto. La autocompactación, la reinyección de directrices del proyecto y el truncamiento de la salida son lo que hace viables las sesiones de codificación largas.

El arnés es el producto, no el modelo. El modelo proporciona inteligencia. El arnés proporciona percepción (lectura de archivos, búsqueda de código), acción (escritura de archivos, ejecución de comandos) y memoria. Construir un agente de codificación es construir el arnés.

Si quieres probar y depurar las interacciones de la API de tu agente personalizado, incluyendo conversaciones de uso de herramientas de múltiples turnos, esquemas de solicitud complejos y validación de respuestas, prueba Apidog gratis. Se encarga de la depuración de la API para que puedas centrarte en la lógica del agente.

Preguntas frecuentes

¿Puedo usar legalmente patrones de la fuga de Claude Code?

La fuga expuso patrones arquitectónicos, no algoritmos propietarios. Construir un agente de codificación que utilice un bucle `while` con despacho de herramientas es un patrón estándar documentado en la propia documentación de la API de Anthropic. No debes copiar el código de Anthropic textualmente, pero recrear la arquitectura con tu propio código es una práctica estándar.

¿Qué modelo debo usar para un agente de codificación DIY?

Claude Sonnet 4.6 ofrece el equilibrio adecuado de velocidad y capacidad para tareas de codificación. Claude Opus 4.6 produce mejores resultados en decisiones de arquitectura complejas, pero cuesta más y funciona más lento. Para ediciones y búsquedas de archivos simples, Claude Haiku 4.5 funciona y cuesta un 90% menos.

¿Cuánto cuesta ejecutar tu propio agente de codificación?

Una sesión de codificación típica (30-50 turnos) con Claude Sonnet 4.6 cuesta entre $1 y $5 en tarifas de API. El principal factor de costo es el tamaño de la ventana de contexto; una compactación agresiva mantiene los costos bajos. El código fuente filtrado de Claude Code muestra que activa la compactación al 92% del uso del contexto para controlar esto.

¿Por qué Claude Code usa React para una aplicación de terminal?

Ink (React para terminales) permite al equipo reutilizar el modelo de componentes de React y la gestión de estado para interacciones complejas de la interfaz de usuario, como diálogos de permisos, salida en streaming y visualizaciones de llamadas a herramientas. Para un proyecto DIY, un simple REPL de `input()` / `print()` es suficiente.

¿Cuál es la característica más importante a construir después del bucle principal?

El sistema de permisos. Sin él, el modelo puede sobrescribir archivos y ejecutar comandos arbitrarios sin supervisión del usuario. Incluso una simple puerta de “confirmar antes de escribir/ejecutar” previene la mayoría de los daños accidentales.

¿Cómo maneja Claude Code los errores de las llamadas a herramientas?

Los errores de las herramientas se devuelven como contenido de texto en el mensaje `tool_result`. El modelo ve el error y decide si reintentar, intentar un enfoque diferente o preguntar al usuario. No hay un manejo de errores especial; el razonamiento del modelo se encarga de la recuperación.

¿Puedo usar esto con modelos que no sean Claude?

Sí. El patrón de uso de herramientas funciona con cualquier modelo que admita la llamada a funciones: GPT-4, Gemini, Llama y otros. Necesitarás adaptar el formato de llamada API, pero el bucle del agente, las herramientas y el sistema de memoria son agnósticos al modelo.

¿Cómo evito que el agente ejecute comandos peligrosos?

Comienza con una lista negra de patrones peligrosos (`rm -rf /`, `mkfs`, etc.) y exige aprobación explícita para todas las llamadas a `run_command`. Claude Code clasifica cada operación como de riesgo BAJO, MEDIO o ALTO y bloquea o pide confirmación basándose en la clasificación. Construye lo mismo para tus herramientas.

Practica el diseño de API en Apidog

Descubre una forma más fácil de construir y usar APIs