Capadonna-Labs/DuckClaw

Multi-agent platform with a zero-trust posture, DuckDB as the analytical state store, and a singleton DB-Writer path for ACID mutations.

4

stars

505

commits

Python

primary language

Sep 6, 2026

updated

README

DuckClaw

Plataforma multi-agente DB-first: DuckDB es el control plane (workers, políticas, proyectos, runtime, RAG, conectores MCP). El API Gateway y los agentes leen en read_only=True; las mutaciones van por comandos tipados → cola Redis → DB-Writer (singleton ACID).

Core genérico LangGraph/LangChain — sin verticales hardcodeadas en Python. Multi-tenant · Windows / Linux / macOS · Docs de arquitectura en docs/architecture/.


Arquitectura DB-first (canonical)

Fuente de verdad: docs/architecture/system_overview.md · límites: GATEWAY_DB_WRITER_BOUNDARIES.md

Una bóveda, un schema

ConceptoValor canónico
Hub DuckDBdb/private/default/duckclaw.duckdb
EnvDUCKCLAW_GATEWAY_DB_PATH=db/private/default/duckclaw.duckdb
Schema SQLSolo main (+ schemas internos DuckDB: information_schema, pg_catalog)
Migracionespackages/shared/src/duckclaw/schema_migrations.py33 versiones (uv run duckclaw-migrate)
Bootstrapbootstrap_core.py — DDL idempotente sin ALTER TABLE ADD COLUMN

Tablas de homeostasis/meditate viven en main.homeostasis_targets y main.meditate_runs (migración M033). El paquete Python harness_core/ es código Meditate/Heartbeat — no es un schema DuckDB separado.

No usar: db/duckclaw.duckdb (legacy en raíz), db/system.duckdb, db/telegram.duckdb, bóvedas axis.duckdb (legacy). Fresh start: uv run duckops db fresh-dev. Migrar legacy: uv run duckops db migrate-legacy-axis.

Procesos y quién escribe

