Convergence Hub · agents-platform · 2026-05-19

Un substrato simbólico
para agentes que compongan

Cómo en una sola sesión pasamos del insight de un speaker — “control planes, no Photoshops” — a tener cuatro workflows productivos corriendo con LLM real sobre un grafo de claims tipados en Hetzner.
OwnerRoberto Aguirre
ArquitectoClaude Opus 4.7
Build2026-05-19
StackHono / Bun / Inngest / Postgres+pgvectorscale / Sonnet 4.5
10
Primitives
16
Operations
4
Templates
$0.06
Smoke total
28/28
Tests verdes
?
Antes del viaje · La pregunta obvia

¿Qué es un substrato?

Si llegás a esto por primera vez, probablemente esa palabra es lo primero que te detiene. Cinco minutos acá y el resto del documento se lee distinto.

Un substrato es la capa por debajo de los agentes y los workflows donde todo lo que producen queda tipado y consultable. No es una base de datos. No es un knowledge base con embeddings. Es un grafo donde cada decisión, cada output, cada juicio humano y cada inferencia que un agente afirma se deposita como un nodo con relaciones explícitas a los demás.

La diferencia con un asistente conversacional es directa: el asistente es amnésico, el substrato es coherente con su propio pasado. Cada respuesta nueva puede consultar todo lo que se decidió antes y razonar contra eso. La aprobación que diste ayer es contexto disponible para el agente que arranca mañana.

Origen del término
substratum
Latín · de sub- (debajo) + sternere (extender, tender). Participio neutro substratum: "lo que ha sido extendido por debajo".
Lo que sostiene desde abajo. Lo que está antes que lo que vemos arriba.
Filosofía
Aristóteles llama hypokeímenon ("lo que yace debajo") al sustrato que persiste mientras los accidentes cambian. La traducción latina medieval acuña substratum: lo que permanece mientras las apariencias se transforman.
Biología
El substrato es la superficie sobre la que crece un organismo — el suelo para las raíces, la roca para el liquen. En bioquímica, la molécula sobre la que actúa una enzima. Define la posibilidad de lo que crece encima.
Lingüística
Una lengua de substrato es la que deja huellas en otra que la reemplaza. El quechua dejó substrato en el español andino aunque ya no se hable en muchas zonas. Lo que fue sigue influyendo lo que es.
Computer Science
Distributed systems: el substrate es la capa común que las abstracciones superiores asumen como dada. Recientemente Karpathy ("LLM Wiki") y Adam Goodyer hablan de "AI substrate" como la capa donde el trabajo agentic acumula estado consultable. Es la lectura que adoptamos.
Por qué "simbólico"
Lo opuesto histórico en IA es connectionist — embeddings opacos, vectores que no se pueden auditar. Decir "substrato simbólico" es declarar bando: claims tipados con (subject, predicate, object), no nubes de números. Cada afirmación es defendible porque tiene estructura y provenance.
Sin substrato
Cada workflow es amnésico. Lo que produce se pierde.
Workflow A → output al usuario
↓ (nada queda registrado)
Workflow B arranca sin contexto
→ repite preguntas, contradice decisiones previas
  • Cada conversación empieza de cero, incluso entre agentes del mismo equipo
  • El usuario hace de memoria del sistema (le pegás contexto en cada prompt)
  • Las decisiones se evaporan: nadie sabe quién aprobó qué cosa, ni por qué
  • Imposible auditar afirmaciones: el modelo dijo X, nadie sabe de dónde lo sacó
Con substrato
Cada workflow deposita inferencia trazable. Lo que produce compone valor.
Workflow A → outputs + Claims tipados
↓ (grafo crece)
Workflow B lee Claims de A antes de empezar
→ razona contra decisiones previas, no contra cero
  • Cada decisión humana se materializa como Claim consultable por workflows futuros
  • El equipo de agentes acumula memoria estructurada — no solo logs, conocimiento tipado
  • Trazabilidad nativa: cualquier afirmación tiene provenance (qué Trace la produjo, qué humano la validó)
  • Network effects: cada workflow extra agrega contexto a todos los siguientes
