# Integrated example for sibling project folders: # ./glpi-ai-agent # ./glpi-ai-knowledgebase # ./glpi-neural-brain # Run from glpi-neural-brain: # docker compose -f deployment/docker-compose.full.yml up -d --build services: agent-data-init: build: context: ${AGENT_PROJECT_PATH:-../../glpi-ai-agent} target: data-init restart: "no" user: "0:0" volumes: - agent-data:/app/data security_opt: [no-new-privileges:true] cap_drop: [ALL] cap_add: [CHOWN, FOWNER] agent: build: ${AGENT_PROJECT_PATH:-../../glpi-ai-agent} restart: unless-stopped env_file: ${AGENT_ENV_FILE:-../../glpi-ai-agent/.env} environment: DATA_DIR: /app/data KNOWLEDGE_DIR: /app/knowledge OLLAMA_URL: http://ollama:11434 OLLAMA_URLS: ${OLLAMA_URLS:-http://ollama:11434} OLLAMA_NODE_NAMES: ${OLLAMA_NODE_NAMES:-local-gpu} OLLAMA_NODE_WEIGHTS: ${OLLAMA_NODE_WEIGHTS:-1} OLLAMA_ROUTING_MODE: ${OLLAMA_ROUTING_MODE:-least_inflight} OLLAMA_NODE_MAX_INFLIGHT: ${OLLAMA_NODE_MAX_INFLIGHT:-1} BRAIN_ACTIVITY_URL: http://brain:8090/api/events BRAIN_ACTIVITY_API_KEY: ${BRAIN_API_KEY:-} ports: - "127.0.0.1:${AGENT_PORT:-8080}:8080" volumes: - agent-data:/app/data - ${KNOWLEDGE_HOST_PATH:-../../glpi-ai-agent/knowledge}:/app/knowledge:ro depends_on: agent-data-init: condition: service_completed_successfully security_opt: [no-new-privileges:true] cap_drop: [ALL] read_only: true tmpfs: [/tmp:size=64m,mode=1777] kb-editor: build: ${KB_PROJECT_PATH:-../../glpi-ai-knowledgebase} image: kb-helpdesk:neural-stack restart: unless-stopped ports: - "${KB_EDITOR_PORT:-8081}:8080" environment: APP_MODE: editor APP_TITLE: KB Administration APP_SUBTITLE: Wissen und AI-THINK prüfen DATA_DIR: /data/knowledge BACKUP_DIR: /data/backups STAGING_DIR: /data/staging LISTEN_ADDR: :8080 BASIC_AUTH_USER: ${EDITOR_AUTH_USER:-} BASIC_AUTH_PASSWORD: ${EDITOR_AUTH_PASSWORD:-} BRAIN_ACTIVITY_URL: http://brain:8090/api/events BRAIN_ACTIVITY_API_KEY: ${BRAIN_API_KEY:-} volumes: - ${KNOWLEDGE_HOST_PATH:-../../glpi-ai-agent/knowledge}:/data/knowledge:rw - ${KB_BACKUP_HOST_PATH:-../../glpi-ai-knowledgebase/backups}:/data/backups:rw - ${KB_STAGING_HOST_PATH:-../../glpi-ai-knowledgebase/staging}:/data/staging:rw read_only: true tmpfs: [/tmp:size=32m] security_opt: [no-new-privileges:true] cap_drop: [ALL] kb-search: image: kb-helpdesk:neural-stack depends_on: [kb-editor] restart: unless-stopped ports: - "${KB_SEARCH_PORT:-8082}:8080" environment: APP_MODE: google APP_TITLE: IT Helpdesk Wissen APP_SUBTITLE: Interne Lösungsdatenbank AUTO_RELOAD_INTERVAL: 60s DATA_DIR: /data/knowledge # Deliberately isolated: production search never sees Brain AI-THINK drafts. STAGING_DIR: /tmp/empty-staging LISTEN_ADDR: :8080 OLLAMA_BASE_URL: http://ollama:11434 AI_FALLBACK_ENABLED: ${AI_FALLBACK_ENABLED:-false} OLLAMA_MODEL: ${OLLAMA_CHAT_MODEL:-qwen3:8b} BRAIN_ACTIVITY_URL: http://brain:8090/api/events BRAIN_ACTIVITY_API_KEY: ${BRAIN_API_KEY:-} volumes: - ${KNOWLEDGE_HOST_PATH:-../../glpi-ai-agent/knowledge}:/data/knowledge:ro read_only: true tmpfs: [/tmp:size=32m] security_opt: [no-new-privileges:true] cap_drop: [ALL] brain: build: context: .. restart: unless-stopped ports: - "${BRAIN_PORT:-8090}:8090" environment: BRAIN_LISTEN_ADDR: :8090 BRAIN_DATA_DIR: /app/data BRAIN_KNOWLEDGE_DIRS: /sources/knowledge BRAIN_STAGING_DIRS: /sources/staging BRAIN_AGENT_RUNS_FILES: /sources/agent-data/runs.jsonl BRAIN_API_KEY: ${BRAIN_API_KEY:-} OLLAMA_URL: http://ollama:11434 OLLAMA_URLS: ${OLLAMA_URLS:-http://ollama:11434} OLLAMA_NODE_NAMES: ${OLLAMA_NODE_NAMES:-local-gpu} OLLAMA_NODE_WEIGHTS: ${OLLAMA_NODE_WEIGHTS:-1} OLLAMA_ROUTING_MODE: ${OLLAMA_ROUTING_MODE:-least_inflight} OLLAMA_NODE_MAX_INFLIGHT: ${OLLAMA_NODE_MAX_INFLIGHT:-1} OLLAMA_NODE_HEALTH_INTERVAL: ${OLLAMA_NODE_HEALTH_INTERVAL:-15s} OLLAMA_NODE_FAILURE_COOLDOWN: ${OLLAMA_NODE_FAILURE_COOLDOWN:-30s} OLLAMA_NODE_REQUEST_TIMEOUT: ${OLLAMA_NODE_REQUEST_TIMEOUT:-8m} OLLAMA_FAILOVER_ENABLED: ${OLLAMA_FAILOVER_ENABLED:-true} OLLAMA_FAILOVER_ATTEMPTS: ${OLLAMA_FAILOVER_ATTEMPTS:-0} OLLAMA_REQUIRE_SAME_MODEL_DIGEST: ${OLLAMA_REQUIRE_SAME_MODEL_DIGEST:-true} OLLAMA_REQUIRE_EMBEDDING_MODEL: ${OLLAMA_REQUIRE_EMBEDDING_MODEL:-true} OLLAMA_CHAT_MODEL: ${OLLAMA_CHAT_MODEL:-qwen3:8b} OLLAMA_EMBEDDING_MODEL: ${OLLAMA_EMBEDDING_MODEL:-embeddinggemma} BRAIN_AUTO_ENRICH: ${BRAIN_AUTO_ENRICH:-true} BRAIN_SCAN_INTERVAL: ${BRAIN_SCAN_INTERVAL:-20s} BRAIN_PERSIST_INTERVAL: ${BRAIN_PERSIST_INTERVAL:-5m} BRAIN_LEARNING_ENABLED: ${BRAIN_LEARNING_ENABLED:-true} BRAIN_THINKING_ENABLED: ${BRAIN_THINKING_ENABLED:-true} BRAIN_LEARNING_SOURCES: ${BRAIN_LEARNING_SOURCES:-} BRAIN_DISPLAY_SOURCES: ${BRAIN_DISPLAY_SOURCES:-} BRAIN_THINKING_SOURCES: ${BRAIN_THINKING_SOURCES:-} BRAIN_DEFAULT_VIEW: ${BRAIN_DEFAULT_VIEW:-neural} BRAIN_MAX_DISPLAY_NODES: ${BRAIN_MAX_DISPLAY_NODES:-0} BRAIN_LOW_POWER_MODE: ${BRAIN_LOW_POWER_MODE:-false} BRAIN_ENRICH_INTERVAL: ${BRAIN_ENRICH_INTERVAL:-90s} BRAIN_ENRICH_BATCH_SIZE: ${BRAIN_ENRICH_BATCH_SIZE:-3} BRAIN_ENRICH_STEP_DELAY: ${BRAIN_ENRICH_STEP_DELAY:-3s} BRAIN_ENRICH_ANCHORS: ${BRAIN_ENRICH_ANCHORS:-48} BRAIN_SIMILARITY_THRESHOLD: ${BRAIN_SIMILARITY_THRESHOLD:-0.68} BRAIN_RELATION_THRESHOLD: ${BRAIN_RELATION_THRESHOLD:-0.72} BRAIN_ARTICLE_SYNTHESIS_ENABLED: ${BRAIN_ARTICLE_SYNTHESIS_ENABLED:-true} BRAIN_ARTICLE_LANGUAGE: ${BRAIN_ARTICLE_LANGUAGE:-de-DE} BRAIN_ARTICLE_SYNTHESIS_MODEL: ${BRAIN_ARTICLE_SYNTHESIS_MODEL:-qwen3:8b} BRAIN_ARTICLE_REVIEW_MODEL: ${BRAIN_ARTICLE_REVIEW_MODEL:-qwen3:8b} BRAIN_ARTICLE_REVIEW_REPAIR_ROUNDS: ${BRAIN_ARTICLE_REVIEW_REPAIR_ROUNDS:-1} BRAIN_ARTICLE_MIN_SOURCES: ${BRAIN_ARTICLE_MIN_SOURCES:-3} BRAIN_ARTICLE_MAX_SOURCES: ${BRAIN_ARTICLE_MAX_SOURCES:-8} BRAIN_ARTICLE_MIN_PRODUCTION_RATIO: ${BRAIN_ARTICLE_MIN_PRODUCTION_RATIO:-0.70} BRAIN_ARTICLE_MAX_GENERATION_DEPTH: ${BRAIN_ARTICLE_MAX_GENERATION_DEPTH:-2} BRAIN_ARTICLE_MIN_CONFIDENCE: ${BRAIN_ARTICLE_MIN_CONFIDENCE:-0.74} BRAIN_ARTICLE_MIN_TEXT_CHARS: ${BRAIN_ARTICLE_MIN_TEXT_CHARS:-180} BRAIN_ARTICLE_MIN_ANSWER_CHARS: ${BRAIN_ARTICLE_MIN_ANSWER_CHARS:-420} BRAIN_ARTICLE_MAX_RESEARCH_QUERIES: ${BRAIN_ARTICLE_MAX_RESEARCH_QUERIES:-6} BRAIN_ARTICLE_RESEARCH_RESULTS: ${BRAIN_ARTICLE_RESEARCH_RESULTS:-12} BRAIN_ARTICLE_RESEARCH_ROUNDS: ${BRAIN_ARTICLE_RESEARCH_ROUNDS:-3} BRAIN_ARTICLE_RESEARCH_FETCH_RESULTS: ${BRAIN_ARTICLE_RESEARCH_FETCH_RESULTS:-6} BRAIN_ARTICLE_RESEARCH_EXPLORATION_RESULTS: ${BRAIN_ARTICLE_RESEARCH_EXPLORATION_RESULTS:-3} BRAIN_ARTICLE_RESEARCH_PREFETCH_MIN_RELEVANCE: ${BRAIN_ARTICLE_RESEARCH_PREFETCH_MIN_RELEVANCE:-0.25} BRAIN_ARTICLE_RESEARCH_MIN_RELEVANCE: ${BRAIN_ARTICLE_RESEARCH_MIN_RELEVANCE:-0.55} BRAIN_ARTICLE_RESEARCH_MIN_QUALITY: ${BRAIN_ARTICLE_RESEARCH_MIN_QUALITY:-0.35} BRAIN_ARTICLE_RESEARCH_PAGE_MAX_BYTES: ${BRAIN_ARTICLE_RESEARCH_PAGE_MAX_BYTES:-2097152} BRAIN_ARTICLE_RESEARCH_PAGE_MAX_CHARS: ${BRAIN_ARTICLE_RESEARCH_PAGE_MAX_CHARS:-14000} BRAIN_ARTICLE_RESEARCH_FETCH_TIMEOUT: ${BRAIN_ARTICLE_RESEARCH_FETCH_TIMEOUT:-20s} BRAIN_ARTICLE_RESEARCH_ALLOW_PRIVATE: ${BRAIN_ARTICLE_RESEARCH_ALLOW_PRIVATE:-false} BRAIN_RESEARCH_OLLAMA_MAX_INFLIGHT: ${BRAIN_RESEARCH_OLLAMA_MAX_INFLIGHT:-2} BRAIN_RESEARCH_OLLAMA_QUEUE_SIZE: ${BRAIN_RESEARCH_OLLAMA_QUEUE_SIZE:-64} BRAIN_RESEARCH_DEDUPE_THRESHOLD: ${BRAIN_RESEARCH_DEDUPE_THRESHOLD:-0.92} BRAIN_RESEARCH_DEDUPE_TTL: ${BRAIN_RESEARCH_DEDUPE_TTL:-45m} BRAIN_TOP_K: ${BRAIN_TOP_K:-8} BRAIN_MAX_CONTEXT_CHARS: ${BRAIN_MAX_CONTEXT_CHARS:-16000} BRAIN_RESEARCH_ENABLED: ${BRAIN_RESEARCH_ENABLED:-false} BRAIN_AUTONOMOUS_RESEARCH_ENABLED: ${BRAIN_AUTONOMOUS_RESEARCH_ENABLED:-false} BRAIN_AUTONOMOUS_RESEARCH_IDLE_ONLY: ${BRAIN_AUTONOMOUS_RESEARCH_IDLE_ONLY:-true} BRAIN_AUTONOMOUS_RESEARCH_INTERVAL: ${BRAIN_AUTONOMOUS_RESEARCH_INTERVAL:-30m} BRAIN_AUTONOMOUS_RESEARCH_TASKS_PER_CYCLE: ${BRAIN_AUTONOMOUS_RESEARCH_TASKS_PER_CYCLE:-1} BRAIN_AUTONOMOUS_RESEARCH_MAX_TASKS_PER_DAY: ${BRAIN_AUTONOMOUS_RESEARCH_MAX_TASKS_PER_DAY:-12} BRAIN_AUTONOMOUS_RESEARCH_MAX_QUERIES_PER_TASK: ${BRAIN_AUTONOMOUS_RESEARCH_MAX_QUERIES_PER_TASK:-6} BRAIN_AUTONOMOUS_RESEARCH_MAX_PAGES_PER_TASK: ${BRAIN_AUTONOMOUS_RESEARCH_MAX_PAGES_PER_TASK:-8} BRAIN_AUTONOMOUS_RESEARCH_MAX_ROUNDS: ${BRAIN_AUTONOMOUS_RESEARCH_MAX_ROUNDS:-3} BRAIN_AUTONOMOUS_RESEARCH_MIN_PRIORITY: ${BRAIN_AUTONOMOUS_RESEARCH_MIN_PRIORITY:-0.65} BRAIN_AUTONOMOUS_RESEARCH_COOLDOWN: ${BRAIN_AUTONOMOUS_RESEARCH_COOLDOWN:-168h} BRAIN_AUTONOMOUS_RESEARCH_LEASE: ${BRAIN_AUTONOMOUS_RESEARCH_LEASE:-45m} BRAIN_AUTONOMOUS_RESEARCH_MAX_ATTEMPTS: ${BRAIN_AUTONOMOUS_RESEARCH_MAX_ATTEMPTS:-3} BRAIN_AUTONOMOUS_RESEARCH_QUERY_TRIGGERS: ${BRAIN_AUTONOMOUS_RESEARCH_QUERY_TRIGGERS:-true} BRAIN_AUTONOMOUS_RESEARCH_OPPORTUNITY_LIMIT: ${BRAIN_AUTONOMOUS_RESEARCH_OPPORTUNITY_LIMIT:-8} # In Docker, localhost points to this Brain container. Use the SearXNG # service name (for example http://searxng:8080) or host.docker.internal. SEARXNG_URL: ${SEARXNG_URL:-} GLPI_KB_ENABLED: ${GLPI_KB_ENABLED:-false} GLPI_URL: ${GLPI_URL:-} GLPI_API_VERSION: ${GLPI_API_VERSION:-v2.3} GLPI_CLIENT_ID: ${GLPI_CLIENT_ID:-} GLPI_CLIENT_SECRET: ${GLPI_CLIENT_SECRET:-} GLPI_USERNAME: ${GLPI_USERNAME:-} GLPI_PASSWORD: ${GLPI_PASSWORD:-} GLPI_ALLOW_INSECURE_HTTP: ${GLPI_ALLOW_INSECURE_HTTP:-false} GLPI_TIMEOUT: ${GLPI_TIMEOUT:-20s} GLPI_KB_PATH: ${GLPI_KB_PATH:-auto} GLPI_KB_FILTER: ${GLPI_KB_FILTER:-} GLPI_KB_LIMIT: ${GLPI_KB_LIMIT:-500} GLPI_KB_SYNC_INTERVAL: ${GLPI_KB_SYNC_INTERVAL:-10m} GLPI_KB_SOURCE: ${GLPI_KB_SOURCE:-GLPI Knowledge Base} volumes: - brain-data:/app/data - ${KNOWLEDGE_HOST_PATH:-../../glpi-ai-agent/knowledge}:/sources/knowledge:ro - ${KB_STAGING_HOST_PATH:-../../glpi-ai-knowledgebase/staging}:/sources/staging:rw - agent-data:/sources/agent-data:ro extra_hosts: - "host.docker.internal:host-gateway" ollama: image: ollama/ollama:latest restart: unless-stopped volumes: - ollama-data:/root/.ollama volumes: agent-data: brain-data: ollama-data: