Proyecto independiente No afiliado, patrocinado ni avalado por la Watch Tower Bible and Tract Society o Jehovah's Witnesses.
jw-agent-toolkit
EN

Guía

Second Brain (Fase 49)

Karpathy-style compiler + GraphRAG sobre el toolkit. Foco exclusivo del proyecto: publicaciones de los testigos de Jehová. TJ es el único dominio que el toolkit empaqueta y mantiene.

Foco del proyecto (lectura obligatoria)

jw-agent-toolkit es 100% para publicaciones JW (wol.jw.org, JWPUB, EPUBs de la organización, Watchtower, Despertad, libros de estudio, etc.). Eso no cambia con Fase 49.

Lo que Fase 49 sí hace es separar dos cosas que antes estaban mezcladas:

  1. El runtime (compiler, grafo, wiki, lint) — lógica que en sí misma no contiene NodeType ni EdgeType específicos de TJ.
  2. El dominio TJ — las 6 NodeTypes (Verse, Topic, Publication, Concept, Person, Place) y 6 EdgeTypes (CITED_IN, MENTIONS, EXPANDS, CROSS_REFERENCES, CONTRADICTS, ABOUT) que sí codifican la estructura de la literatura JW.

Esa separación es una decisión de ingeniería, no un cambio de scope.

TL;DR

# Inicializar (TJ por defecto). Crea raw/, vault/, graph/ + config.toml + CLAUDE.md.
jw brain init --domain tj --brain ~/jw-second-brain

# Tirar archivos en raw/inbox/ (md, txt, html, epub, jwpub, pdf-future...)
cp ~/Downloads/notas-*.md ~/jw-second-brain/raw/inbox/

# Dry-run primero (recomendado en el primer compile)
jw brain compile --brain ~/jw-second-brain --dry-run

# Compile real
jw brain compile --brain ~/jw-second-brain

# Query (Karpathy-first → graph → vector)
jw brain query "Qué versículos se conectan a través de Eclesiastés 9:5?" --brain ~/jw-second-brain

# Lint
jw brain lint --brain ~/jw-second-brain

# Snapshot
jw brain snapshot --brain ~/jw-second-brain --label pre-experiment

# Multi-tenant
jw brain list                                    # registry global
jw brain status --brain my-tj-brain              # alias del registry
JW_BRAIN_HOME=~/jw-second-brain jw brain status  # env var

El patrón

Tres capas, una operación recurrente:

raw/ (usuario tira datos)  →  Compiler agéntico  →  graph + wiki
                              "sale a pasear"
  • raw/inbox/: cualquier formato cae aquí. El parser_router enruta por mime-type. Tras procesar, el archivo se mueve a raw/processed/ (audit trail).
  • vault/Second-Brain/: el agente es dueño absoluto. Páginas Markdown autogeneradas con frontmatter YAML; cualquier página con human_edited: true queda inmune a futuras compilaciones.
  • graph/backend.duckdb: la capa GraphRAG persistente. Nodos: Verse, Topic, Publication, Concept, Person, Place. Aristas: CITED_IN, MENTIONS, EXPANDS, CROSS_REFERENCES, CONTRADICTS, ABOUT.

Por qué grafo además de RAG vectorial

Para queries de multi-hop (“versículos en publicaciones que también citan X”), el grafo es estrictamente superior al vector. Benchmark canónico (Microsoft GraphRAG 2024 → 2026): queries con 3+ saltos pasan de ~16.7% accuracy en vector solo a 56-80% en grafo + vector híbrido.

Backends

BackendCuándoProsContras
duckdb (default)siempreembedded, cero deps externos, snapshot por tarballSQL recursivo limitado vs Cypher
neo4j (opt-in)corpus grande, queries Cypher complejastraversal pleno, ecosystem maduroproceso externo, opt-in via [neo4j] extra

Mismo GraphBackend Protocol — el código de aplicación no cambia entre uno y otro.

El fixture financial_brain_plugin — qué es y qué NO es