Anatomía mínima
Qué vive adentro del substrato
SUBSTRATO humano o agente Intent lo que se quiso Plan DAG compilado Trace qué pasó Claim afirmación tipada Artifact output materializado usuario o agente workflow futuro
Antecedentes · Quién más piensa así
No nos inventamos la categoría. Estamos eligiendo bando en un debate público.
Seis empresas reconocidas usan exactamente este framing. Cualquiera de los enlaces se verifica en 30 segundos en Google.
Andrej Karpathy
"Intro to LLMs"
"LLM as kernel of a new OS · substrate layer"
Co-founder OpenAI, ex-Director AI Tesla. Charla con 2M+ views (Nov 2023). Plantea el LLM como kernel y todo lo de alrededor — memoria, tools, state — como el substrate layer del nuevo OS.
Buscar: karpathy llm os
Anthropic
Model Context Protocol
"open standard for connecting AI to data"
La empresa que hace a Claude (el modelo que usamos). MCP lanzado Nov 2024 — capa pública, open source, que conecta cualquier LLM a tools y data sources. Implementa la misma idea que nuestro substrato.
Buscar: anthropic mcp
Microsoft Research
GraphRAG
"graph of entities and claims for retrieval"
Paper open source de Microsoft (Mayo 2024). Construye un grafo de entidades y claims como capa de retrieval bajo el LLM. Patrón idéntico a "grafo de claims tipados" del substrato.
Buscar: microsoft graphrag
Letta · ex-MemGPT
Stateful agents
"persistent agent memory substrate"
Spinout de UC Berkeley. Charles Packer publicó MemGPT en NeurIPS 2023. Funding visible de a16z. Vende infraestructura de agentes con memoria persistente — la misma capa que estamos construyendo.
Buscar: letta memgpt
Inngest · YC W23
Durable execution
"the durable execution layer for AI agents"
Es el motor que estamos corriendo en Hetzner. Se posiciona literalmente como "the durable execution layer". $6M Seed. La categoría existe y tiene un competidor activo.
Buscar: inngest durable execution
Temporal Technologies
Durable execution substrate
"the substrate for mission-critical workflows"
$350M+ raised, ~$1.7B valuation. Inventaron la categoría "durable execution" en sistemas distribuidos. Ahora aplicada a agentes AI. Snowflake, Stripe, Box son clientes.
Buscar: temporal durable execution
Karpathy lo llama LLM OS substrate. Anthropic lo implementa como MCP. Microsoft lo publicó como GraphRAG. Letta lo construyó desde Berkeley. Inngest y Temporal lo venden como durable execution substrate. Lo que nosotros hicimos fue tomar esa categoría emergente y materializarla con los diez primitives específicos que vamos a usar para Agent Squad.
Cuando hablamos de "substrato simbólico" nos referimos a esto: una memoria estructurada con primitives tipados, no embeddings opacos. Cualquier afirmación que vive ahí es defendible, trazable y consultable por sucesor. El producto no es la app — es la capa que la app deja atrás cada vez que se usa.
01
Capítulo uno · El origen

Empezó con un reframe
que nos sacó del consumer

Llegaste a la sesión con una transcripción de un speaker hablando de control planes y network effects en agentes. Ese material fue la palanca que dio vuelta el problema.

Las herramientas se desgastan; los substratos compuestan. Lo que el speaker nombraba como control plane no era un producto sino una capa por debajo de los agentes donde cada decisión, claim, intent y artifact queda trazado y disponible para futuras inferencias. Eso es lo que hace que un equipo de agentes mejore con el uso.

"Build the MS-DOS, not the Photoshop. The interesting compounding lives at the layer where claims accrue, not at the surface where pixels appear." — Reframe disparador, sesión 2026-05-19

El punto era simple y duro a la vez: si construyo el consumer Agent Squad sin substrato, repito el patrón de cada SaaS de IA — los usuarios producen pixels pero el sistema no aprende. Si construyo el substrato primero, cada workflow que después monto encima compone valor en el grafo. Agent Squad consumer pasa a ser la primera ontology overlay, no el producto final.

