Agent Squad · arquitectura

El viaje de un pedido

Desde el segundo en que presionás Login hasta que el primer muñequito te entrega el trabajo. Quién saluda a quién, dónde se valida tu identidad, cómo despierta el cerebro — y los dos momentos exactos en que entra el retrieval.

7 estaciones · seguí la línea
0 / 7
sequenceDiagram
    autonumber
    actor U as Vos (humano)
    participant W as Oficina · apps/web
    participant I as InsForge · identidad
    participant A as API substrato · :4000
    participant N as Nova · compositor
    participant V as pgvector + e5 · $0
    participant X as Executor
    participant G as Inngest · Docker
    participant P as Postgres · SoR
    participant L as Langfuse
    U->>W: clic LOGIN
    W->>I: credenciales
    I-->>W: sesión + workspace_id
    Note over W,I: identidad se valida ACÁ
    U->>W: "necesito X" (lenguaje natural)
    W->>A: POST /compose · HTTPS + bearer
    A->>N: interpretá el pedido
    N->>V: embebé → buscá SuperSkills
    V-->>N: 🔎 match? (RAG #1 · RUTEO)
    N-->>X: MATCH / PLAN / FORGE / CANNOT
    X->>G: encola steps (durable)
    G->>X: invoca handlers (retries)
    loop cada step = un muñequito
        X->>V: 🔎 recall de claims (RAG #2 · CONTEXTO)
        X->>L: traza la llamada LLM
        X->>P: escribe step_execution
    end
    X->>P: Artifacts + Claims (provenance)
    A-->>W: read-model: estado de la corrida
    W-->>U: el muñequito entrega ✅
    
1

El clic 🔐 identidad

Vos → Oficina → InsForge

Presionás Login en la oficina (apps/web, SvelteKit en Vercel). La oficina no sabe de contraseñas: se las pasa a InsForge, el dueño único de tu identidad. InsForge valida y devuelve una sesión con tu user_id y workspace_id.

Tu identidad se valida una sola vez y en un solo lugar. El cerebro en Docker nunca ve tu contraseña.

los datos sensibles del grafo viven en el box, no en el proveedor de identidad.
Frontera: InsForge manda en identidad; el substrato manda en el grafo. Dueño único por dato, sin replicación.
2

El pedido cruza a Hetzner 🤝 saludo #2

apps/web → API substrato (:4000)

Escribís "necesito X". La oficina hace el saludo real al cerebro: POST /api/workspaces/:id/compose por HTTPS + bearer. Viajan dos cosas: el texto y tu workspace_id (la etiqueta de tenencia).

La API valida el bearer — la segunda frontera. No revalida tu password (eso fue InsForge); confía en el token firmado.

solo cruza el workspace_id como referencia — la identidad no se replica en el box.
Hono API · superficies /compose · /intents · /approvals · /forge, todas tras bearer.
3

Nova interpreta 🔎 RAG #1 · ruteo

API → Nova → pgvector

Acá el agente sabe qué hacer. Nova embebe tu pedido (e5-small ONNX, in-process, $0) y hace búsqueda vectorial contra los SuperSkills guardados de tu workspace.

Según lo que el retrieval encuentre, decide el desenlace: MATCH (reusa) · PLAN (compone) · FORGE (construye) · CANNOT (honesto).

Es un RAG sobre el catálogo de capacidades — no sobre documentos. El retrieval es lo que elige con qué herramienta resolverte.

el embedding nunca sale del box: el ruteo es local, $0, sin API externa.
4 desenlaces de Nova. MATCH = match semántico fuerte contra SuperSkills; sin match → PLAN/FORGE.
4

El cerebro despierta el plan ⚙ durable

ExecutorInngest (Docker :8288)

Nova entrega el desenlace al Executor, que no ejecuta a lo bruto: encola los steps en Inngest. Inngest invoca de vuelta los handlers, con retries automáticos.

Es durable: si el box se reinicia a mitad de corrida, el run no se pierde.

El saludo de ida y vuelta que el bug histórico serveHost=localhost rompía en silencio: Inngest no lograba invocar de vuelta y nada se ejecutaba, sin un solo error visible.
5

El muñequito trabaja 🔎 RAG #2 · contexto

Executor → pgvector · Langfuse · Postgres

Cada step es una operación + un agente (el muñequito). Mientras trabaja, el executor hace recall vectorial de los claims previos del grafo (claim.recall_*): recupera lo que el squad ya estableció para fundamentar y no rehacer.

Si llama a un LLM, queda trazado en Langfuse (prompt, costo). Cada paso se escribe en Postgres (step_executions) — cientos de writes a localhost.

Mismo motor de embeddings que el #1, otro propósito: uno elige la herramienta, el otro alimenta el conocimiento.

Co-locación: la DB vive en el mismo box que el runtime — el recall y los writes son a microsegundos, no por red.
6

El gate ⏸ ≤72h

Inngest · waitForEvent → humano

Antes de oficializar puede haber un run-gate. Si lo hay, Inngest suspende la corrida de forma durable (waitForEvent, hasta 72h) — el muñequito espera sin consumir nada — hasta que un humano aprueba o rechaza desde la oficina. Si no hay gate, sigue derecho.

en lo regulado, este gate es la revisión experta obligatoria por documento antes de oficializar.
7

La entrega ✅ provenance

Postgres → read-model → Oficina → Vos

El trabajo se materializa en Artifacts + Claims con provenance en Postgres: cada claim apunta a su fuente (la trazabilidad que lo hace defendible en lo regulado).

El viaje de vuelta no es el grafo entero — es un read-model (status, % avance, link al artifact). El muñequito te entrega el trabajo en la oficina 3D.

solo proyecciones de estado cruzan a la oficina; el contenido sensible se queda en el box.
Frontera de una dirección: workspace_id hacia adentro, read-model idempotente hacia afuera. Sin sincronización bidireccional.

El giro: el retrieval entra dos veces

Mismo motor de embeddings local (e5-small ONNX, in-process, $0). Dos propósitos distintos:

🔎 #1 — Ruteo (estación 3)

"¿Qué sé hacer?" Retrieval sobre el catálogo de SuperSkills → elige el desenlace de Nova.

🔎 #2 — Contexto (estación 5)

"¿Qué ya sé?" Recall de claims previos del grafo → fundamenta el trabajo del agente.