En packages/jw-brain/tests/fixtures/financial_brain_plugin/ hay un paquete Python pequeño que registra un FinanceBrainDomain con NodeTypes Transaction/Vendor/Category/TaxYear.

Aclaración obligatoria (porque la prosa anterior podía confundir):

  • ❌ NO es una funcionalidad del producto.
  • ❌ NO es algo que el toolkit ofrece a usuarios finales.
  • ❌ NO está en el roadmap.
  • ❌ NO se distribuye, no se publica en PyPI, no se instala en producción.
  • ✅ Es únicamente un test fixture que vive bajo tests/ y se carga solo durante el test que verifica el descubrimiento de plugins.

Para qué existe: probar que el runtime de F49 no tiene TJ hardcoded en sitios que deberían ser dominio-agnósticos (graph backend, wiki writer, compiler loop, query router, CLAUDE.md autogen). Sin un dominio distinto a TJ que sirva de “control”, esa garantía no se puede demostrar — el test test_domain_registry.py::test_plugin_domain_discovered_via_f41 falla si alguien introduce ese acoplamiento sin querer.

El proyecto sigue siendo 100% TJ. Si en algún momento quisieras usar el runtime para tu propio uso personal en otro dominio, técnicamente podrías porque la arquitectura lo permite — pero eso sería tu uso personal externo, no parte del scope del toolkit ni una promesa de soporte de mi parte.

Multi-tenant

Cada brain es independiente. El registry global en ~/.jw-brain/registry.toml mantiene el mapa alias → ruta absoluta. Auto-registro en cada jw brain init.

El caso TJ legítimo del multi-tenant es separar contextos de estudio: por ejemplo un brain para estudio personal y otro para preparación de reuniones, ambos con dominio tj pero distinto vault Obsidian y distinto corpus en raw/.

jw brain init --brain ~/jw-study-brain        # estudio personal
jw brain init --brain ~/jw-meeting-brain      # preparación de reuniones
jw brain list                                 # lista ambos
jw brain status --brain jw-study-brain        # alias resuelve a path

Cómo se integra con las fases previas

FaseCómo F49 la usa
F20 ObsidianEl wiki vive en <vault>/Second-Brain/ con write-safe contract idéntico (.obsidian/ marker + path traversal defense).
F39 NLI runtimelint.contradiction_finder corre NLI sobre pares de claims que comparten un Topic. Detecta contradicciones cross-publication.
F40 content-provenanceCada arista lleva content_hash + accessed_at + run_id + model_id + confidence.
F41 plugin SDKBrainDomain se descubre via jw_agent_toolkit.brain_domains entry-point group. TJ es builtin; cualquier otro es plugin.
F45 semantic-chunkingEl parser_router puede usar chunkers configurables al preparar texto para el extractor LLM.

CLI

ComandoQué hace
jw brain initCrea estructura, config.toml, CLAUDE.md autogenerado per dominio. Auto-registra alias.
jw brain compileLoop discover → parse → LLM extract → upsert grafo + escribir wiki + mover a processed/. --dry-run no muta.
jw brain queryRouter Karpathy-first: wiki sintetizada → graph traversal → vector fallback.
jw brain lintOrphan pages + (TODO) NLI cross-publication contradictions.
jw brain snapshotTarball del backend a <brain>/snapshots/.
jw brain statusStats del grafo, raw pending/processed.
jw brain listBrains del registry global.

MCP tools

ToolEquivalente CLI
second_brain_statusjw brain status
second_brain_compilejw brain compile
second_brain_queryjw brain query
second_brain_lintjw brain lint
second_brain_snapshotjw brain snapshot

Variables de entorno

VariableDefaultEfecto
JW_BRAIN_HOMEunsetPath absoluto a brain por defecto si no se pasa --brain
JW_BRAIN_BACKENDduckdbBackend default (duckdb o neo4j)
JW_GEN_PROVIDERfakeProvider LLM (fake, ollama, …). Default fake para mantener CLI sin red

Tests

.venv/bin/python -m pytest packages/jw-brain/tests/ -v

Editar esta página en docs/guias/second-brain.md