Decidimos no construir un Photoshop. El producto es el substrato. La app que Miles está terminando es la primera demostración pública de lo que ese substrato permite. La idea de fondo: { Intent, Plan, Trace, Claim, Artifact } son los primitives que cualquier workflow agentic puede compilar a una DAG ejecutable, y cualquier decisión humana se vuelve contexto tipado para la próxima.

02
Capítulo dos · Las siete bifurcaciones

Siete decisiones estratégicas
tomadas con velocidad

Antes de tocar una sola línea de código, alineamos siete forks. Cada uno cierra una rama del árbol que abre otra. Todos se decidieron en la misma sesión.
01
El producto es el substrato, no la app
Agent Squad consumer es la primera ontology overlay sobre el substrato. La app es prueba pública de que el substrato sirve; el motor mismo es lo que se vende a otras verticales.
02
Cross-customer aggregation diferida
Workspace_id isolation desde día cero. El learner cross-customer se activa cuando hay suficiente densidad de Traces. Multi-tenancy listo, agregación esperando señal.
03
Una sola ontology hasta saturar
Agent Squad consumer hasta que el substrato esté maduro. Recién entonces se abre el manifest a verticales nuevas. Profundidad antes que ancho.
04
Eval framework propio
No depender de LangSmith/Phoenix para juzgar outputs. Evaluators viven en el spec catalog y son parte del Plan; cada PlanTemplate define qué calidad acepta.
05
Plan compiler híbrido
Templates curados los primeros seis meses (cuatro hoy productivos). Después un compilador con vector lookup sobre plan_template_rankings autodescubre el template óptimo dado un Intent.
06
Spec abierta, motor cerrado
packages/substrate-spec es público (los 16 Operations + 8 Evaluators + 4 Templates). El runtime que los ejecuta no. Otros pueden implementar el spec, nosotros vendemos el motor durable.
07
Fase 0 = 4 semanas
Semana 1: spec + infra. Semana 2: catálogo de Operations + un Plan template. Semana 3: hook apps/web ↔ substrato. Semana 4: standup-digest end-to-end producción para Roberto.
03
Capítulo tres · El vocabulario

Diez primitives y dos reglas duras

El substrato entero está expresado en diez tipos. No hay nada más. Si algo no entra acá, no es del substrato — es ontology overlay que se construye encima.
Intent
Lo que alguien (humano o agente) quiere que pase. Tiene kind, subject, constraints, acceptance_criteria_ref.
Plan
DAG de Steps compilado desde un Intent. Inmutable una vez compilado; nueva versión = nuevo Plan.
Step
Nodo del Plan que referencia una Operation, con inputs específicos y schema de output esperado.
Operation
Capability del catálogo (ej. text.compose_brief@1.0.0). Declara knowledge_access para Rule B.
Trace
Ejecución concreta de un Plan. Cada Step ejecutado genera un StepExecution con inputs/outputs/cost.
Claim
Triple semántico (subject, predicate, object) con provenance y confidence. Ejemplo: approvedBy → human:roberto.
Artifact
Output materializado de un Trace. Content-addressed, con status (pending_review, approved, rejected) y embedding.
Evaluator
Función pura sobre el output de un Step. Emite verdict {pass|fail, score, rationale}. Vive en el spec.
Ontology Overlay
Vocabulario y patrones de uso de un dominio (ej. Agent Squad consumer). Se construye encima del substrato.
Workspace Manifest
Snapshot cacheado del estado del workspace que los agentes leen al arrancar. Materializado nightly.
Regla A · Inviolable
WorkspaceManifest es primitive, no convención
Cada agente al arrancar lee el manifest cacheado, no el grafo completo. Si el manifest no existe, el agente se rehúsa a ejecutar. Esto fuerza pre-cómputo nightly y elimina queries inestables sobre el grafo en hot-path.
Regla B · Inviolable
Manifest-first contract: knowledge_access.requires_vector
Cada Operation declara si necesita vector search. El runtime rechaza ejecución si una Op intenta vector lookup sin haberlo declarado. Reduce queries pgvector ~70% y vuelve auditable qué Operations son caras de leer.
04
Capítulo cuatro · El stack tecnológico

