# Substrato Agent Squad sobre Amazon Bedrock AgentCore — Estado del roadmap

Fecha: 2026-07-09 · Repo: `agent-squad-app` (branch `main`)

Principio rector: **el substrato es el plano de control soberano; AgentCore es un plano de ejecución y fontanería alquilado.** AgentCore nunca decide, solo ejecuta. Cada capacidad de AgentCore entra por un puerto (interface nuestra) con al menos 2 adapters, uno self-hostable, vivo en CI.

---

## Estado del roadmap

| Wave | Estado | PR / merge | Qué habilita |
|------|--------|-----------|--------------|
| **0 · ModelPlane L1** | ✅ en `main` | #75 · `fdcce16` | Router de modelos por clase de tarea; Bedrock opt-in |
| **1a · SandboxPort + spike** | ✅ en `main` | #76 · `5fe5d04` | Puerto async sobre FORGE + fix de seguridad + spike de Code Interpreter validado |
| **1b · CodeInterpreterAdapter** | ✅ en `main` | #77 · `c79d9f6` | Ejecución remota de FORGE en microVMs Firecracker; paridad 8/8 con local |
| 2 · Tool Broker + Gateway + Identity + Policy | pendiente | — | Capacidades impuras de FORGE vía tools MCP con grants |
| 3 · Runtime + Strands (ADR-001) | pendiente | — | Agent-sessions largas; Strands como Execution Adapter puro |

**Efecto en producción hoy: cero.** `local`/`claude-cli` siguen de default en el ModelPlane y en el SandboxPort; todo lo de AgentCore es opt-in reversible al instante.

---

## Wave 0 — ModelPlane L1 (router de modelos por clase de tarea)

Punto único de resolución de modelo por **clase de tarea** (`judge`, `compose`, `standard`, `lite`, `bulk`) con política en Postgres + env, y provider `bedrock` junto a `claude-cli`/`anthropic-api`.

- **Paridad total al merge:** todas las clases resuelven por default al modelo y canal actuales. Mover una clase a otro modelo/proveedor pasa a ser config (fila en `model_routing_policy` o `MODEL_CLASS_<CLASE>`), no código.
- El model id estaba hardcodeado en 20 archivos; ahora vive en un solo punto de resolución.
- Validado en vivo: Bedrock Converse a Haiku 4.5 respondió con las credenciales del box.
- Palanca de recuperación ante CLI caído documentada: `LLM_API_FALLBACK=true` (el `LLM_PROVIDER` global quedó inerte para llamadas con `modelClass`).

---

## Wave 1a — SandboxPort + conformance + spike

El sandbox de FORGE (ejecución de código no confiable) pasa de dos funciones acopladas al box a un puerto async `SandboxAdapter` con `verify()`/`execute()` y taxonomías `ok|red|infra` / `ok|error|infra`.

- **`LocalSandboxAdapter`** (bwrap) es el primer adapter; `local` es el default.
- **Fix de seguridad real:** el loop Inngest de FORGE podía degradar el `verify` a ejecución sin aislamiento de red en producción; ahora hace fail-hard `infra` igual que `execute`.
- **Suite de conformance** (8 casos): garantía ejecutable de que cualquier adapter futuro preserva la taxonomía. Es la ruta de salida de AgentCore.
- **Spike de Code Interpreter** (validado contra AWS real):
  - **G1 · egress:** bloqueado por DNS, por IP cruda y por TCP directo. El MMDS del microVM responde pero `iam/security-credentials` da 404 → sin credenciales IAM que robar.
  - **G2 · runtime:** deno 2.3.3 con TypeScript nativo, node 24, npm/npx; ARM64/Amazon Linux 2023.
  - **G3 · fidelidad:** estrategia deno + shim de vitest reprodujo los 4 veredictos del sandbox local exactos.

---

## Wave 1b — CodeInterpreterAdapter (ejecución remota de FORGE)

Segundo adapter del SandboxPort: ejecuta `verify`/`execute` de FORGE en una sesión efímera de **AgentCore Code Interpreter** (microVM Firecracker, modo SANDBOX), sacando la ejecución de código no confiable del box de producción.

