Español: es/architecture.md. This document reflects the current implementation (through the sandbox/security and agent-catalog work).
Monorepo layout:
apps/web— Next.js panel (Explorer, Graph, Knowledge, Wiki, Docs, Vectors, Costs, Cookbook, Hub, Memory, Decisions, Workflow, Terminal, Agents, Lessons, Quality, Review, Skills) +/login+ dashboard IDEsapps/api— NestJS REST API (+ Hub, Cookbook, Observations SSE, Better Auth at/api/auth/*,POST /api/auth/api-token,GET /api/health/ides)apps/worker— BullMQ jobs + MCP HTTP mirror (:37700, JWT onPOST /api/tools/*and hooks) + cronsapps/mcp-server— MCP stdio server (16 search/timeline + 9 get + 6 feedback tools)apps/mcp-proxy— HTTP router local worker vs remote VPS MCP (MCP_PROXY_ROUTES, TTL cache for search tools)apps/observatory— static public aggregates siteapps/yaggo-brain-cli—update,contrib,install,doctor,wrapapps/sandbox-runner— CLI entry for sandbox commandsinfra/vectors-worker— Python UMAP + HDBSCAN (:37800)infra/ragas-worker— Python RAG faithfulness (:37801)infra/docling-worker— Python PDF parse (:37802, Docling with pymupdf fallback)packages/*— shared libraries (hub,observatory-data,model-router/benchmarks,auth,privacy,sandbox,memory,code-intel)
- Better Auth (
packages/auth): email/password, bearer tokens, scopes; mounted at/api/auth/* - Auth guard (API): global guard; skip
/health,/api/auth/*;AUTH_DISABLED=trueby default for local dev - RLS: Postgres policies on workspace-scoped tables via
app.workspace_idGUC (withDbContext) - Privacy:
<private>redaction triggers + read-time filter; redacted/private chunks excluded from vector snapshots - Sandbox: Docker ephemeral runner (
infra/sandbox/), seccomp profile, read-only repo bind mount, command guard + audit,SANDBOX_MODE=stubstill supported - Audit:
GET /api/projects/:id/audit; blocked commands →audit_log.action = command.blocked_dangerous - Workspace policy:
allow_network_in_sandbox(default false); bridge only withrequiresNetwork+ audit - Agent permissions:
can_execute_commandsenforced on sandbox exec whenagentIdprovided - CI:
.github/workflows/security.yml(gitleaks + license-checker onpackages/)
- Web → API
POST /api/projects/:id/ask model-routerselects tier/model (optionalROUTER_USE_BENCHMARKS=true→model_profiles)raghybrid retrieval: pgvector chunks + PageIndex tree scoring (PAGE_INDEX_ENABLED=true)- Optional LiteLLM answer;
cost-enginerecordsmodel_calls
- Upload PDF → worker
ingest-document - If
DOCLING_ENABLED=true, POST todocling-worker:37802/parse(Docling or pymupdf fallback) indexDocumentChunks+document_treesPageIndex tree persisted
- Local Letta-style blocks in
memory_blocks+memory_blocks_index(no external Letta service) - MCP
update_memory_blockwrites block value;memory_getreturns full content - Default seeds:
human,persona,project_contexton first update
- Table
decisionsfor architectural decisions - Worker job
ingest-adr-decisionsimportsdocs/adr/*.mdidempotently bysource_path
- CLI
yaggo-brain contrib --lesson-id=...→POST /api/hub/contrib - API enqueues
hub-process-submissionjob @yaggo-brain/hubgeneralizes lesson, runs eval gates, writeshub_publications+packages/hub/seed/community-lessons.json- Web Hub tab lists
hub_submissionsstatus
- Seed
model_profilesfrompackages/model-router/benchmarks/seed.jsonon migrate GET /api/cookbook/recommendationsusesdetectHardware()stub + profiles- Worker
ingest-public-benchmarksproposes diff (no overwrite)
@yaggo-brain/observatory-dataexports anonymized JSON (k-anonymity ≥ 5)- Worker weekly cron
export-observatory-snapshot→apps/observatory/public/data/snapshot.json pnpm observatory:build→ static site inapps/observatory/dist
GET /api/observations+ SSE/api/observations/stream- MCP
record_observationpersists toobservations - Memory tab live stream; Quality metrics (lesson rates, skill pass-rates); A/B compare ask
GET /api/projects/:id/vectors/status
- Knowledge — aggregated graph (wiki, lessons, decisions, documents) via
GET .../knowledge/graph - Decisions — ADR/decision timeline + Import ADRs job
- Workflow — editable React Flow graph stored in
workflows.definition - Terminal — xterm + one-shot sandbox exec (
POST .../sandbox/exec)
- UI detects
type:uuidpatterns in answers, observations, lessons (CitationLink) - Click opens
CitationDrawer→POST /api/citations/resolve→resolveGetByCitedIds(MCP layer 3) - Client-side cache in
use-citation-resolver
- Split layout: observations SSE + memory blocks editor (
PATCH .../memory/blocks/:id) - 3-layer search:
GET .../memory/search(all sources orlayer=blocks) + drawer for get layer - Compress now stub (session.end integration pending)
GET/POST /api/projects/:id/decisions,POST .../decisions/ingest-adrsGET/PATCH /api/projects/:id/memory/blocks,GET .../memory/searchGET/PUT /api/projects/:id/workflows/defaultPOST /api/citations/resolve
- Terminal or API →
POST /api/projects/:id/sandbox/execwith optionalagentId guardCommand(regex + chained segments) → on block:recordAudit+ 400runInSandbox→ Docker with seccomp, cap-drop, read-only rootfs, optional-v repo:/workspace:ro- Settings tab →
GET .../auditlast 50 security events
Build sandbox image: pnpm sandbox:build
- Chunks with embeddings in
chunks(pgvector) - Worker job
build-vector-snapshotPOSTs tovectors-worker - Snapshot stored in
vector_snapshots - Web tab Vectors renders UMAP scatter (canvas MVP)
- Catalog: 14 agents in
packages/agent-runtime/src/agents/*.yaml(Zod + permission matrix) - Readonly runners: architect, documentation, security-agent, reviewer-agent, research-agent
- QA write: generates diff + runs
sandboxcommand (requirescan_execute_commands) - Dispatch:
runAgentchecks scope, budget (BUDGET_EXCEEDED), andagent.beforehooks - Hooks:
bootstrapAgentHooks()on API and worker startup; per-agentsubscribed_hooks - MCP:
get_agentslists catalog;invokeToolfilters byallowed_toolswhenagent_idset - Approve review: worker job
apply-review-patchcreates git branch + commit - Reject review: creates project lesson
proposed+ enqueues quality review - Agent Board: kanban by run status/review + catalog filters (project/workspace)
- Trigger events: failed agent eval, eval suite below threshold, review reject, MCP
request_reflexion, session end - API/worker enqueues
quality-review(cooldown: max 5/workspace/24h viaaudit_log) @yaggo-brain/quality-agentLangGraph: evaluate → reflect → record lesson → pattern check → optional autoresearch- Lessons promote
proposed → acceptedat 3 distinctevidenceRuns - Optional
quality_findingsemitted; panelGET .../quality/findings
packages/hooksdispatchessession.start|end,tool.before|after,prompt.compose- Worker
POST /api/hooks/:eventreturns 202 and runs handlers async - Cursor install copies hook scripts to
.cursor/hooks/yaggo-brain/and projecthooks.json session.end: compress observations →session_summaries+ enqueue quality review
- Datasets in
packages/evals/datasets/*.jsonl pnpm evalruns 7 suites (incl.uplift-canonical[D-69],rag-faithfulness-canonical)pnpm --filter @yaggo-brain/evals ci-gateblocks >5% regression oncode-review-canonical
- Catalog under
packages/skills/catalog/{skillId}/ - Versions in
versions/{semver}/SKILL.md - ADRs auto-written to
docs/adr/on improvement - Cron:
0 3 * * *via BullMQ repeatable job
- Layer 1
*_search: compact{ hits: [{id, title, citedId}], citedIds } - Layer 2
*_timeline: chronological context around an anchor - Layer 3
*_get: full content viaGetResponse.items[] - Extra:
get_vector_neighbors(chunk_id)for pgvector similarity code_searchvia@yaggo-brain/code-intel(file_nodes + AGE graph)- Feedback includes
update_memory_block
yaggo-brain installdetects Cursor / Claude Code / Windsurf and delegates to native paths- Hooks POST to worker
POST /api/hooks/:event(session.start|end,prompt.compose,tool.after) .yaggo-brain/ide-status.jsonupdated by hooks; APIGET /api/health/idesmerges DB + filemcp-proxyroutes tool calls perprojectId(localworker vsremoteVPS)POST /api/auth/api-tokenissues scoped bearer tokens for MCP/hooks- Plugin manifests:
.cursor-plugin/,.claude-plugin/