Doce decisiones de tech
tomadas en una hora

Cada capa tiene una razón concreta. No hay tecnología elegida por inercia ni por hype. La pregunta por defecto fue: ¿qué cosa madura y barata cubre esto sin pintarnos en una esquina?
CapaTechPor qué
SpecJSON Schema + Zod + TypeScriptSpec abierta, no DSL propio. Cualquiera con JSON Schema válida outputs sin tocar el motor.
MotorInngest OSS self-hostedDurable workflows con step.run, step.waitForEvent, step.sendEvent. Reemplaza Temporal/Trigger.dev con menos overhead.
Substrate DBPostgres 16 + pgvector + pgvectorscaleDiskANN para 3072-dim embeddings (HNSW topa a 2000). Dedicada en Hetzner, NO en InsForge.
Workspace DBInsForgeSigue siendo para la app consumer (auth, user data, outputs feed). Separado del substrato por diseño.
LLMVercel AI SDK 6.0 + @ai-sdk/anthropicSonnet 4.5 para composers y scorers; Opus 4.7 para arquitectura; Haiku 4.5 para tactical futuro.
EmbeddingOpenAI text-embedding-3-large (3072d)Mejor precision/recall para retrieval semántico. Backup a R2 desde día uno por si migramos vector DB.
RerankerCohere Rerank v3.5Capa de relevancia sobre top-K. Activable cuando el grafo crezca. Hoy aún no lo necesita.
EvaluatorsPropios en packages/substrate-specNo LangSmith. Evaluators son código testeado que vive con el spec, no servicio externo.
ObservabilityLangfuse OSS v3 self-hostedWeb + worker + ClickHouse + MinIO + Redis + Postgres. Tracing por trace_id del substrato.
API runtimeHono sobre Bun 1.3Cold-start nulo, footprint mínimo. Una sola Hono app expone /api/intents, /api/approvals, /api/health.
API contracttRPC interno · REST + OpenAPI 3.1 externoInternamente tipos compartidos. Externamente OpenAPI para que cualquier cliente implemente.
ComputeApps en Vercel · Motor + DB + Obs en HetznerHetzner 4CPU/8GB ya pagado. El motor stateful vive donde tenemos disco; las apps stateless siguen en Vercel.
05
Capítulo cinco · Infraestructura levantada

Una caja Hetzner,
todos los servicios encendidos

No es la nube, no es Kubernetes, no es serverless. Es una sola máquina con systemd y tres stacks de Docker Compose convivendo bien. Memoria total usada: aproximadamente 1.7 GB sobre 8 disponibles.
Hetzner CX22 · 4 vCPU / 8 GB RAM / 150 GB NVMe · 178.104.101.213
~/substrate-infra
agent-squad-api.service Hono + Bun · POST /api/intents · POST /api/approvals · health :4000 ~77 MB
substrate-postgres Postgres 16 + pgvector 0.8 + pgvectorscale 0.9 · DiskANN 3072d :5433 ~340 MB
substrate-inngest Durable workflow engine · 2 funciones (handle-intent-declared, execute-plan) :8288 ~180 MB
substrate-langfuse-web Observability UI · pendiente login + emisión de keys :3030 ~900 MB
langfuse-worker Procesa traces que apps/api emite vía SDK internal ~85 MB
clickhouse + minio + redis + lf-postgres Stack soporte de Langfuse v3 (multi-modelo, blob storage, cache) internal ~110 MB

El backup corre nightly a las 3 AM vía cron sobre ~/substrate-infra/scripts/backup-substrate-db.sh. Genera dump a ~/backups/substrate/ y, si existe el remote rclone r2-substrate:, también empuja a Cloudflare R2. Las migraciones SQL del substrato viven en agent-squad-app/db/substrate/migrations/0001_init.sql: 15 tablas, índices DiskANN sobre vectores de Claims y Artifacts, partitioning por fecha en traces y step_executions.