- **Conformance remota 8/8 = paridad con el adapter local.** La prueba ejecutable de que el contrato es nuestro y AgentCore solo ejecuta.
- Estrategia: deno con TS nativo + shim de vitest vía import map (cero red, cero deps del registry, sin tocar el contrato de generación de FORGE).
- `local` sigue de default; `code-interpreter` es opt-in vía `FORGE_SANDBOX_ADAPTER=code-interpreter` + `AGENTCORE_CODE_INTERPRETER_ID`. Reversible al instante (el adapter se resuelve por llamada).
- **Regla load-bearing preservada:** todo error de AWS/sesión/transporte/timeout → `infra`, jamás un falso `red`/`error` de generación.

### Hallazgos del proceso adversarial (todos resueltos o documentados)

El valor de la conformance + reviews encadenados: cazaron defectos reales en orden de sutileza creciente, ninguno detectable por tests unitarios:

1. Bug de provisioning que solo AWS revela: el nombre del interpreter debe cumplir `[a-zA-Z][a-zA-Z0-9_]{0,47}` (sin guiones) → prefijo `forge_ci_`.
2. Divergencia de runtime (deno niega red/env por default) → fix `--no-prompt` (denegación = `red`, no `infra`-hang) + fixture de env agnóstica al runtime.
3. La clase del **bug del PATH**: deno ausente → exit 127 → se clasificaba `red` en vez de `infra` → fix con **nonce por invocación** en el sentinel (inforjable por el código no confiable), anclado a exit 127 para evitar falsos positivos.
4. El nonce filtrable vía `/proc` → documentado como fast-follow pre-default (DoS-only, threat model hipotético) en vez de seguir refinando.

### Fast-follows de seguridad ANTES de promover `code-interpreter` a default

Ambos DoS-only y bajo threat model hipotético (el "código no confiable" es generado por el LLM de FORGE intentando cumplir una tarea, no por un atacante externo). Con `local` de default no afectan a producción.

1. **Acotar `--allow-read`** a los archivos exactos del sandbox (cierra el canal `/proc` y reduce superficie). Requiere re-validar la conformance remota.
2. **Ampliar `safety.ts`** para cubrir las APIs nativas `Deno.readTextFile`/`Deno.writeTextFile` (hoy solo bloquea `readFileSync`/`writeFileSync`).

---

## Infra AWS provisionada

- **Grant IAM:** política `AgentCoreCodeInterpreterSpike` (least-privilege, Code Interpreter control + data plane) adjunta a `remotion-lambda` en la cuenta `226585212364` / `us-east-1`.
- **Interpreter:** `forge_ci_1783617549840-PK1X81ohys` (custom, `networkMode: SANDBOX`), provisionado y ocioso (no cobra idle; solo las sesiones cobran).
- Regla operativa de seguridad: NO poner secretos en tags/user-data del interpreter (el MMDS es legible por el código dentro del sandbox).

---

## Cómo se ejecutó (protocolo cerebro/manos)

- **Cerebro:** Fable 5 (planes, auditorías, decisiones de diseño, verificación con evidencia, trabajo contra AWS).
- **Manos:** Codex CLI (Waves 0, 1a y el grueso de 1b) y, cuando Codex agotó su cuota de ChatGPT Plus, subagentes Sonnet (tramo final de 1b) por autorización explícita.
- Cada task pasó por implementer → review en sesión fresca → fixes → review final de rama; la verificación con evidencia real (tests, typecheck, conformance contra AWS) la hizo siempre el cerebro.

---

## Próximos pasos posibles

1. **Wave 2** — Tool Broker + Gateway + Identity + Policy: desbloquea las capacidades impuras de FORGE (llamar APIs externas) vía tools MCP con grants de corta vida por step.
2. **Cerrar los fast-follows de seguridad de la 1b** para dejar el adapter remoto listo para promover a default por entorno.
3. **Activar el ModelPlane por clase** (ej. mover `lite`/`bulk` a Haiku 4.5 en Bedrock, ~70% más barato) con shadow-scoring.

Documentos fuente en el repo: `docs/superpowers/specs/` y `docs/superpowers/plans/` (specs y planes de cada wave), `docs/spikes/` (actas del spike y de la conformance remota), `docs/runbooks/` (model-plane, code-interpreter). Arquitectura objetivo completa: basic-memory `agent-squad-substrate/arquitectura-objetivo-agentcore.md`.