flowchart TB
  subgraph Clients
    ADM[duckclaw-admin BFF :3001]
    HTTP[Clientes / Playground]
  end

  subgraph Gateway["DuckClaw-Gateway :8000 — read_only"]
    API[FastAPI · admin_domains/* · chat]
  end

  subgraph Compute["Agents — read_only"]
    MGR[Manager · routing policies/capabilities]
    WRK[Workers · tools · MCP]
  end

  subgraph Async["Redis"]
    QW[(duckdb_write_queue)]
    QK[(duckclaw:knowledge_sync_jobs)]
  end

  subgraph Writers["Singleton writers"]
    DW[DB-Writer — mutaciones ACID hub/vaults]
    KI[Knowledge-Indexer — ingest RAG carpetas]
  end

  subgraph Hub["duckclaw.duckdb — control plane"]
    DB[(main.* · admin_* · knowledge · policies)]
  end

  ADM --> API
  HTTP --> API
  API --> MGR --> WRK
  API & WRK & KI -->|"SELECT read_only"| DB
  API -->|"Upsert*Command"| QW
  KI -->|"Upsert*Command docs/chunks"| QW
  API -->|"enqueue folder_ingest"| QK
  QW --> DW -->|"COMMIT"| DB
  QK --> KI
Proceso PM2RolEscribe DuckDB
DuckClaw-GatewayHTTP, admin API, chat, encola comandosread_only=True
DuckClaw-DB-WriterConsume duckdb_write_queue✅ único writer habitual
DuckClaw-Knowledge-IndexerConsume duckclaw:knowledge_sync_jobs, escanea vaults Obsidian❌ encola writes al DB-Writer
DuckClaw-HeartbeatTicks proactivos / homeostasis❌ encola deltas
duckclaw-adminNext.js BFF → gateway (secretos solo server-side)

Límites de proceso: GATEWAY_PROCESS_BOUNDARIES.md · GATEWAY_DB_WRITER_BOUNDARIES.md

Reglas que no negociar

ReglaDetalle
Quién escribeSolo DB-Writer en rutas normales. Gateway/agentes/indexer: read_only=True.
Cómo mutarduckclaw.write_commands (Pydantic) → enqueue_write_command / enqueue_typed_command → DB-Writer → write_handlers/*.
Dónde vive la verdadTablas main.admin_*, prompt_policy_registry, knowledge, grants — no Markdown runtime ni if worker_id == "…".
VerticalesQuant, Finanz, PQRSD, Leila/Telegram bot legacy, etc. fuera del core (extensiones opt-in).
TelegramIntegración opt-in; no arranca con el stack core. Ver Integraciones en admin.
Airbag framework4 policies con fallback en código (FRAMEWORK_POLICY_PACK); el resto exige fila en DB.
RAG carpetasGateway solo encola; ingest pesado en DuckClaw-Knowledge-Indexer + progreso Redis duckclaw:knowledge_sync_status:{job_id}.

Contrato cola/ledger: DB_WRITER_CONTRACT.md

Control plane en el hub

DominioTablas / owners
Identidad adminadmin_console_users, admin_user_profiles, admin_user_agents
Workersadmin_worker_catalog, contexts, capabilities, skills, assignments
Políticasprompt_policy_registry, worker_prompt_bindings, worker_runtime_policies
Proyectosadmin_projects, admin_project_agents, members
Runtimeadmin_runtime_settings (tenant, chat, gateway, LLM, secrets)
RAGadmin_knowledge_sources, documents, chunks — ver docs/architecture/tri_cameral_memory.md
Memoria semánticamain.semantic_memory (context injection / VLM — distinto del RAG admin)
Homeostasismain.homeostasis_targets, main.meditate_runs
MCPadmin_mcp_connectors, admin_worker_mcp_grants
Kanban / informesadmin_kanban_*, admin_report_*
HITLcode_decisions, agent_uncertainty_log

Bóvedas por usuario/tenant (Memoria Triple SQL+PGQ+VSS): MULTI_VAULT_SYSTEM.md — opcional; el hub canónico basta para admin + playground.

Admin API

Rutas bajo /api/v1/adminservices/api-gateway/routers/admin_domains/* (un módulo por dominio). Mutaciones = comando tipado → Redis → DB-Writer. Código nuevo no va a god-routers.


Inicio rápido

# macOS / Linux — prereqs + migrate + PM2 + admin
bash scripts/bootstrap/up.sh
# o
uv run duckops up

Variables mínimas en .env:

DUCKCLAW_GATEWAY_DB_PATH=db/private/default/duckclaw.duckdb
DUCKCLAW_GATEWAY_URL=http://127.0.0.1:8000
REDIS_URL=redis://localhost:6379/0
DUCKCLAW_ADMIN_API_KEY=...
DUCKCLAW_ADMIN_EMAIL=...
DUCKCLAW_ADMIN_PASSWORD=...

Diagnóstico: uv run duckops doctor · Migraciones: uv run duckclaw-migrate · Fresh vault: uv run duckops db fresh-dev

Guía: docs/GETTING_STARTED.md · CLI: uv run duckops --help


Admin UI

pnpm admin:install   # primera vez
pnpm admin:dev       # http://localhost:3001
pnpm dev:local       # gateway + db-writer + admin

Stack PM2: uv run duckops stack deploy (Gateway, DB-Writer, Knowledge-Indexer, Heartbeat).

Admin: apps/duckclaw-admin/README.md


Estructura del repo

duckclaw/
├── packages/
│   ├── shared/     # schema_migrations, write_commands, admin_* readers, knowledge_sync_queue
│   ├── agents/     # manager, workers, forge/rag, commands, MCP bridge
│   ├── core/       # bindings C++ / performance
│   └── duckops/    # CLI: up, init, doctor, stack deploy
├── services/
│   ├── api-gateway/       # FastAPI · admin_domains/* · chat
│   ├── db-writer/         # consumidor singleton duckdb_write_queue
│   ├── knowledge-indexer/   # consumidor duckclaw:knowledge_sync_jobs
│   └── heartbeat/         # ticks proactivos
├── apps/duckclaw-admin/   # Next.js BFF
├── harness_core/          # Python Meditate/homeostasis (tablas en main.*)
├── docs/architecture/     # arquitectura, DuckDB, límites de servicios
└── tests/                 # guardrails DB-first

Imports Python (puntos de entrada)

from duckclaw import DuckClaw
from duckclaw.gateway_db import get_gateway_db_path
from duckclaw.schema_migrations import run_pending_migrations, verify_migration_integrity
from duckclaw.db_write_queue import enqueue_typed_command
from duckclaw.write_commands import UpsertWorkerCommand, CreateKnowledgeSourceCommand
from duckclaw.workers import WorkerFactory, list_workers
from duckclaw.prompt_policies import PromptPolicyResolver
from duckclaw.forge.rag import build_knowledge_context, search_knowledge
from duckclaw.knowledge_sync_queue import enqueue_knowledge_sync_job, get_job_status

Tests

uv run pytest tests/ -m "not integration" \
  --ignore tests/run_singleton_writer_pipeline.py \
  --ignore tests/deprecated

Guardrails: test_forge_legacy_cleanup.py · test_db_first_guardrails_static.py · test_schema_migrations.py · test_knowledge_sync_queue.py


Documentación

QuéDónde
Índice docsdocs/README.md
Overview / límitesdocs/architecture/
Contratos API / writerdocs/api/

Built by IoTCoreLabs

Contributors

elsam8424

269 commits

Arevalojj2020

214 commits

cursoragent

11 commits

Capadonna-Labs/DuckClaw

Multi-agent platform with a zero-trust posture, DuckDB as the analytical state store, and a singleton DB-Writer path for ACID mutations.

4

stars

505

commits

Python

primary language

Sep 6, 2026

updated

README

DuckClaw

Plataforma multi-agente DB-first: DuckDB es el control plane (workers, políticas, proyectos, runtime, RAG, conectores MCP). El API Gateway y los agentes leen en read_only=True; las mutaciones van por comandos tipados → cola Redis → DB-Writer (singleton ACID).

Core genérico LangGraph/LangChain — sin verticales hardcodeadas en Python. Multi-tenant · Windows / Linux / macOS · Docs de arquitectura en docs/architecture/.


Arquitectura DB-first (canonical)

Fuente de verdad: docs/architecture/system_overview.md · límites: GATEWAY_DB_WRITER_BOUNDARIES.md

Una bóveda, un schema

ConceptoValor canónico
Hub DuckDBdb/private/default/duckclaw.duckdb
EnvDUCKCLAW_GATEWAY_DB_PATH=db/private/default/duckclaw.duckdb
Schema SQLSolo main (+ schemas internos DuckDB: information_schema, pg_catalog)
Migracionespackages/shared/src/duckclaw/schema_migrations.py33 versiones (uv run duckclaw-migrate)
Bootstrapbootstrap_core.py — DDL idempotente sin ALTER TABLE ADD COLUMN

Tablas de homeostasis/meditate viven en main.homeostasis_targets y main.meditate_runs (migración M033). El paquete Python harness_core/ es código Meditate/Heartbeat — no es un schema DuckDB separado.

No usar: db/duckclaw.duckdb (legacy en raíz), db/system.duckdb, db/telegram.duckdb, bóvedas axis.duckdb (legacy). Fresh start: uv run duckops db fresh-dev. Migrar legacy: uv run duckops db migrate-legacy-axis.

Procesos y quién escribe

flowchart TB
  subgraph Clients
    ADM[duckclaw-admin BFF :3001]
    HTTP[Clientes / Playground]
  end

  subgraph Gateway["DuckClaw-Gateway :8000 — read_only"]
    API[FastAPI · admin_domains/* · chat]
  end

  subgraph Compute["Agents — read_only"]
    MGR[Manager · routing policies/capabilities]
    WRK[Workers · tools · MCP]
  end

  subgraph Async["Redis"]
    QW[(duckdb_write_queue)]
    QK[(duckclaw:knowledge_sync_jobs)]
  end

  subgraph Writers["Singleton writers"]
    DW[DB-Writer — mutaciones ACID hub/vaults]
    KI[Knowledge-Indexer — ingest RAG carpetas]
  end

  subgraph Hub["duckclaw.duckdb — control plane"]
    DB[(main.* · admin_* · knowledge · policies)]
  end

  ADM --> API
  HTTP --> API
  API --> MGR --> WRK
  API & WRK & KI -->|"SELECT read_only"| DB
  API -->|"Upsert*Command"| QW
  KI -->|"Upsert*Command docs/chunks"| QW
  API -->|"enqueue folder_ingest"| QK
  QW --> DW -->|"COMMIT"| DB
  QK --> KI
Proceso PM2RolEscribe DuckDB
DuckClaw-GatewayHTTP, admin API, chat, encola comandosread_only=True
DuckClaw-DB-WriterConsume duckdb_write_queue✅ único writer habitual
DuckClaw-Knowledge-IndexerConsume duckclaw:knowledge_sync_jobs, escanea vaults Obsidian❌ encola writes al DB-Writer
DuckClaw-HeartbeatTicks proactivos / homeostasis❌ encola deltas
duckclaw-adminNext.js BFF → gateway (secretos solo server-side)

Límites de proceso: GATEWAY_PROCESS_BOUNDARIES.md · GATEWAY_DB_WRITER_BOUNDARIES.md

Reglas que no negociar

ReglaDetalle
Quién escribeSolo DB-Writer en rutas normales. Gateway/agentes/indexer: read_only=True.
Cómo mutarduckclaw.write_commands (Pydantic) → enqueue_write_command / enqueue_typed_command → DB-Writer → write_handlers/*.
Dónde vive la verdadTablas main.admin_*, prompt_policy_registry, knowledge, grants — no Markdown runtime ni if worker_id == "…".
VerticalesQuant, Finanz, PQRSD, Leila/Telegram bot legacy, etc. fuera del core (extensiones opt-in).
TelegramIntegración opt-in; no arranca con el stack core. Ver Integraciones en admin.
Airbag framework4 policies con fallback en código (FRAMEWORK_POLICY_PACK); el resto exige fila en DB.
RAG carpetasGateway solo encola; ingest pesado en DuckClaw-Knowledge-Indexer + progreso Redis duckclaw:knowledge_sync_status:{job_id}.

Contrato cola/ledger: DB_WRITER_CONTRACT.md

Control plane en el hub

DominioTablas / owners
Identidad adminadmin_console_users, admin_user_profiles, admin_user_agents
Workersadmin_worker_catalog, contexts, capabilities, skills, assignments
Políticasprompt_policy_registry, worker_prompt_bindings, worker_runtime_policies
Proyectosadmin_projects, admin_project_agents, members
Runtimeadmin_runtime_settings (tenant, chat, gateway, LLM, secrets)
RAGadmin_knowledge_sources, documents, chunks — ver docs/architecture/tri_cameral_memory.md
Memoria semánticamain.semantic_memory (context injection / VLM — distinto del RAG admin)
Homeostasismain.homeostasis_targets, main.meditate_runs
MCPadmin_mcp_connectors, admin_worker_mcp_grants
Kanban / informesadmin_kanban_*, admin_report_*
HITLcode_decisions, agent_uncertainty_log

Bóvedas por usuario/tenant (Memoria Triple SQL+PGQ+VSS): MULTI_VAULT_SYSTEM.md — opcional; el hub canónico basta para admin + playground.

Admin API

Rutas bajo /api/v1/adminservices/api-gateway/routers/admin_domains/* (un módulo por dominio). Mutaciones = comando tipado → Redis → DB-Writer. Código nuevo no va a god-routers.


Inicio rápido

# macOS / Linux — prereqs + migrate + PM2 + admin
bash scripts/bootstrap/up.sh
# o
uv run duckops up

Variables mínimas en .env:

DUCKCLAW_GATEWAY_DB_PATH=db/private/default/duckclaw.duckdb
DUCKCLAW_GATEWAY_URL=http://127.0.0.1:8000
REDIS_URL=redis://localhost:6379/0
DUCKCLAW_ADMIN_API_KEY=...
DUCKCLAW_ADMIN_EMAIL=...
DUCKCLAW_ADMIN_PASSWORD=...

Diagnóstico: uv run duckops doctor · Migraciones: uv run duckclaw-migrate · Fresh vault: uv run duckops db fresh-dev

Guía: docs/GETTING_STARTED.md · CLI: uv run duckops --help


Admin UI

pnpm admin:install   # primera vez
pnpm admin:dev       # http://localhost:3001
pnpm dev:local       # gateway + db-writer + admin

Stack PM2: uv run duckops stack deploy (Gateway, DB-Writer, Knowledge-Indexer, Heartbeat).

Admin: apps/duckclaw-admin/README.md


Estructura del repo

duckclaw/
├── packages/
│   ├── shared/     # schema_migrations, write_commands, admin_* readers, knowledge_sync_queue
│   ├── agents/     # manager, workers, forge/rag, commands, MCP bridge
│   ├── core/       # bindings C++ / performance
│   └── duckops/    # CLI: up, init, doctor, stack deploy
├── services/
│   ├── api-gateway/       # FastAPI · admin_domains/* · chat
│   ├── db-writer/         # consumidor singleton duckdb_write_queue
│   ├── knowledge-indexer/   # consumidor duckclaw:knowledge_sync_jobs
│   └── heartbeat/         # ticks proactivos
├── apps/duckclaw-admin/   # Next.js BFF
├── harness_core/          # Python Meditate/homeostasis (tablas en main.*)
├── docs/architecture/     # arquitectura, DuckDB, límites de servicios
└── tests/                 # guardrails DB-first

Imports Python (puntos de entrada)

from duckclaw import DuckClaw
from duckclaw.gateway_db import get_gateway_db_path
from duckclaw.schema_migrations import run_pending_migrations, verify_migration_integrity
from duckclaw.db_write_queue import enqueue_typed_command
from duckclaw.write_commands import UpsertWorkerCommand, CreateKnowledgeSourceCommand
from duckclaw.workers import WorkerFactory, list_workers
from duckclaw.prompt_policies import PromptPolicyResolver
from duckclaw.forge.rag import build_knowledge_context, search_knowledge
from duckclaw.knowledge_sync_queue import enqueue_knowledge_sync_job, get_job_status

Tests

uv run pytest tests/ -m "not integration" \
  --ignore tests/run_singleton_writer_pipeline.py \
  --ignore tests/deprecated

Guardrails: test_forge_legacy_cleanup.py · test_db_first_guardrails_static.py · test_schema_migrations.py · test_knowledge_sync_queue.py


Documentación

QuéDónde
Índice docsdocs/README.md
Overview / límitesdocs/architecture/
Contratos API / writerdocs/api/

Built by IoTCoreLabs

Contributors

elsam8424

269 commits

Arevalojj2020

214 commits

cursoragent

11 commits

Languages

Python

77.0%

TypeScript

21.1%