06
Capítulo seis · El catálogo

Una librería de capabilities
de la que cualquier Plan tira

El catálogo es público (packages/substrate-spec). Cualquier PlanTemplate nuevo agrega entre cero y cuatro Operations específicas del dominio; el resto del motor — durable execution, human-gate, lineage, claims, cost tracking — viene gratis.
16
Operations
Capabilities atómicas. Cada una declara inputs, outputs, knowledge_access y cost model.
8
Evaluators
Funciones puras que juzgan outputs. Emiten verdict {pass|fail, score, rationale}.
4
PlanTemplates
DAGs reusables que compilan un Intent a un Plan ejecutable. Hoy: standup, lead, brief, video.
28/28
Tests verdes
Cada Operation y cada PlanTemplate tiene su smoke test integración. Sin verde no se mergea.
Trace & Artifact
  • trace.query@1.0.0
  • artifact.list_recent@1.0.0
  • artifact.publish@1.0.0
Claim memory
  • claim.recall_decisions@1.0.0
  • claim.recall_voice@1.0.0
Text composition
  • text.compose_narrative@2.0.0
  • text.compose_brief@1.0.0
Evaluation & gates
  • evaluator.run@1.0.0
  • human_gate.approve@1.0.0
Sales / prospecting
  • prospect.search@1.0.0
  • prospect.score_batch@1.0.0
URL ingestion
  • url.fetch_transcript@1.0.0
Video pipeline
  • video.script_draft@1.0.0
  • video.compose@1.0.0
Voice
  • voice.tts@1.0.0
07
Capítulo siete · Los cuatro Plan Templates

Cuatro DAGs productivos
cada uno con su propio agente

Cada PlanTemplate es un DAG topo-sorteado que se compila desde un Intent. Los colores marcan el tipo de Step: amber LLM, cian evaluator, verde publish, rosa human-gate, gris system.
system
LLM
evaluator
publish
human-gate
standup-digest-v1
$0.0222 / run
Karina · PMO Lead · 8 steps · 0 nuevas Ops
s1 trace.query s2 artifact.list s3 claim.dec. s4 claim.voice s5 · LLM compose s6 evaluator s7 publish s8 human-gate → ✓
lead-research-v1
$0.0143 / run
Alexa · Sales · 8 steps · 2 nuevas Ops
s1 claim.dec. s2 claim.voice s3 prospect.search s4 · LLM score_batch s5 · LLM compose s6 evaluator s7 publish s8 human-gate
brief-synthesis-v1
$0.0147 / run
Sofia · Content · 7 steps · 1 nueva Op
s1 claim.dec. s2 claim.voice s3 artifact.list s4 · LLM compose_brief s5 evaluator s6 publish s7 human-gate
video-render-v1
$0.0124 / run
Mae + Sofia + Marcus · 9 steps · 4 nuevas Ops · TTS/compose aún mock
s1 url.transcript s2 claim.voice s3 claim.dec. s4 · LLM script_draft s5 voice.tts s6 video.compose s7 evaluator s8 publish s9 human-gate
08
Capítulo ocho · Human-gate suspension

El gate durable
donde la persona es autoridad final

Inngest step.waitForEvent pausa el Plan por hasta 24 horas. Cuando llega el evento, valida que el artifact_id matchea y resume. Si no llega, aplica fallback. Cada decisión humana se materializa como Claim tipado y consultable.
Executor
Inngest
API
Roberto
step.run(s7 human_gate)
step.waitForEvent('approval.received', if: async.data.artifact_id == X)
trace.status → awaiting_human · intent.status → awaiting_human
— flujo suspendido hasta 24 horas —
POST /api/approvals { artifact_id, decision: approve, comment }
inngest.send({ name: 'approval.received', data: { artifact_id, decision, ... } })
match async.data.artifact_id → resume step
artifact.status → approved · emit 5 Claims · trace.verdict → pass

