CLAUDE.md

This commit is contained in:
2026-05-20 21:21:45 +00:00
parent 564f1a9479
commit e67dc06a22

212
CLAUDE.md Normal file
View File

@@ -0,0 +1,212 @@
# CLAUDE.md — odoo-ai
This file gives Claude Code the context it needs to work effectively on this project.
**Read this before making any changes.**
---
## What This Project Is
`odoo-ai` is a multi-agent AI system that integrates with Odoo 18 Community Edition.
It consists of two main components that work together:
1. **`agent_service/`** — FastAPI service (port 8001) — the AI brain. Hosts MasterAgent + 8 specialist agents, all LLM backends, memory tiers, and tool layers.
2. **`addons/activeblue_ai/`** — Odoo 18 module — the Odoo-side integration. OWL2 chat panel, webhook controllers, approval workflows, and cron jobs.
These are deployed as two separate Docker Compose stacks on the same host (`192.168.2.9`).
---
## Deployment Context
| Item | Value |
|---|---|
| Agent service URL | `http://192.168.2.9:8001` (internal)
| Odoo URL | `http://192.168.2.9:8069` (separate vhost) |
| Ollama | `http://192.168.2.9:11434` |
| LLM model | `activeblue-chat` (llama-based, ~124s cold-start from disk) |
| Postgres | Two separate DBs — one for Odoo, one for agent service |
**HIPAA constraint**: HIPAA-locked agents (`finance_agent`, `accounting_agent`, `employees_agent`, `expenses_agent`) must always use Ollama. Ollama is to have the ability to call out to Claude or any other cloud AI solution for assistance on completing a task if Ollama has not been able to resolve the request after 5 tries, no personal data is to be leaked out of the environment.
---
## Project Structure
```
odoo-ai/
├── agent_service/
│ ├── agents/ # MasterAgent, 8 specialist agents, PeerBus, SweepCoordinator
│ ├── llm/ # OllamaBackend, ClaudeBackend, LLMRouter, ToolCallValidator
│ ├── memory/ # ConversationStore, OperationalStore, KnowledgeStore, MemoryManager
│ ├── tools/ # OdooClient + per-domain tool files
│ ├── routers/ # FastAPI routers: dispatch, approval, registry, sweep, health
│ ├── prompts/ # System prompts — one per agent
│ ├── mcp/ # MCP gateway (SSE, 14 tools, all forced local)
│ ├── migrations/ # Alembic — 7 tables
│ ├── logging_utils/ # Structured JSON logging + Loki push
│ ├── config.py # pydantic-settings — all config lives here
│ ├── app_state.py # Global singletons (MasterAgent, LLMRouter, etc.)
│ └── main.py # FastAPI app + lifespan startup (prewarm + auto-heal)
├── addons/
│ └── activeblue_ai/
│ ├── models/ # ab.ai.bot, ab.ai.directive, ab.ai.log, ab.ai.agent.registry
│ ├── controllers/ # /ai/chat, /ai/webhook/callback, /ai/health, /ai/approval/*
│ ├── views/ # XML views + menus
│ ├── security/ # groups + ACL
│ ├── data/ # cron jobs
│ └── static/ # OWL2 JS + CSS + XML templates (systray brain icon + chat panel)
├── tests/ # 433 pytest tests — run before committing
├── research/ # Per-domain research notes — read before touching a domain
├── debian/ # .deb packaging
├── docker-compose.yml # Agent service + its Postgres
├── docker-compose.odoo.yml # Odoo 18 + Odoo Postgres
├── Dockerfile
├── traefik_dynamic_ai.yml # Traefik dynamic config for ai.activeblue.net
├── setup.sh # Detects stale DB volume, runs Alembic on startup
├── build_deb.sh / publish_repo.sh
├── .env.example
└── VERSION
```
---
## Key Architectural Rules
### Agent constraints
- **Max 8 tools per specialist agent** — enforced by `ToolCallValidator` at startup; `AgentConfigError` is raised if exceeded. Do not add tools without removing others.
- Agents are **stateless** — no instance state between requests. All state lives in the 3-tier memory tables.
- `MasterAgent` is a **singleton** — instantiated once in `app_state.py`, shared across all requests.
### Memory tiers
| Tier | Table | TTL | Scope |
|---|---|---|---|
| 1 | `ab_conversation_memory` | 200 rows/user hard cap | Per user |
| 2 | `ab_operational_memory` | 90 days | Per agent + scope |
| 3 | `ab_knowledge_store` | Permanent | Entity-keyed |
### LLM routing
- `LLMRouter` selects backend: Ollama or Claude, based on `LLM_PRIVACY_MODE` env + per-agent DB overrides
- Privacy modes: `local` (Ollama only) / `hybrid` (per-agent override) / `cloud` (Claude for non-HIPAA agents)
- **HIPAA agents are always Ollama** — this is hardcoded, not just config
### Auto-RAG
All agents automatically call `odoo_doc_agent` to fetch Odoo 18 workflow guidance before answering. Don't remove this.
### Auto-heal loop
`main.py` lifespan starts a background task that calls `sysops_agent.auto_heal()` every 2 minutes if any system is degraded.
If all systems are running properly, then the MasterAgent which is seen by the user in the Discuss tab of odoo will be seen as Online denoted by a green icon that odoo uses to show user's online. The MasterAgent is a user in odoo with the email of activeblue_ai_bot@local
### Key workflows
The user will be able to drop a zip file into the MasterAgent, the MasterAgent has the ability to extract this file, examine the contents and proceed to ask on what to do with the files. The MasterAgent has OCR capability and has recently been updated to Llama Vision. The MasterAgent is to route the information with the customer's request to the correct Agent. As an example of workflows that have worked in the past;
User drops receipts zip file in the chat;
MasterAgent extracts and reads the files with OCR and asks what to do with them.
Customer states; create an expense report.
MasterAgent routes the information to the responsible agent.
The responsible agent creates the expense report and then confirms when complete.
MasterAgent replies to the customer that the report is complete.
### Ollama cold-start
`activeblue-chat` takes ~124s to load from disk. `_prewarm_ollama()` runs as a background task at startup. `OllamaBackend` enforces `_MIN_TIMEOUT=300s` regardless of env var — do not lower this.
---
## Coding Conventions
- **Python async throughout** — all agent methods, tool calls, DB access are `async`
- **asyncpg** for direct Postgres — not SQLAlchemy ORM, not psycopg2
- **pydantic-settings** in `config.py` — all configuration comes from here, not hardcoded
- **Structured JSON logging** via `logging_utils/` — use this, not `print()` or raw `logging`
- **Conventional commits**: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`
- **Feature branches** per agent or feature — don't commit directly to `main` for large changes
- **Alembic** for all DB schema changes — never modify tables directly
### Adding a new specialist agent
1. Create `agent_service/agents/<name>_agent.py` — extend base agent class
2. Create `agent_service/tools/<name>_tools.py` — max 8 tools
3. Create `agent_service/prompts/<name>_agent.txt`
4. Register in `AgentRegistry`
5. Add tests in `tests/test_<name>_agent.py` and `tests/test_<name>_tools.py`
6. If HIPAA-sensitive, hardcode Ollama in `LLMRouter`
### Modifying the Odoo module
- Odoo module lives in `addons/activeblue_ai/` — copy this into the Odoo container's addons volume to deploy
- After any model change: increment `version` in `__manifest__.py` and run module upgrade in Odoo
- OWL2 components are in `static/src/` — Odoo bundles JS at runtime, no separate build step needed
- XML IDs must be globally unique — prefix everything with `activeblue_ai.`
---
## Running Locally (Dev)
```bash
# 1. Copy and fill .env
cp .env.example .env
# 2. Start Odoo stack
docker compose -f docker-compose.odoo.yml up -d
# 3. Start agent service (dev mode with reload)
pip install -r requirements.txt
uvicorn agent_service.main:app --reload --port 8001
# 4. Run Alembic migrations
cd agent_service/migrations && alembic upgrade head
# 5. Install Odoo module
# Odoo → Settings → Apps → search "ActiveBlue AI" → Install
```
---
## Tests
**Always run tests before committing.**
```bash
# Preferred: use the project test venv
.venv-test/bin/python -m pytest tests/ -q
# Or manually
pip install -r requirements-test.txt
pytest tests/ -v
```
433 tests covering all 8 agents, all tool layers, PeerBus, AgentRegistry, ToolCallValidator, memory, dispatch router, and LLM router. All tests run in `local` mode (Ollama mocked) — no cloud LLM calls in tests.
---
## Environment Variables
See `.env.example` for full list. Critical ones:
| Variable | Notes |
|---|---|
| `ODOO_URL` | `http://ai.activeblue.net` |
| `ODOO_API_KEY` | Odoo user API key — get from Odoo user settings |
| `OLLAMA_URL` | `http://192.168.2.9:11434` — use this IP, not `.2.10` or `.2.47` |
| `LLM_PRIVACY_MODE` | `local` / `hybrid` / `cloud` — default `local` |
| `ANTHROPIC_API_KEY` | Only needed for `hybrid` or `cloud` mode |
| `POSTGRES_PASSWORD` | No default — must be set |
| `WEBHOOK_SECRET` | Shared between Odoo and agent service |
---
## Common Issues & Gotchas
- **Ollama timeout errors on first request**: model is still warming. Check `/health/detailed` — if it says `warming`, wait. Do not lower `_MIN_TIMEOUT`.
- **`AgentConfigError` at startup**: a specialist agent has > 8 tools. Remove tools before adding new ones.
- **Alembic "table already exists"**: stale DB volume. `setup.sh` detects this — check its logic before manually dropping tables.
- **OWL2 chat panel not loading**: JS bundle cache in Odoo. Run `Assets → Clear cache` in debug mode, or restart Odoo.
- **PeerBus routing loops**: `depth` parameter limits recursion. Don't increase `MAX_PEER_DEPTH` without understanding call-log tracking.
- **Traefik ACME for `ai.activeblue.net`**: config is in `traefik_dynamic_ai.yml` — copy to Traefik CT's dynamic config directory on `192.168.1.53`.
- **Two separate Postgres instances**: agent service DB ≠ Odoo DB. Alembic only manages the agent service DB. Never run Alembic against the Odoo DB.
---
## What's Out of Scope for This Repo
- Axolotl / QLoRA fine-tuning pipeline → `/opt/axolotl` on `192.168.2.9` (separate)
- IRC bot → `tocmo0nlord/irc-bot` (separate repo)
- Traefik main config → managed on CT 112 directly
- Odoo HIPAA training eLearning module → different Odoo addon, different repo