Files
agenticSystem/README.md
Jordan 264acc90b4 Add .gitignore, remove __pycache__ from tracking, and update MCP/orchestrator modules
- Add .gitignore to exclude .env, __pycache__, node_modules, and IDE files
- Remove all __pycache__ bytecode files from version control
- Add MCP config files (mcp.json, mcp.json.example)
- Add MCP manager, registry, and config modules
- Update routes, orchestrator engine, and agent base with latest changes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:47:26 +01:00

415 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Agentic Microservice
Microservicio de orquestación agéntica con context engineering avanzado, multi-agent orchestration, integración MCP, SSE streaming y knowledge base. Diseñado como backend para Acai Code.
## Arquitectura
```
Client → API (FastAPI) → Orchestrator → Subagents (planner/coder/collector/reviewer)
↓ ↓
Context Engine Model Adapter (Claude / OpenAI)
↓ ↓
Memory Store + KB MCP Client (stdio)
Redis (sessions, events, knowledge)
```
**Principios:**
- **Context over chat history** — el modelo recibe estado estructurado, nunca raw tool outputs
- **Knowledge filtering** — solo los docs relevantes al task entran en contexto (keyword scoring)
- **Compaction** — extracción de facts, eliminación de redundancia, prioridades por sección
- **Artifact summarization** — outputs de tools resumidos antes de entrar al contexto
- **Error recovery** — steps fallidos se saltan, timeout global, sesión nunca se queda en executing
- **Concurrency lock** — Redis SETNX impide ejecución simultánea en la misma sesión
## Quick Start
### Con Docker Compose
```bash
# 1. Configurar
cp .env.example .env
# Editar .env — al menos una API key (ANTHROPIC o OPENAI)
# 2. Levantar todo (Redis + microservicio)
docker compose up --build
# 3. Solo Redis (para desarrollo local)
docker compose up redis -d
```
### Desarrollo local
```bash
# 1. Redis
docker compose up redis -d
# 2. Dependencias
pip install -r requirements.txt
# 3. Configurar .env
AGENTIC_OPENAI_API_KEY=sk-...
AGENTIC_DEFAULT_MODEL_PROVIDER=openai
AGENTIC_DEFAULT_MODEL_ID=gpt-4o
AGENTIC_REDIS_PORT=6380
# 4. Arrancar
python3 -m uvicorn src.main:app --reload --port 8001
# 5. Dashboard en http://localhost:8001/dashboard/
```
### Cargar Knowledge Base
```bash
# Cargar docs desde el directorio docs/
curl -X POST http://localhost:8001/api/v1/knowledge/load \
-H "Content-Type: application/json" \
-d '{"docs_path": "docs"}'
```
## Dashboard
Interfaz web para testing integrada en el microservicio. Se accede en `/dashboard/`.
**Features:**
- Gestión de sesiones (crear, eliminar, seleccionar)
- Chat con envío sync (Send) o streaming (Stream)
- Event Log en tiempo real con filtros por categoría y export JSON
- Inspector de estado (task, plan, facts, constraints, timeline)
- Context Debug — muestra exactamente qué recibe cada agente (secciones, tokens, previews)
- Dark/light mode
- Responsive (3 columnas → 1 columna en móvil)
**Atajos de teclado:**
- `Enter` → Send
- `Ctrl+Enter` → Stream
- `Shift+Enter` → Nueva línea
## API Reference
Base URL: `/api/v1`
### Sesiones
```bash
# Crear sesión
curl -X POST http://localhost:8001/api/v1/sessions \
-H "Content-Type: application/json" \
-d '{
"project_profile": {"name": "mi-proyecto", "tech_stack": ["python", "twig"]},
"immutable_rules": ["Responde siempre en español", "Usa Tailwind CSS"],
"metadata": {}
}'
# → {"session_id": "abc123...", "status": "idle"}
# Obtener estado
curl http://localhost:8001/api/v1/sessions/{session_id}
# Eliminar
curl -X DELETE http://localhost:8001/api/v1/sessions/{session_id}
```
### Mensajes
```bash
# Sync — espera la respuesta completa
curl -X POST http://localhost:8001/api/v1/sessions/{session_id}/messages \
-H "Content-Type: application/json" \
-d '{"message": "Crea un módulo FAQ con acordeón"}'
# Streaming — retorna inmediatamente, resultados vía SSE
curl -X POST http://localhost:8001/api/v1/sessions/{session_id}/messages \
-H "Content-Type: application/json" \
-d '{"message": "Crea un módulo FAQ con acordeón", "stream": true}'
```
Respuesta sync:
```json
{
"session_id": "...",
"task_id": "...",
"content": "### Step 1\n...\n### Review\n...",
"steps_completed": 5,
"steps_failed": [],
"artifacts_count": 0,
"review": "...",
"status": "completed"
}
```
### SSE Streaming
```bash
curl -N http://localhost:8001/api/v1/sessions/{session_id}/stream
```
Tipos de evento:
| Evento | Cuándo |
|--------|--------|
| `session.created` | Sesión inicializada |
| `execution.started` | Pipeline arranca |
| `subagent.assigned` | Step ruteado a un agente |
| `agent.delta` | Chunk de texto del agente |
| `tool.started` | Herramienta MCP ejecutándose |
| `tool.completed` | Herramienta terminó |
| `execution.completed` | Task completado |
| `error` | Error en step, planning, o timeout |
### Knowledge Base
```bash
# Cargar docs desde directorio
curl -X POST http://localhost:8001/api/v1/knowledge/load \
-H "Content-Type: application/json" \
-d '{"docs_path": "docs"}'
# Cargar desde ruta absoluta
curl -X POST http://localhost:8001/api/v1/knowledge/load \
-H "Content-Type: application/json" \
-d '{"docs_path": "/ruta/a/mis/docs"}'
# Listar docs cargados
curl http://localhost:8001/api/v1/knowledge
# Eliminar un doc
curl -X DELETE http://localhost:8001/api/v1/knowledge/{doc_id}
```
Los docs se cargan como `*.md` del directorio. Se sobreescriben si ya existen. No requiere reinicio — la siguiente conversación usa los docs actualizados.
### Debug
```bash
# Historial de eventos (persistidos en Redis)
curl http://localhost:8001/api/v1/sessions/{session_id}/events
# Context debug — qué recibió cada agente
curl http://localhost:8001/api/v1/sessions/{session_id}/context-debug
# Health check
curl http://localhost:8001/health
```
## Context Engine
El componente más crítico del sistema. Ensambla el prompt que recibe el modelo con secciones priorizadas:
| Sección | Prioridad | Contenido |
|---------|-----------|-----------|
| `immutable_rules` | 100 | System prompt del agente + reglas de sesión. Nunca se recorta |
| `project_profile` | 80 | Perfil del proyecto (nombre, tech stack) |
| `knowledge_base` | 60 | Docs relevantes filtrados por keywords del task |
| `task_state` | 70 | Objetivo, plan, step actual, facts, constraints |
| `artifact_memory` | 50 | Resúmenes de outputs de herramientas |
| `working_context` | 30 | Items de trabajo recientes entre steps |
**Knowledge filtering:** no carga todos los docs. Extrae keywords del objetivo y step actual, puntúa cada doc (título ×10, tags ×5, contenido ×1), y selecciona los más relevantes dentro de un budget de 15k tokens. Los docs que no caben entran como summary de una línea.
**Token counting:** usa `tiktoken` (encoding `cl100k_base`) para conteo real. Fallback a estimación si tiktoken no está instalado.
**Compaction:** si el total excede el context window (120k tokens default), las secciones de menor prioridad se comprimen o eliminan. `immutable_rules` nunca se toca.
## Orchestrator Pipeline
```
mensaje → planner → [step₁ → step₂ → ... → stepₙ] → reviewer → respuesta
```
1. **Planner** descompone el mensaje en pasos con agent role asignado
2. **Router** rutea cada step al agente apropiado (keyword matching: implement→coder, buscar→collector, etc.)
3. **Subagent** ejecuta el step con su propio contexto controlado
4. Si un step **falla**, se marca como failed y el pipeline continúa con el siguiente
5. **Reviewer** valida el trabajo si hubo >1 step
6. **Timeout global** de 5 min (configurable) — si se excede, la sesión pasa a error
**Concurrency:** Redis lock (SETNX) con TTL de 5 min. Si llega un segundo mensaje mientras uno se ejecuta → `{"status": "busy"}`. El lock se libera automáticamente si el proceso muere.
## MCP (Model Context Protocol)
Arquitectura **per-session**: el microservicio corre como un Docker único, y cada sesión arranca sus propios subprocesos MCP con las env vars del proyecto del usuario.
### Modelo de operación
```
Docker (microservicio — uno solo corriendo)
└── mcp.json ← template: QUÉ servers arrancar (global)
└── mcp-server/ ← código MCP (baked-in)
POST /sessions { mcp_env: { ACAI_WEB_URL: "https://tienda.com", ... } }
→ Arranca subprocesos MCP con esas env vars
→ Session aislada con su propio MCPManager
→ 33 tools descubiertas automáticamente
DELETE /sessions/{id}
→ Mata los subprocesos MCP de esa sesión
```
### Configuración
**1. Template global** (`mcp.json` en la raíz — define QUÉ servers existen):
```json
{
"mcpServers": {
"acai-code": {
"command": "node",
"args": ["mcp-server/stdio.js"],
"env": {},
"timeout": 30,
"startup_timeout": 10
}
}
}
```
```bash
# En .env
AGENTIC_MCP_CONFIG_PATH=mcp.json
```
**2. Per-session env vars** (cada usuario/proyecto pasa las suyas al crear sesión):
```bash
curl -X POST http://localhost:8001/api/v1/sessions \
-H "Content-Type: application/json" \
-d '{
"project_profile": {"name": "tienda-online"},
"mcp_env": {
"ACAI_WEB_URL": "https://superadmin_tienda.forge.acaisuite.com/",
"ACAI_WEBSITE": "tienda.com",
"ACAI_PROJECT_DIR": "/projects/tienda"
}
}'
```
Las env vars de `mcp_env` se fusionan con las del template y se pasan al subproceso MCP. El MCP server lee el token desde el `.acai` del proyecto automáticamente.
**3. Legacy** (un solo server global, sin `mcp.json`):
```bash
AGENTIC_MCP_SERVER_COMMAND=node
AGENTIC_MCP_SERVER_ARGS=["mcp-server/stdio.js"]
```
### Tool namespacing
En modo multi-server, los tools se namespean: `acai-code.compile_module`, `filesystem.read_file`. En modo single-server los tools mantienen su nombre original.
### API de gestión MCP
```bash
# Ver estado de todos los MCP servers activos (por sesión)
curl http://localhost:8001/api/v1/mcp/status
# Hot-reload del template (re-lee mcp.json, no afecta sesiones activas)
curl -X POST http://localhost:8001/api/v1/mcp/reload
```
### Ciclo de vida
1. `POST /sessions` con `mcp_env` → arranca subprocesos MCP para esa sesión
2. `POST /sessions/{id}/messages` → el agente usa los tools del MCP de esa sesión
3. Si el server se reinicia y la sesión sigue en Redis → el MCP se reconecta automáticamente al siguiente mensaje
4. `DELETE /sessions/{id}` → mata subprocesos MCP de esa sesión
Los resultados de tools **nunca** entran al contexto como raw output — se resumen como artifacts.
## Configuración
Variables de entorno con prefijo `AGENTIC_`:
| Variable | Default | Descripción |
|----------|---------|-------------|
| `AGENTIC_ANTHROPIC_API_KEY` | — | API key de Anthropic |
| `AGENTIC_OPENAI_API_KEY` | — | API key de OpenAI |
| `AGENTIC_DEFAULT_MODEL_PROVIDER` | `claude` | `claude` o `openai` |
| `AGENTIC_DEFAULT_MODEL_ID` | `claude-sonnet-4-20250514` | Modelo por defecto |
| `AGENTIC_REDIS_HOST` | `localhost` | Host de Redis |
| `AGENTIC_REDIS_PORT` | `6379` | Puerto de Redis |
| `AGENTIC_REDIS_DB` | `0` | Base de datos Redis |
| `AGENTIC_REDIS_PASSWORD` | — | Password de Redis |
| `AGENTIC_MAX_TOKENS` | `4096` | Max tokens de salida por llamada |
| `AGENTIC_CONTEXT_MAX_TOKENS` | `120000` | Max context window |
| `AGENTIC_MAX_EXECUTION_STEPS` | `25` | Max steps por task |
| `AGENTIC_MAX_EXECUTION_TIMEOUT_SECONDS` | `300` | Timeout global (5 min) |
| `AGENTIC_SUBAGENT_MAX_STEPS` | `10` | Max iterations por subagent |
| `AGENTIC_MCP_CONFIG_PATH` | — | Ruta a `mcp.json` (multi-MCP per-session) |
| `AGENTIC_MCP_SERVER_COMMAND` | — | Legacy: comando del servidor MCP (single) |
| `AGENTIC_MCP_SERVER_ARGS` | `[]` | Legacy: argumentos del servidor MCP |
| `AGENTIC_MCP_TIMEOUT_SECONDS` | `30` | Timeout por tool call |
| `AGENTIC_DEBUG` | `false` | Logging verbose |
## Redis Key Structure
```
agentic:session:{id} → SessionState JSON (TTL 24h)
agentic:session:{id}:artifacts → Hash de ArtifactSummary
agentic:session:{id}:events → Lista de SSE events (cap 500)
agentic:session:{id}:lock → Execution lock (SETNX, TTL 5min)
agentic:sessions:index → Set de session IDs activos
agentic:memory:knowledge:{doc_id} → MemoryDocument JSON
agentic:memory:knowledge:_index → Set de doc IDs
agentic:memory:_tag:{tag} → Set de doc IDs por tag
agentic:memory:_type:{type} → Set de doc IDs por tipo
```
## Project Structure
```
.
├── src/
│ ├── main.py # FastAPI app, lifecycle, wiring
│ ├── config.py # Pydantic settings
│ ├── models/ # Pydantic v2 data models
│ │ ├── session.py # SessionState, TaskState, TaskStep
│ │ ├── context.py # ContextPackage, MemoryDocument
│ │ ├── agent.py # AgentProfile, SubAgentDefinition
│ │ ├── artifacts.py # ArtifactSummary
│ │ └── tools.py # ToolExecution, ToolDefinition
│ ├── context/ # Context Engine (core)
│ │ ├── engine.py # Prompt assembly, knowledge filtering, debug
│ │ └── compactor.py # Compaction, summarization, tiktoken
│ ├── memory/ # Persistent memory
│ │ └── store.py # Redis-backed memory + embeddings
│ ├── adapters/ # Model provider adapters
│ │ ├── base.py # ModelAdapter interface
│ │ ├── claude_adapter.py # Anthropic Claude (streaming)
│ │ └── openai_adapter.py # OpenAI GPT (streaming)
│ ├── mcp/ # MCP (per-session, multi-server)
│ │ ├── client.py # stdio transport, tool registry
│ │ ├── config.py # mcp.json parser (Pydantic)
│ │ ├── manager.py # MCPManager (aggregates tools, routes calls)
│ │ └── registry.py # Per-session MCP lifecycle
│ ├── orchestrator/ # Agent orchestration
│ │ ├── engine.py # Pipeline + error recovery + timeout
│ │ ├── router.py # Step-to-agent routing
│ │ └── agents/
│ │ ├── base.py # Shared execution loop
│ │ ├── planner.py # Plan decomposition
│ │ ├── coder.py # Implementation
│ │ ├── collector.py # Context gathering
│ │ └── reviewer.py # Validation
│ ├── streaming/ # SSE streaming
│ │ └── sse.py # Event emitter + Redis persistence
│ ├── storage/ # Persistence
│ │ └── redis.py # Sessions, events, locks
│ └── api/ # REST endpoints
│ └── routes.py # Sessions, messages, knowledge, debug
├── dashboard/ # Testing UI (vanilla JS, zero build)
│ ├── index.html
│ ├── css/main.css
│ └── js/
│ ├── app.js # State, SSE handlers
│ ├── api.js # Fetch + EventSource
│ └── components/ # Sidebar, chat, event log, inspector, timeline
├── mcp-server/ # Acai MCP server (Node.js, stdio)
├── docs/ # Knowledge base documents (*.md)
├── mcp.json # MCP server template (qué servers arrancar)
├── mcp.json.example # Ejemplo con múltiples servers
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── .env.example
```