Bug crítico aprendido: el match en step.waitForEvent debe usar async.data.X, no event.data.X. event referencia el trigger original (plan.compiled) — usarlo ahí evalúa al tiempo de la suspension, no del evento futuro, y matchea con null. async.data referencia el evento que se está esperando. Sin esto, todos los gates se quedan colgados indefinidamente.

Lo que esto desbloquea: el humano puede aprobar/rechazar/agregar comment, y la decisión queda como Claim tipado consultable por futuros workflows. La próxima vez que armemos un brief sobre el mismo topic, claim.recall_decisions ya tiene "este angle ganó" como contexto. Esto es el efecto compuesto del substrato — no es retrieval, es construcción de memoria estructurada.

09
Capítulo nueve · Smoke test con LLM real

Cuatro templates activados
con Sonnet 4.5 verdadero

Wireamos ANTHROPIC_API_KEY + OPENAI_API_KEY a apps/api/.env, restart systemd, y disparamos un Intent por cada template. Los cuatro alcanzaron awaiting_human con outputs reales. Costo total para los cuatro runs: seis centavos.
standup-digest
$0.0222
content-brief
$0.0147
lead-list
$0.0143
video-reel
$0.0124
Total · 4 templates end-to-end
$0.064
standup-digest · narrative real
"Shipped hoy: video reel 9:16 listo para Fase 1, brief LinkedIn substrato vs RAG aprobado, lead list ICP corrió. En cola hay 5 digests sin resolver desde las 16:32. Mi recomendación es aprobar o rechazar los pendientes antes de cerrar el día."
content-brief · angle generado
"RAG te da respuestas parecidas. Un grafo de claims tipados te da respuestas defendibles. Cuando tu negocio depende de que la IA no invente, la arquitectura importa más que el prompt."
video-reel · script real, hook
"¿Cansado de que ChatGPT te invente respuestas que después no sirven para nada? El problema no es que los agentes sean malos. Es que sus salidas se pierden. Nada se acumula."
lead-list · prospect score con rationale
"Sofía Ramírez (Helix Comms, Founder & CEO). Fit 0.75. Beta testing 3 LLM tools señala experimentación activa con IA. Interés público en marketplaces de skills se alinea con la propuesta."

Lo no trivial: Sonnet razonó sobre el propio backlog del workspace. El narrative de standup-digest mencionó textualmente cuántos digests anteriores quedaron queued y awaiting_human, porque trace.query + artifact.list_recent + claim.recall le feedearon esos datos. La cadena retrieval → composer está validada end-to-end con datos reales del substrato.

10
Capítulo diez · El ciclo cerrado

Aprobamos el brief
y nacieron cinco Claims

El último paso de la sesión fue cerrar el ciclo del content-brief: POST /api/approvals con decision approve y un comment. El gate se reactivó, el artifact pasó a approved, y el substrato materializó cinco Claims tipados que viven para siempre como contexto consultable.
Artifact
Brief LinkedIn
"Substrato vs RAG"
approved
approvedBy →
human:roberto
approvalComment →
"angle es exactamente el frame que quiero. Hook 2 gana sobre los otros 3"
hasKind →
doc
hasStatus →
pending_review (antes de aprobar)
producedByOp →
artifact.publish@1.0.0

Este es el momento donde el substrato deja de ser teoría y empieza a comportarse como capital. La próxima vez que armemos un brief sobre el mismo topic, claim.recall_decisions va a recuperar "Hook 2 ganó sobre los otros 3" como contexto del composer. Sonnet no necesita recordarlo — el grafo se lo entrega. Eso es lo que distingue un substrato de un RAG: no busca documentos parecidos, sirve afirmaciones tipadas con provenance.

Después de una sola sesión, el workspace de Roberto tiene cuatro PlanTemplates productivos, dieciséis Operations atómicas, sesenta y pico de Claims acumulados como contexto compuesto, y un costo real de operación de aproximadamente dos centavos por workflow ejecutado. La pieza importante no es eso. La pieza importante es que cada uno de esos Claims va a estar acá mañana, y dentro de un año, alimentando los próximos workflows que armemos.