The bot service in docker-compose.yml builds from ./bot, but the agent code lived in 'ai procurement/' and ./bot was only a Windows junction on reza.g's machine (and was gitignored) — exactly as the team reported: 'bot/ was never committed — prod-v7's bot is un-buildable from the repo.' - junction removed; 'ai procurement/' renamed to 'bot/' via git mv (all 41 files keep their history as pure renames) - 'bot/' dropped from .gitignore (voice/ stays ignored — runtime voice notes; bot/.env stays ignored by bot/.gitignore) - compose needs no change: context: ./bot and ./bot/app now resolve to committed files - bot/INTEGRATION-REPORT.md added: full story (problem, root cause, git state, security note on the committed BALE_BOT_TOKEN / AI_API_KEY compose defaults, and usage instructions for the team) Verified: 41 renames staged with zero secret/cache files; voice/ and bot/.env still ignored.
2.1 KiB
ERP integration pack
The agent is a standalone container — it talks to the ERP exclusively over
HTTP and keeps its own state in its own bot_* tables. Integrating it into the
ERP stack needs exactly
two things:
1. Compose service
Add erp-compose-service.yml to the ERP's
docker-compose.yml (and the Coolify variant). The bot long-polls Bale, so it
needs no ports, no webhook, no TLS — it joins the compose default network
and reaches http://api:8000/api/v1 in-network.
Credentials/env are passed at compose level from a .env next to the compose
file: BALE_BOT_TOKEN, AI_BASE_URL, AI_API_KEY, AI_LLM_MODEL
(see ../.env.example for the full list).
If your stack is started with multiple
-ffiles (e.g. a prod_v2 checkout + port-remap override), keep using the same chain — thebotservice merges in like any other service and the override's host-port remaps don't affect it.
2. Per-user attribution in the API
Apply x-actor-id.patch — a ~6-line, fully
backward-compatible change to backend/app/utils/security.py:
- before:
get_actorreturns the rawAuthorization: Bearer …string andquote_events.actorstores the bot's token; - after: an
X-Actor-Id: <users.id>header (sent by the bot for every mutating call, carrying the linked ERP user's id) takes precedence, so the audit trail records the human who asked, not the bot.
Requests without the header behave exactly as before.
What the agent does NOT touch
- No ERP code is imported by the bot (HTTP-only, own postgres tables
bot_links/bot_drafts/bot_messages/bot_meta, created idempotently at startup withCREATE TABLE IF NOT EXISTS). - No Alembic migration needed — the bot owns its schema.
- The ERP's data model stays untouched; committed drafts flow through the
ordinary public endpoints (
POST /quotes,PATCH /quotes/{id}/accept,PATCH /quotes/{id}/arrive-items,POST /suppliers,POST /materials).