Última revisión: mayo de 2026
Practica los temas del examen CCA-F desde tu terminal — comandos de Claude Code CLI, llamadas a la API de Anthropic, servidores MCP y patrones multi-agente, cada uno vinculado a un dominio del examen.
Al finalizar este laboratorio, habrás instalado Claude Code, configurado un proyecto con CLAUDE.md, creado un comando slash personalizado, conectado un servidor MCP, utilizado la API tool_use con salida estructurada, explorado el pensamiento extendido y construido un pipeline de supervisor multiagente — cubriendo los cinco dominios del examen CCA-F desde tu terminal. No se requiere cuenta en la nube ni facturación; todo se ejecuta localmente.
node --version)ANTHROPIC_API_KEY en tu shell (export ANTHROPIC_API_KEY=sk-ant-...)mkdir cca-f-lab && cd cca-f-lab)Las llamadas a la API de Anthropic conllevan cargos basados en el uso. Los pasos 6-8 y 10 utilizan claude-sonnet-4-6, que cuesta aproximadamente $3/M tokens de entrada y ~$15/M tokens de salida. El costo total de este laboratorio suele ser inferior a $0.15. El pensamiento extendido (Paso 7) utiliza tokens de pensamiento adicionales facturados a la tarifa de salida.
Claude Code es la CLI que el examen CCA-F evalúa más directamente — la configuración, los hooks, los comandos slash y los modos de permiso residen aquí. Comenzamos instalándolo globalmente para que cada paso posterior pueda llamar a claude.
Después de la instalación, un rápido claude --version demuestra que el binario está en tu PATH, y claude --print-system-prompt confirma que la clave API es válida (realiza una llamada ligera internamente).
# Install Claude Code globally
npm install -g @anthropic-ai/claude-code
# Verify installation
claude --version
# Confirm API connectivity (prints the built-in system prompt)
claude --print-system-prompt | head -20El examen evalúa exhaustivamente la jerarquía de tres niveles de CLAUDE.md: usuario (~/.claude/CLAUDE.md), proyecto (raíz del repositorio) y módulo (subdirectorios). Cada nivel hereda del superior y puede anularlo.
Crearemos un archivo a nivel de proyecto que establece convenciones de codificación y un archivo a nivel de usuario que establece preferencias personales. Cuando Claude Code lee el proyecto, fusiona los tres niveles — exactamente el comportamiento que el examen pregunta.
# Create project root CLAUDE.md
cat > CLAUDE.md << 'EOF'
# Project: CCA-F Lab
## Coding conventions
- Use TypeScript for all new files
- Prefer const over let
- Use single quotes for strings
- No semicolons (Prettier default)
## Testing
- Run `npm test` before committing
- All new functions must have at least one test
EOF
# Create user-level CLAUDE.md (applies to ALL your projects)
mkdir -p ~/.claude
cat > ~/.claude/CLAUDE.md << 'EOF'
# User preferences
- Be concise in responses
- Prefer functional programming patterns
- Always explain the "why" before showing code
EOF
# Verify Claude Code sees both files
claude "What instructions do you see in CLAUDE.md?" --printLos comandos slash personalizados residen en .claude/commands/ como archivos Markdown. El nombre del archivo se convierte en el nombre del comando (por ejemplo, scaffold.md → /scaffold). El contenido del archivo es la plantilla de prompt — puede incluir $ARGUMENTS para la entrada del usuario.
Este es un tema de examen de alta frecuencia: dónde residen los comandos, cómo se pasan los argumentos y cómo difieren de los hooks.
# Create the commands directory
mkdir -p .claude/commands
# Create a scaffold command
cat > .claude/commands/scaffold.md << 'EOF'
Create a new TypeScript module named $ARGUMENTS with:
1. A main source file at src/$ARGUMENTS/index.ts
2. A test file at src/$ARGUMENTS/__tests__/index.test.ts
3. Export the module from the project root index.ts
Follow the coding conventions in CLAUDE.md.
EOF
# Test the command (Claude Code will execute it interactively)
claude /scaffold calculatorLos hooks ejecutan comandos de shell en respuesta a eventos de Claude Code. El examen evalúa tres tipos de hooks: PreToolUse (antes de que se ejecute una tool), PostToolUse (después) y Notification (en cambios de estado). Los hooks se definen en .claude/settings.json.
Agregaremos un hook PostToolUse que ejecuta un linter después de cada edición de archivo — un patrón de producción común sobre el que el examen pregunta con frecuencia.
# Initialize a package.json so we have a lint script
npm init -y
npm install --save-dev typescript @typescript-eslint/parser
# Create project-level settings with a post-tool hook
mkdir -p .claude
cat > .claude/settings.json << 'EOF'
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"command": "npx tsc --noEmit 2>&1 | head -5"
}
]
},
"permissions": {
"allow": [
"Read",
"Write",
"Edit"
]
}
}
EOF
# Verify settings are recognized
cat .claude/settings.jsonEl Model Context Protocol (MCP) es un dominio central del examen. Los servidores MCP exponen tools, resources y prompts a los clientes LLM a través de un protocolo JSON-RPC estandarizado. El transporte stdio es el más simple — el servidor lee de stdin y escribe en stdout.
Construiremos un servidor MCP mínimo que expone una tool get_weather, luego configuraremos Claude Code para conectarse a él. Esto ejercita el ciclo de vida completo de MCP que el examen evalúa: definición de tool, cableado de transporte, invocación de tool y manejo de resultados.
# Install the MCP SDK
npm install @modelcontextprotocol/sdk
# Create the MCP server
cat > mcp-weather.mjs << 'EOF'
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new McpServer({ name: "weather", version: "1.0.0" });
server.tool("get_weather", { city: { type: "string" } }, async ({ city }) => ({
content: [{ type: "text", text: `Weather in ${city}: 72°F, sunny` }],
}));
const transport = new StdioServerTransport();
await server.connect(transport);
EOF
# Register the MCP server in Claude Code settings
cat > .claude/settings.json << 'EOF'
{
"mcpServers": {
"weather": {
"command": "node",
"args": ["mcp-weather.mjs"]
}
}
}
EOF
# Ask Claude Code to use the MCP tool
claude "What is the weather in Tokyo? Use the get_weather tool."El examen evalúa en detalle el flujo de tool_use de la API de Messages: envías tools en la solicitud, el modelo responde con un bloque de contenido tool_use, lo ejecutas y devuelves un tool_result, y luego el modelo produce la respuesta final.
Este paso utiliza curl para llamar directamente a la API — el enfoque más alineado con el examen, ya que este evalúa el formato de solicitud/respuesta sin procesar, no los wrappers del SDK.
# Call the Messages API with a tool definition
curl -s https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"tools": [{
"name": "calculate",
"description": "Evaluate a math expression",
"input_schema": {
"type": "object",
"properties": {
"expression": { "type": "string", "description": "Math expression to evaluate" }
},
"required": ["expression"]
}
}],
"messages": [{
"role": "user",
"content": "What is 15% tip on a $85.50 dinner bill?"
}]
}' | python3 -m json.toolEl pensamiento extendido permite al modelo usar un bloque thinking para razonar paso a paso antes de responder. El examen evalúa cuándo usarlo (razonamiento complejo, matemáticas, generación de código) y cómo configurar budget_tokens.
Enviaremos un acertijo lógico deliberadamente complicado y compararemos las respuestas con y sin pensamiento extendido para ver la diferencia de calidad de primera mano.
# Request WITH extended thinking
curl -s https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 16000,
"thinking": {
"type": "enabled",
"budget_tokens": 10000
},
"messages": [{
"role": "user",
"content": "A farmer has 17 sheep. All but 9 run away. How many does he have left? Explain your reasoning step by step."
}]
}' | python3 -m json.tool
# The response includes a "thinking" block showing the model's
# internal reasoning before the final answer.El caché de prompts permite marcar partes de la solicitud como cacheables. Los prefijos en caché cuestan un 90% menos en llamadas posteriores y tienen cero latencia adicional. El examen evalúa la ubicación del bloque cache_control y los encabezados de acierto de caché.
Enviaremos el mismo prompt de sistema grande dos veces y verificaremos los encabezados de respuesta para confirmar el acierto de caché en la segunda llamada.
# First call — creates the cache entry
curl -s -D /dev/stderr https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 256,
"system": [{
"type": "text",
"text": "You are a helpful assistant specialized in cloud architecture. You follow AWS Well-Architected Framework principles. You always recommend infrastructure as code. You prefer Terraform over CloudFormation. You prioritize security and cost optimization.",
"cache_control": { "type": "ephemeral" }
}],
"messages": [{ "role": "user", "content": "How should I set up VPC peering?" }]
}' > /dev/null 2>&1
# Second call — should hit the cache (check usage.cache_read_input_tokens)
curl -s https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 256,
"system": [{
"type": "text",
"text": "You are a helpful assistant specialized in cloud architecture. You follow AWS Well-Architected Framework principles. You always recommend infrastructure as code. You prefer Terraform over CloudFormation. You prioritize security and cost optimization.",
"cache_control": { "type": "ephemeral" }
}],
"messages": [{ "role": "user", "content": "What about NAT gateway sizing?" }]
}' | python3 -c "import sys,json; d=json.load(sys.stdin); print(f\"Cache read tokens: {d['usage'].get('cache_read_input_tokens', 0)}\")"El examen evalúa cómo ejecutar Claude Code de forma no interactiva — el flag --print envía el resultado a stdout sin una sesión interactiva, y --output-format json proporciona una salida estructurada para scripts.
Este es el patrón utilizado en los pipelines de CI: se alimenta un prompt, se obtiene un resultado, se analiza programáticamente.
# Headless mode: prompt in, text out
claude --print "List 3 TypeScript best practices, one per line"
# JSON output for programmatic use
claude --print --output-format json "What is 2+2?"
# Pipe a file for code review (CI pattern)
echo 'const x: any = "hello";' > example.ts
claude --print "Review this TypeScript file for type safety issues: $(cat example.ts)"El Dominio 1 (Arquitectura Agentica, 27%) es el de mayor peso en el examen. El patrón de supervisor — un orquestador que distribuye tareas a subagentes especialistas, cada uno con su propio prompt de sistema y conjunto de tools — es la arquitectura más evaluada.
Construiremos un script Node.js autocontenido que implementa un supervisor coordinando a dos especialistas: un investigador que lee archivos y resume, y un escritor que produce la salida. El supervisor descompone una tarea, delega a cada especialista a través de llamadas a la API separadas y agrega los resultados. Ejecútalo desde la terminal y observa cómo se produce la delegación en vivo.
# Install the Anthropic SDK
npm install @anthropic-ai/sdk
# Create sample data for the agents to work with
cat > sales-data.csv << 'EOF'
month,revenue,units
Jan,12500,150
Feb,15200,180
Mar,11800,140
Apr,18900,220
May,22100,260
Jun,19500,230
EOF
# Create the multi-agent supervisor script
cat > supervisor.mjs << 'SCRIPT'
import Anthropic from "@anthropic-ai/sdk";
import { readFileSync } from "fs";
const client = new Anthropic();
async function callAgent(role, systemPrompt, userMessage) {
console.log(`\n--- ${role} agent ---`);
const response = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
system: systemPrompt,
messages: [{ role: "user", content: userMessage }],
});
const text = response.content
.filter((b) => b.type === "text")
.map((b) => b.text)
.join("\n");
console.log(text);
return text;
}
// --- Supervisor: decompose, delegate, aggregate ---
const data = readFileSync("sales-data.csv", "utf-8");
console.log("=== SUPERVISOR: Decomposing task ===");
console.log("Task: Analyze sales data and write a brief executive summary.\n");
console.log("Step 1: Delegate analysis to Researcher agent");
console.log("Step 2: Delegate writing to Writer agent");
console.log("Step 3: Combine results\n");
// Sub-agent 1: Researcher — extracts insights
const analysis = await callAgent(
"Researcher",
"You are a data analyst. Extract key trends, highs, lows, and growth rates. Be precise with numbers. Output bullet points only.",
`Analyze this CSV data:\n\n${data}`
);
// Sub-agent 2: Writer — produces the summary from the analysis
const summary = await callAgent(
"Writer",
"You are a business writer. Write a 3-sentence executive summary from the analysis provided. Use a professional tone. Include specific numbers.",
`Write an executive summary based on these findings:\n\n${analysis}`
);
console.log("\n=== SUPERVISOR: Final aggregated output ===");
console.log(summary);
SCRIPT
# Run the supervisor
node supervisor.mjsEste laboratorio se ejecuta completamente de forma local — no hay recursos en la nube que desmantelar.
# Remove the lab directory
cd .. && rm -rf cca-f-lab
# Optionally remove the user-level CLAUDE.md we created
rm -f ~/.claude/CLAUDE.md
# Optionally uninstall Claude Code
npm uninstall -g @anthropic-ai/claude-code
Este laboratorio se centra en ejercicios prácticos de CLI y API. NO cubre:
Batch es conceptualmente simple pero tarda minutos en completarse; el Playbook cubre el formato de solicitud.Browse y Playbook.