{"id":"b93c537f-0836-45cb-bc33-a8cbaf98cd37","slug":"eddi","kind":"mcp","name":"EDDI","summary":"Config-driven engine that turns JSON into production-grade AI agents. Multi-agent orchestration, 12+ LLM providers, MCP/A2A protocols, RAG, persistent memory, and enterprise compliance (EU AI Act, GDP","owner":"labsai","repoUrl":"https://github.com/labsai/EDDI","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":383,"match":null,"fewStars":false,"format":"mcp","createdAt":null,"addedAt":"2026-10-14T03:43:05.229Z","logoUrl":"https://avatars.githubusercontent.com/u/22817083?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["databases","search","cloud-infra"],"tags":["mongodb","java","conversational-ai","quarkus","conversation-memory","langchain4j","postgres","a2a"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-14T03:50:08.412Z","sample":false,"url":"https://conduits.dev/tools/eddi","language":"Java","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"![EDDI Banner Image](/screenshots/EDDI-Readme-banner-image.webp)\n\n# E.D.D.I — Multi-Agent Orchestration Middleware for Conversational AI\n\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/12355/badge?v=2)](https://www.bestpractices.dev/projects/12355) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/labsai/EDDI/badge)](https://securityscorecards.dev/viewer/?uri=github.com/labsai/EDDI) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/2c5d183d4bd24dbaa77427cfbf5d4074)](https://app.codacy.com/organizations/gh/labsai/dashboard?utm_source=github.com&utm_medium=referral&utm_content=labsai/EDDI&utm_campaign=Badge_Grade)\n\n[![CI](https://github.com/labsai/EDDI/actions/workflows/ci.yml/badge.svg)](https://github.com/labsai/EDDI/actions/workflows/ci.yml) [![CodeQL](https://github.com/labsai/EDDI/actions/workflows/codeql.yml/badge.svg)](https://github.com/labsai/EDDI/actions/workflows/codeql.yml) ![Tests](https://img.shields.io/badge/tests-20%2C000%2B-brightgreen) ![Coverage](https://img.shields.io/badge/coverage-%3E90%25%20instr%20%2F%20%3E80%25%20branch-brightgreen)\n\n[![Docker Pulls](https://img.shields.io/docker/pulls/labsai/eddi)](https://hub.docker.com/r/labsai/eddi) [![Latest Release](https://img.shields.io/github/v/release/labsai/EDDI?label=latest&color=blue)](https://github.com/labsai/EDDI/releases) [![Repository: AI Ready](https://img.shields.io/badge/Repository-AI_Ready-blueviolet?logo=robot)](AGENTS.md)\n\n**E.D.D.I** (Enhanced Dialog Driven Interface) is a production-grade, **config-driven multi-agent orchestration middleware** for conversational AI. It coordinates users, AI agents, and business systems through **intelligent routing, persistent memory, and API orchestration** — without writing code.\n\nBuilt with **Java 25** and **Quarkus**. Ships as a **Red Hat-certified Docker image** with the **Manager dashboard and Chat UI built in**. Selected as a **UNIDO Trusted Partner** for Industrial AI. Native support for **MCP** (Model Context Protocol), **A2A** (Agent-to-Agent), the **OpenAI Chat Completions API**, **Slack**, **OpenAPI**, and **OAuth 2.0**.\n\n[Website](https://eddi.labs.ai/) · [Documentation](https://docs.labs.ai/) · License: Apache 2.0\n\n---\n\n## 📑 Table of Contents\n\n- [🏁 Quick Start](#-quick-start)\n- [💡 Why EDDI?](#-why-eddi)\n- [📸 See It In Action](#-see-it-in-action)\n- [✨ Features](#-features)\n- [📖 Documentation](#-documentation)\n- [📋 Compliance & Privacy](#-compliance--privacy)\n- [🏗️ Development](#️-development)\n  - [Prerequisites](#prerequisites)\n  - [Quarkus Dev Mode](#quarkus-dev-mode)\n  - [Maven Command Reference](#maven-command-reference)\n  - [Build & Docker](#build--docker)\n  - [Kubernetes](#️-kubernetes)\n- [🤝 Contributing](#-contributing)\n- [🔒 Security](#-security)\n- [📜 Code of Conduct](#-code-of-conduct)\n\n---\n\n## 🏁 Quick Start\n\nThe fastest way to get EDDI running is the **one-command installer**. It sets up EDDI + your choice of database via Docker Compose and points you at the dashboard, where the **Platform Operator** (or the form-based agent wizard) creates your first AI agent for you.\n\n**Linux / macOS / WSL2:**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/labsai/EDDI/main/install.sh | bash\n```\n\n**Windows (PowerShell):**\n\n```powershell\nInvoke-WebRequest -UseBasicParsing -Uri \"https://raw.githubusercontent.com/labsai/EDDI/main/install.ps1\" -OutFile \"install.ps1\"\nUnblock-File .\\install.ps1\n.\\install.ps1\n```\n\nRequires [Docker](https://docs.docker.com/get-docker/). The wizard auto-generates a unique vault encryption key for secret management.\n\nEverything is served from one port: `http://localhost:7070` opens a chooser between the **Manager** (`/manage`, the admin dashboard) and the **Workforce** workspace (`/workforce`, group conversations), and the standalone chat UI is at `/chat`. See [Getting Started](docs/getting-started.md).\n\n<details>\n<summary><strong>🔧 Installer options</strong></summary>\n\n```bash\nbash install.sh --defaults                 # All defaults, no prompts\nbash install.sh --db=postgres --with-auth  # PostgreSQL + Keycloak\nbash install.sh --full                     # Everything enabled (PostgreSQL + auth + monitoring)\nbash install.sh --local                    # Build Docker image from local source\nbash install.sh --eddi-version=6.5.0       # Pin a release (image and compose files from its tag)\nbash install.sh --dry-run                  # Show the image tag and the git ref the files come from\n```\n\nWith the default `latest` image, the compose files are downloaded from the newest\nrelease's tag (looked up through the GitHub API), not from `main`.\n\nThe `--local` flag is for contributors testing pre-release builds:\n\n```bash\n./mvnw package -DskipTests    # Build the Java app\nbash install.sh --local        # Build Docker image + start containers\n```\n\n</details>\n\n### 🔄 Updating\n\nThe installer creates an `eddi` CLI wrapper that makes updating easy:\n\n```bash\neddi update\n```\n\nThis pulls the latest Docker image from the registry and restarts the containers. It works even when the same tag (e.g. `latest`) was re-published — Docker always checks the remote digest for changes.\n\n> **Upgrading across releases?** Read the upgrade guide first: [Upgrading from 6.4](docs/upgrading-from-6.4.md) lists what an existing deployment must change, because several defaults now fail closed (a Keycloak realm imported from 6.1–6.4 needs a repair that re-running the installer applies and `eddi update` does not). A database that comes from EDDI 5 starts with [Upgrading from 5.x](docs/upgrading-from-5x.md).\n\n> **`eddi` command not found?** The CLI lives at `~/.eddi/eddi` (Linux/macOS) or `~/.eddi/eddi.cmd` (Windows). Either restart your terminal so the PATH takes effect, or use the full path:\n>\n> ```bash\n> # Linux / macOS\n> ~/.eddi/eddi update\n>\n> # Windows (PowerShell)\n> & \"$HOME\\.eddi\\eddi.cmd\" update\n> ```\n\n<details>\n<summary><strong>Manual update (without the CLI)</strong></summary>\n\nIf the `eddi` CLI isn't available, run the equivalent docker commands from your install directory (`~/.eddi` by default):\n\n```bash\ncd ~/.eddi\ndocker compose --env-file .env -f docker-compose.yml pull\ndocker compose --env-file .env -f docker-compose.yml up -d\n```\n\nAdjust the `-f` flags to match your setup (e.g. add `-f docker-compose.auth.yml` if using Keycloak).\n\n</details>\n\n### 🐳 Docker Compose (Manual)\n\nIf you prefer manual control over Docker Compose:\n\n```bash\n# Default (EDDI + MongoDB)\ndocker compose up\n\n# PostgreSQL instead of MongoDB — a complete stack, so it is NOT layered on\n# docker-compose.yml (an overlay cannot un-declare the base's mongodb service)\ndocker compose -f docker-compose.postgres-only.yml up\n\n# With Keycloak authentication. No realm account ships a password (see the\n# header of docker-compose.auth.yml, or let install.sh --with-auth set one)\ndocker compose -f docker-compose.yml -f docker-compose.auth.yml up\n\n# With Prometheus + Grafana monitoring\ndocker compose -f docker-compose.yml -f docker-compose.monitoring.yml up\n\n# With a local LLM — Ollama on the same Docker network, reachable as\n# http://ollama:11434 (no host.docker.internal needed)\ndocker compose -f docker-compose.yml -f docker-compose.ollama.yml up -d\n\n# The same local LLM, on the host's NVIDIA GPUs — layered on the Ollama overlay\n# above, never instead of it (all it adds is `gpus: all`)\ndocker compose -f docker-compose.yml -f docker-compose.ollama.yml \\\n  -f docker-compose.ollama-nvidia.yml up -d\n\n# Auth + monitoring + NATS together (overlays stack in any combination)\ndocker compose -f docker-compose.yml -f docker-compose.auth.yml \\\n  -f docker-compose.monitoring.yml -f docker-compose.nats.yml up\n```\n\nAvailable compose overlays: `docker-compose.auth.yml` (Keycloak), `docker-compose.monitoring.yml` (Prometheus+Grafana), `docker-compose.nats.yml` (NATS JetStream), `docker-compose.ollama.yml` (local LLM; add `docker-compose.ollama-nvidia.yml` on top for NVIDIA GPU access), `docker-compose.chroma.yml` (vector store), `docker-compose.mcp-sidecar.yml` (reach a stdio-only MCP server through a bridge sidecar — read the [MCP Client](docs/mcp-client.md#stdio-servers-via-a-bridge-sidecar) guide first), `docker-compose.local.yml` (build from source). `docker-compose.postgres-only.yml` is a complete standalone stack rather than an overlay — use it on its own, not with `-f docker-compose.yml`; so is `docker-compose.openwebui.yml`, a runnable [Open WebUI](docs/open-webui-integration.md) demo of the OpenAI-compatible API.\n\nThe compose files publish EDDI (and Keycloak) on `127.0.0.1` only. To reach them from another host, set `EDDI_BIND=0.0.0.0` (and `KEYCLOAK_BIND` for Keycloak) in `.env` — with authentication on.\n\nThe Ollama overlay pulls `llama3.2:3b` on first start and keeps models in a named volume; override with `OLLAMA_PULL_MODEL=qwen3:4b`, or set it empty to skip the pull. It also sets `EDDI_OLLAMA_DEFAULT_BASE_URL`, so the agent wizard and the setup API pre-fill a base URL that resolves from inside the container — the one thing that trips up every first local-LLM agent, because `localhost` there is the container, not the host.\n\n`docker-compose.ollama-nvidia.yml` adds GPU access to that Ollama and needs two things of the host, neither of which it degrades gracefully without: **Docker Compose 2.30.0 or newer**, which is where the `gpus` service attribute was introduced — older versions fail on it, so check `docker compose version` — and the **NVIDIA Container Toolkit** configured as a Docker runtime. `gpus: all` is a device *request*: with no GPU driver registered, the daemon cannot satisfy it and the container fails to start (`could not select device driver \"\" with capabilities: [[gpu]]`) rather than quietly falling back to the CPU. If you want Ollama on the CPU, leave this overlay off.\n\n```bash\ndocker pull labsai/eddi    # Pull latest from Docker Hub\n```\n\n→ [hub.docker.com/r/labsai/eddi](https://hub.docker.com/r/labsai/eddi)\n\n---\n\n## 💡 Why EDDI?\n\nMost multi-agent frameworks (LangGraph, CrewAI, AutoGen) are Python/Node libraries — great for prototyping, hard to govern in production. EDDI approaches from the opposite direction: **a deterministic engine built to safely govern non-deterministic AI.**\n\n| Dimension          | Typical Python/Node Frameworks           | EDDI                                                                        |\n| ------------------ | ---------------------------------------- | --------------------------------------------------------------------------- |\n| **Concurrency**    | GIL or single-threaded event loop        | Java 25 Virtual Threads — true OS-level parallelism                         |\n| **Agent Logic**    | Embedded in application code             | Versioned JSON configurations — update behavior without redeployment        |\n| **Security Model** | Often relies on sandboxed code execution | No dynamic code execution at all; envelope-encrypted vault, SSRF protection |\n| **Compliance**     | Requires custom implementation           | GDPR, HIPAA, EU AI Act infrastructure built-in                              |\n| **Audit Trail**    | Application-level logging                | HMAC-SHA256 immutable ledger with cryptographic agent signing               |\n| **Deployment**     | pip/npm + manual infrastructure          | One-command Docker install, Kubernetes/OpenShift-ready                      |\n\n> _\"The engine is strict so the AI can be creative.\"_ — [Project Philosophy](docs/project-philosophy.md)\n\n---\n\n## 📸 See It In Action\n\n<table>\n<tr>\n<td width=\"50%\">\n<p align=\"center\"><strong>📊 Dashboard</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-dashboard-1.png\" alt=\"EDDI Dashboard\" />\n<p><em>Platform overview with active agents, workflows, quick actions, and recent conversations</em></p>\n</td>\n<td width=\"50%\">\n<p align=\"center\"><strong>🤖 Agent Fleet</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-agents-1.png\" alt=\"Agents List\" />\n<p><em>All deployed agents at a glance with status, descriptions, and one-click chat</em></p>\n</td>\n</tr>\n<tr>\n<td width=\"50%\">\n<p align=\"center\"><strong>💬 Live Conversation</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-conversation-1.png\" alt=\"Conversation View\" />\n<p><em>Real-time conversation with visible actions, step timing, and tool calls</em></p>\n</td>\n<td width=\"50%\">\n<p align=\"center\"><strong>🗣️ Multi-Agent Debate</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-group-conversations-1.png\" alt=\"Group Conversations\" />\n<p><em>Peer Review with phased discussion: Opinion → Critique → Revision → Synthesis</em></p>\n</td>\n</tr>\n<tr>\n<td width=\"50%\">\n<p align=\"center\"><strong>🛡️ Secrets Vault</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-secret-vault-1.png\" alt=\"Secrets Vault\" />\n<p><em>Envelope-encrypted secrets with rotation tracking, checksums, and per-agent access control</em></p>\n</td>\n<td width=\"50%\">\n<p align=\"center\"><strong>💰 Tenant Quotas</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-quotas-1.png\" alt=\"Tenant Quotas\" />\n<p><em>Rate limits, cost budgets, and live usage monitoring per tenant</em></p>\n</td>\n</tr>\n</table>\n\n<details>\n<summary><strong>More screenshots: LLM Config, Logs, User Memory, Schedules, Agent Detail</strong></summary>\n\n<table>\n<tr>\n<td width=\"50%\">\n<p align=\"center\"><strong>⚡ LLM Task Configuration</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-agents-llm-config-1.png\" alt=\"LLM Configuration\" />\n<p><em>System prompt, model parameters, cascading, RAG, context window, and budget settings</em></p>\n</td>\n<td width=\"50%\">\n<p align=\"center\"><strong>📋 Real-Time Logs</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-logs-1.png\" alt=\"Logs\" />\n<p><em>Live log stream with per-call cost tracking, token counts, warnings, and errors</em></p>\n</td>\n</tr>\n<tr>\n<td width=\"50%\">\n<p align=\"center\"><strong>🧠 Persistent User Memory</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-user-data-1.png\" alt=\"User Data\" />\n<p><em>Cross-session memory with categorized entries, visibility scoping, and conflict detection</em></p>\n</td>\n<td width=\"50%\">\n<p align=\"center\"><strong>⏰ Scheduled Execution</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-schedules-1.png\" alt=\"Schedules\" />\n<p><em>Cron jobs and heartbeats with fire history, retry logic, and dead-letter tracking</em></p>\n</td>\n</tr>\n<tr>\n<td width=\"50%\">\n<p align=\"center\"><strong>🔧 Agent Detail</strong></p>\n<img src=\"screenshots/eddi-v6-screenshot-agents-detail-1.png\" alt=\"Agent Detail\" />\n<p><em>Full agent config: environments, workflows, A2A, security, capabilities, and memory policy</em></p>\n</td>\n<td width=\"50%\">\n</td>\n</tr>\n</table>\n\n</details>\n\n---\n\n## ✨ Features\n\n### 🤖 Multi-Agent Orchestration\n\n- 🔀 **Intelligent Routing** — Direct conversations to different agents based on context, rules, and intent\n- 🗣️ **Group Conversations** — Multi-agent debates with 7 built-in discussion styles: Round Table, Peer Review, Devil's Advocate, Delphi, Debate, Task Force, and Negotiation\n- 🔄 **Follow-up & Continue** — After a group discussion completes, follow up with any specific member agent or continue all phases with a new question — agents retain full context across rounds\n- 💬 **Slack Integration** — Deploy agents to Slack channels and run multi-agent debates directly in threads\n- 🪆 **Nested Groups** — Compose groups of groups for tournament brackets, red-team vs blue-team, and panel reviews\n- 🤖 **Dynamic Agents** — Create, recruit, and delegate to new agents at runtime during group discussions with configurable guardrails\n- 🗳️ **Group Voting** — `VOTE` phases collect explicit ballots (majority or approval, weighted, quorum-gated) and record a decision with the full tally, the raw ballots, and the losing side's dissents\n- 📋 **Shared Artifacts** — A blackboard members co-edit through tools, with compare-and-set concurrency and declarative JSON-Schema, regex, or max-length validators — never an LLM merge\n- 🧑‍🤝‍🧑 **Humans as Members** — A person can hold a seat in the group: their turn pauses the discussion until they answer, or the configured timeout policy resolves it\n- 🎚️ **Facilitator** — An optional facilitator agent is briefed at checkpoints and picks one move from a config-enumerated list (end, extend, call a vote, recruit, escalate) — bounded adaptation, never free-form orchestration\n- 🤝 **Negotiation** — Typed two-party bargaining: positions → proposals → a quoted concession ledger → signed acceptances, with arbitration skipped once agreement is reached\n- 🎯 **Bid-Based Assignment** — Contract-Net-lite task auctions: eligible members bid blind in parallel, highest confidence wins, with deterministic tie-break and fallback to role assignment\n- 🎓 **Team Memory** — A `RETRO` phase distils lessons into team-owned group memory, so they surface in every member's later discussions — institutional knowledge that compounds run over run\n- 🏢 **Standing Teams** — A persistent workspace per group: a backlog that survives between discussions, cron cadences that pull from it, cross-run retry of unverified work, and running team metrics\n- 📦 **Preset Group Templates** — Five packaged, validated group configs (research pod, editorial team, ops task force, decision board, negotiation table) — instantiate by assigning agents to named roles, not by hand-writing phases\n- 📊 **Discussion Overview** — The Manager and the Workforce board render a running discussion as a phase rail, a members × phases matrix, and a roster of one-line member stances, updated live ([details](docs/group-conversations.md#member-stances-the-overview-dashboard))\n- 👥 **Managed Conversations** — Intent-based auto-routing with one conversation per user per intent ([details](docs/managed-agents.md))\n- 🎯 **Capability Matching** — Discover and route to agents by skill, confidence score, and custom attributes\n- 🧙 **Platform Operator** — Meta-agent that reads and operates the deployment — including creating other agents — with every write behind a human approval gate ([how it works](docs/architecture.md#case-study-the-platform-operator))\n- 🔁 **Agent Version Following** — Running conversations move to a newer agent version only when its author saved it as *compatible*; every other save is a breaking change, and the Manager previews what a deployment does to live conversations ([details](docs/deployment-management-of-agents.md#running-conversations-and-new-agent-versions))\n\n### 🧠 LLM Provider Support (19 Providers)\n\n| Category             | Providers                                                             |\n| -------------------- | --------------------------------------------------------------------- |\n| **Cloud APIs**       | OpenAI · Anthropic Claude · Google Gemini · Mistral AI                |\n| **Enterprise Cloud** | Azure OpenAI · Amazon Bedrock · Oracle GenAI · Google Vertex AI       |\n| **Self-Hosted**      | Ollama · Jlama · Hugging Face                                         |\n| **OpenAI-compatible** | xAI Grok · DeepSeek · Moonshot Kimi · Alibaba Qwen · Z.ai GLM · MiniMax · OpenRouter · Groq |\n| **Any endpoint**     | Anything else OpenAI-compatible (Cohere, gateways, etc.) via `baseUrl` |\n\n- 🔀 **Multi-Model Cascading** — Start with cheap/fast models, escalate to powerful ones based on confidence ([details](#-smart-model-cascading))\n- 📋 **JSON Response Mode** — `jsonResponseFormat` policy (`auto` | `on` | `off`) negotiates structured JSON output across all execution paths with provider-aware rules\n- 🔧 **Tool Calling** — Native function/tool calling across all providers that support it\n- 🗄️ **Tool Result Caching** — Per-tool cache scoping (`GLOBAL`, `USER`, `CONVERSATION`) to avoid redundant calls; fail-safe to `USER` on misconfiguration\n\n### 🔗 Standards & Interoperability\n\nEDDI implements open standards — not proprietary APIs:\n\n| Standard                                                             | Role                            | What It Enables                                                                                          |\n| -------------------------------------------------------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------- |\n| **[MCP](https://modelcontextprotocol.io/)** (Model Context Protocol) | Server (80+ tools) + Client    | Control EDDI from Antigravity, Claude Desktop, Cursor, Windsurf, or any MCP client — [setup guide](docs/mcp-server.md#client-configuration). On an authenticated instance `/mcp` is an OAuth protected resource, so clients [sign themselves in](docs/mcp-server.md#the-client-signs-itself-in-preferred). Connect agents to external [MCP tool servers](docs/mcp-client.md) |\n| **[A2A](https://google.github.io/A2A/)** (Agent-to-Agent Protocol)   | Full implementation             | Cross-platform agent communication, Agent Cards, and skill discovery                                     |\n| **[OpenAPI](https://www.openapis.org/)** 3.1                         | Native generation + consumption | Auto-generated spec. Paste any OpenAPI spec → get a fully deployed API-calling agent                     |\n| **OAuth 2.0 / OIDC**                                                 | Keycloak integration            | Authentication, authorization, and multi-tenant isolation. Outbound, [connections](docs/connections.md) give agents per-user OAuth grants to external systems |\n| **OpenAI Chat Completions**                                          | Server (`/v1`, off by default)  | Deployed agents appear as OpenAI models to [Open WebUI](docs/open-webui-integration.md), the `openai` SDK, LangChain, LiteLLM, or any OpenAI-compatible client |\n| **SSE** (Server-Sent Events)                                         | Streaming transport             | Token-by-token chat responses, including most tool-enabled turns, which stream over the provider's streaming transport instead of going silent until the tool loop finishes (a single-chunk fallback still applies to cascade agents, providers without a streaming builder, and a few other configurations) — plus a live `tool_call` event for \"Using {tool}…\" status, group discussion feeds, and live log streaming |\n\n### 💭 Memory & Context Management\n\n- 💾 **Persistent User Memory** — Agents remember facts, preferences, and context across conversations via structured key-value entries with visibility scoping (`self`, `group`, `global`)\n- 🧠 **LLM Memory Tools** — Built-in tools agents can call to read, write, and search their own persistent memory; [guardrails](docs/user-memory.md#guardrails) keep the model to its own `self` memories unless the agent allows more\n- 💤 **Dream Consolidation** — Background memory maintenance: stale entry pruning, contradiction detection, and fact summarization (inspired by [Anthropic's](https://www.anthropic.com/research) research on background memory consolidation)\n- 🪟 **Token-Aware Windowing** — Intelligent context packing with model-specific tokenizer support and anchored opening steps\n- 📝 **Rolling Summary** — Incremental LLM-powered summarization of older turns with a **Conversation Recall Tool** for drill-back into compressed history\n- 🔧 **Property Extraction** — Config-driven slot-filling with `longTerm` / `conversation` / `step` scoping, plus `secret` for values that go straight into the vault — EDDI's importance extraction mechanism\n- 🛡️ **Memory Policy (Commit Flags)** — Strict write discipline marks failed task output as uncommitted (hidden from LLM context) and injects concise error digests for graceful degradation\n- 🧹 **Tool Context Ceiling** — `maxToolContextTokens` caps tool output within a single turn (default 60k tokens), evicting oldest tool exchanges to prevent provider context-window errors while preserving tool-call pairing\n- 🔄 **Conversation State** — Full history with undo/redo support\n\n### 📚 RAG (Retrieval-Augmented Generation)\n\n- 📦 **8 Embedding Providers** — OpenAI, Azure OpenAI, Ollama, Mistral, Bedrock, Cohere, Google Gemini, Vertex AI — queries and documents are embedded asymmetrically where the model supports it\n- 🗄️ **6 Vector Stores** — pgvector, Chroma, In-Memory, MongoDB Atlas, Elasticsearch, Qdrant\n- 🕷️ **Web Crawler Sources** — A knowledge base can crawl a website itself: robots-aware, sitemap-driven, bounded by depth, page count and time budget, with deleted pages tombstoned on later runs ([details](docs/rag.md#ingestion-sources))\n- 📄 **File Uploads** — Upload PDF, Word, Excel, PowerPoint, CSV, HTML, Markdown and text files to a knowledge base; the content, not the file name, decides the format\n- ⏱️ **Scheduled Ingestion** — Each source runs on its own cron or on demand, with preview, purge and a run history of counters and errors — all editable in the Manager's knowledge-base editor\n- 🌐 **httpCall RAG** — Zero-infrastructure RAG via any search API (BM25, Elasticsearch, custom)\n- 📥 **REST Ingestion API** — Async document ingestion with status tracking and in-place replacement of an earlier version\n\n### 🛠️ Built-In AI Agent Tools\n\n| Tool                                           | Description                                                                   |\n| ---------------------------------------------- | ----------------------------------------------------------------------------- |\n| 🔍 **Web Search**                              | DuckDuckGo or Google Custom Search                                            |\n| 🧮 **Calculator**                              | Sandboxed recursive-descent math parser (no `eval()`, no code injection)      |\n| 🌐 **Web Scraper**                             | SSRF-protected, size-capped extraction of web pages as Markdown               |\n| 📄 **PDF Reader**                              | SSRF-protected document extraction                                            |\n| ☁️ **Weather** · 🕐 **DateTime**               | Real-time data tools                                                          |\n| 📊 **Data Formatter** · 📝 **Text Summarizer** | Data transformation tools                                                     |\n| 🔌 **HTTP Calls as Tools**                     | Expose your own REST APIs as LLM-callable tools with full security sandboxing |\n| 🧠 **User Memory**                             | Read/write/search persistent user memory                                      |\n| 🔙 **Conversation Recall**                     | Drill back into summarized conversation history                               |\n| 📎 **Multimodal Attachments**                  | Image, PDF, audio, and video input with MIME-based routing                    |\n\n### 📎 Multimodal Attachments\n\n- 📤 **3 Input Paths** — URL reference, base64 inline, or file upload (`POST /conversations/{id}/attachments` with multipart/form-data)\n- 🗄️ **DB-Agnostic Storage** — GridFS (MongoDB) or bytea (PostgreSQL) via `IAttachmentStore` SPI with grant-based access control and per-tenant quotas\n- 📄 **Hybrid PDF Extraction** — PDFs are auto-extracted to text (shared `AttachmentTextExtractor`) and forwarded as inline context to any LLM, not just vision models\n- 🔍 **readAttachment Tool** — Agents can recall attachments from earlier turns in multi-turn conversations\n- 🧠 **Model Capability Gating** — `ModelCapabilityService` routes images to vision-capable LLMs and falls back to text metadata for others\n- 🔀 **Content-Type Routing** — `contentTypeMatcher` behavior rule condition routes `image/*`, `application/pdf`, etc. to different workflows\n- 👥 **Group Parity** — Attachments fan out with grant injection so group member agents can access the original user's files\n- 🗑️ **GDPR Cleanup** — `deleteByConversation()` cascades to attachment storage when conversations are erased\n\n### ⏰ Scheduled Execution & Heartbeats\n\n- 🫀 **Heartbeat Triggers** — Periodic agent wake-ups at configurable intervals for proactive behavior (inspired by [OpenClaw's](https://openclaw.ai) heartbeat architecture)\n- ⏲️ **Cron Scheduling** — Standard cron expressions for timed agent execution\n- 🔄 **Conversation Strategies** — `persistent` (reuse same conversation across fires) or `new` (fresh context each time)\n- 📊 **Fire Logging** — Complete execution history with status, duration, cost tracking, and retry logic\n- 🌙 **Dream Cycles** — Scheduled background memory consolidation with cost ceilings per run\n\n### 📈 Smart Model Cascading\n\n- 📉 **Cost Optimization** — Try cheap/fast models first, escalate to powerful models only when confidence is low\n- 📊 **4 Confidence Strategies** — Structured output, heuristic, judge model, or none\n- 💰 **Per-Conversation Budgets** — Automatic cost tracking with budget caps and eviction\n- 🏢 **Tenant Cost Ceilings** — Monthly cost budgets per tenant with automatic enforcement\n- 🔢 **Tenant Agent Quotas** — `maxAgentsPerTenant` enforcement on agent deployment\n\n### ✋ Human-in-the-Loop Governance\n\n- 🚦 **Turn-Level Approval** — `PAUSE_CONVERSATION` action halts the entire pipeline; new user input returns `409 Conflict` until a human resumes\n- 🔧 **Per-Tool-Call Gating** — Individual tool invocations can require human approval before execution, with glob-pattern allow/exempt lists across built-in, HTTP, MCP, A2A, dynamic, memory, and recall tools\n- 👥 **Group Phase Approval** — Multi-agent discussion phases can require human sign-off at `PHASE` or `TASK` granularity\n- 🧑‍🤝‍🧑 **Humans in the Room** — Beyond approving, a human can be a full group member with their own speaking turn; a facilitator can also pause a discussion to put a question to a named principal\n- ⏱️ **Timeout Policies** — `WAIT_INDEFINITELY`, `AUTO_APPROVE`, `AUTO_REJECT`, or `ABORT` when humans don't respond in time\n- 🔁 **No-Progress Guard** — Detects infinite approval loops (identical pause fingerprints after automated decisions) and breaks the cycle\n- 💬 **Slack Approvals** — Interactive Block Kit cards with redacted argument previews and approver whitelists\n- 🔌 **MCP Approvals** — External clients can list pending approvals and approve/reject via MCP tools\n- 🖥️ **Manager Approvals** — One page lists pending conversation and group-phase approvals and resolves them\n- 🔄 **Crash Recovery** — Pending approvals survive server restarts; timeout timers are re-armed automatically\n\n### 🔐 Enterprise Security & Compliance\n\n<details open>\n<summary><strong>Security Architecture</strong></summary>\n\n- 🏦 **Secrets Vault** — Envelope encryption (PBKDF2 + AES-256-GCM) with tenant-scoped DEK/KEK rotation. Never plaintext in DB. Each secret names the agents allowed to use it, checked at deploy time, and that grant can be edited without re-entering the value ([details](docs/secrets-vault.md#agent-grants-allowedagents))\n- 🔗 **Connections** — One credential model for every outbound call: `${connection:name}` resolves per request to an org-wide key or the end user's own OAuth grant ([details](docs/connections.md))\n- 🪪 **Caller Identity** — An HTTP call can act as the signed-in user with `${caller:token}`, released only to the caller's own origin or to EDDI itself and never persisted ([details](docs/httpcalls.md#calling-as-the-signed-in-user))\n- 🤫 **Secret Context Values** — A client can pass a credential as context with `\"secret\": true`: usable for one turn, never stored or returned ([details](docs/passing-context-information.md#secret-context-values))\n- 🛡️ **SSRF Protection** — All tools validate URLs against private IPs, internal hostnames, and non-HTTP schemes before any request; credentialed requests don't follow redirects, and downloads are size-capped\n- 🔒 **Sandboxed Evaluation** — Recursive-descent math parser only. No `eval()`, no script engines, no reflection-based execution\n- 🔑 **OAuth 2.0 / Keycloak** — Multi-tenant authentication, authorization, and role-based access control; the token audience is enforced and a token that names no user is refused\n- 🗂️ **Workspaces & Sharing** — Opt-in per-user and per-team spaces for agents and their configuration, with explicit `USE` / `VIEW` / `EDIT` / `OWN` shares ([details](docs/workspaces.md))\n- 🧾 **Restricted Templates** — Runtime templates run in a locked-down Qute engine (allow-listed namespaces and sections, bounded output), and fetched data is never rendered as a template ([details](docs/security.md#runtime-template-engine))\n- ✍️ **Agent Signing** — Ed25519 cryptographic identity per agent; audit entries signed with agent private keys\n- 🚫 **No Dynamic Code Execution** — Custom logic runs in external MCP servers, outside the EDDI security perimeter\n\n</details>\n\n<details open>\n<summary><strong>Regulatory Compliance</strong></summary>\n\n| Regulation                                             | EDDI Support                                                                                                                                   |\n| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |\n| **[EU AI Act](https://artificialintelligenceact.eu/)** | Immutable HMAC-SHA256 audit ledger, decision traceability, risk classification guidance                                                        |\n| **[GDPR](https://gdpr.eu/)**                           | Cascading data erasure (Art. 17), data portability (Art. 15/20), restriction of processing (Art. 18), per-category retention, pseudonymization |\n| **[CCPA](https://oag.ca.gov/privacy/ccpa)**            | Right to delete, right to know, data portability                                                                                               |\n| **[HIPAA](https://www.hhs.gov/hipaa/)**                | Deployment guide, BAA template, LLM provider BAA matrix, session timeout guidance                                                              |\n| **International**                                      | PIPEDA 🇨🇦 · LGPD 🇧🇷 · APPI 🇯🇵 · POPIA 🇿🇦 · PDPA 🇸🇬🇹🇭🇲🇾 · PIPL 🇨🇳 compatibility documented                                                      |\n\n- 📜 **Audit Ledger** — Every agent decision recorded in a write-once, HMAC-secured, append-only ledger\n- 🔍 **Compliance Startup Checks** — Advisory warnings on boot for TLS and database encryption gaps\n- 🗑️ **GDPR Orchestration** — One-call cascading erasure across every store that holds a user's data (memories, conversations, attachments, group transcripts, schedules, OAuth grants, …) plus audit trail pseudonymization, reporting any step that did not complete\n- 📤 **Data Portability** — Complete user data export (memories, conversations, audit entries) via REST and MCP\n\n</details>\n\n### ⚙️ Configuration-Driven Architecture\n\n- 📄 **JSON Configs, Not Code** — Agent behavior defined in versioned, diffable JSON documents\n- 🔧 **Lifecycle Pipeline** — Pluggable task pipeline: Input → Parse → Rules → API/LLM → Output\n- 📦 **Composable Agents** — Agents assembled from reusable, version-controlled workflows and extensions\n- 🧪 **Behavior Rules** — IF-THEN logic engine for routing, orchestration, and business logic\n- 📤 **Import / Export** — Agents portable as ZIP files with automatic secret scrubbing on export\n- 🔄 **Agent Sync** — Live instance-to-instance sync with structural matching, content diffing, and selective resource picking — no ZIP intermediary needed\n- 📝 **Prompt Snippets** — Reusable, versioned system prompt building blocks available as `{snippets.safety_rules}`\n- 🌐 **Global Variables** — Deployment-wide values such as a default model, referenced as `{vars.default-model}` in any config ([details](docs/global-variables.md))\n- 📎 **Content Type Routing** — MIME-based behavior rule conditions for multimodal attachment routing\n\n### 🚀 Cloud-Native & Observable\n\n- 🐳 **One-Command Install** — Interactive wizard sets up EDDI + database via Docker\n- ☸️ **Kubernetes / OpenShift** — Kustomize overlays, Helm charts, PDB, NetworkPolicy (no HPA: EDDI is single-writer per conversation, so both delivery paths pin one replica)\n- 📊 **Prometheus & Grafana** — 50+ Micrometer metrics at `/q/metrics` (tools, vault, memory, scheduling, conversations). Pre-built [Grafana dashboard](docs/monitoring/eddi-grafana-dashboard.json) included\n- 🔭 **OpenTelemetry Tracing** — Per-task distributed traces via OTLP (Jaeger, Tempo, Datadog). Every pipeline task emits a span named `eddi.pipeline.task` carrying `eddi.task.id`, `eddi.task.type`, `eddi.task.index`, `eddi.conversation.id` and `eddi.agent.id`. The equivalent *metric* tags are un-prefixed (`task.id`, `task.type`)\n- 🤖 **LLM Telemetry** — Every model call, on every provider, streaming or not, is timed and counted (`eddi.llm.request.duration`, `eddi.llm.tokens`, `eddi.llm.request.errors`) and traced as a `gen_ai.client.inference` span\n- 🩺 **Health Checks** — Liveness & readiness probes at `/q/health/live` and `/q/health/ready`\n- 🔄 **NATS JetStream** — Async event bus for distributed processing\n- 🛟 **Error Handling & Recovery** — Automatic retry with exponential backoff, MCP circuit breakers (open after 3 failures within 60 s), LLM response validation (`onEmpty` / `onTruncation` / `onRefusal`), streaming timeout retry, and admin endpoint to reset stuck conversations\n- ⚡ **Virtual Threads** — Java 25 virtual threads for true OS-level concurrency (no Python GIL or Node.js event loop bottleneck)\n- 🗃️ **DB-Agnostic** — Choose MongoDB or PostgreSQL; switch with one env var. Single Docker image for both\n- 🏗️ **Red Hat Certified** — Container certification with automated preflight checks in CI/CD\n\n> **📖 Monitoring Guide:** See [docs/monitoring/monitoring-guide.md](docs/monitoring/monitoring-guide.md) for architecture overview, metrics reference, alerting rules, and a production checklist.\n\n### 🖥️ Manager Dashboard & Chat UI\n\nBoth UIs live in this repository (`ui/manager`, `ui/chat`) and are built into the EDDI jar and Docker image — nothing to deploy separately.\n\n- 🎨 **React 19 Manager** (`/manage`) — Admin dashboard for agent building, testing, deployment, and monitoring, with the Platform Operator, an agent wizard, and editors for every resource type, including knowledge-base ingestion sources\n- 👥 **Workforce** (`/workforce`) — A workspace for group conversations: boards, member threads, a live discussion overview, and history\n- 💬 **Chat UI** (`/chat`) — Standalone React chat with SSE streaming and Keycloak auth\n- ✋ **Approvals, Connections & Sharing** — Pages for pending HITL approvals, connections and linked accounts, and sharing resources between users and teams\n- 🔍 **Audit Trail Viewer** — Timeline-based compliance and debugging UI\n- 📋 **Logs Panel** — Live SSE log streaming + searchable history\n- 🔑 **Secrets Manager** — Write-only vault UI with copy-reference support\n- 🌍 **11 Languages** — English, German, Spanish, French, Portuguese, Chinese, Japanese, Korean, Arabic (RTL), Hindi, Thai\n\n---\n\n## 📖 Documentation\n\n| Guide                                                        | Description                                        |\n| ------------------------------------------------------------ | -------------------------------------------------- |\n| **[Getting Started](docs/getting-started.md)**               | Setup and first steps                              |\n| **[Developer Quickstart](docs/developer-quickstart.md)**     | Build your first agent in 5 minutes                |\n| **[Manager Dashboard](docs/agent-manager-gui.md)**           | The built-in admin UI and the Workforce workspace  |\n| **[Architecture](docs/architecture.md)**                     | Deep dive into EDDI's design and pipeline          |\n| **[LLM Configuration](docs/langchain.md)**                   | Connecting to 19 LLM providers                     |\n| **[Behavior Rules](docs/behavior-rules.md)**                 | Configuring agent routing logic                    |\n| **[Agent Config Authoring](docs/agent-config-authoring.md)** | Rules and pitfalls for writing agent JSON          |\n| **[HTTP Calls](docs/httpcalls.md)**                          | External API integration                           |\n| **[RAG](docs/rag.md)**                                       | Knowledge bases, crawled and uploaded sources, retrieval |\n| **[MCP Server](docs/mcp-server.md)**                         | 80+ tools for AI-assisted agent management         |\n| **[MCP Client](docs/mcp-client.md)**                         | Connecting agents to external MCP servers          |\n| **[A2A Protocol](docs/a2a-protocol.md)**                     | Agent-to-Agent peer communication                  |\n| **[OpenAI-Compatible API](docs/open-webui-integration.md)**  | Agents as OpenAI models for Open WebUI & SDKs      |\n| **[Slack Integration](docs/slack-integration.md)**           | Deploy agents to Slack and run group discussions   |\n| **[Connections](docs/connections.md)**                       | One credential model, including per-user OAuth     |\n| **[Group Conversations](docs/group-conversations.md)**       | Debate, voting, artifacts, standing teams          |\n| **[User Memory](docs/user-memory.md)**                       | Cross-conversation fact retention                  |\n| **[Memory Policy](docs/memory-policy.md)**                   | Commit flags and strict write discipline            |\n| **[Model Cascading](docs/model-cascade.md)**                 | Cost-optimized multi-model routing                 |\n| **[Human-in-the-Loop](docs/hitl.md)**                        | Approval gates, timeout policies, Slack & MCP surfaces |\n| **[Managed Agents](docs/managed-agents.md)**                 | Intent-based routing, one conversation per user    |\n| **[Scheduling & Heartbeats](docs/scheduling.md)**            | Cron schedules, heartbeats, dream consolidation    |\n| **[Deployment Management](docs/deployment-management-of-agents.md)** | Deploying, undeploying, and agent version following |\n| **[Agent Sync](docs/agent-sync-guide.md)**                   | Live instance-to-instance sync and upgrade imports |\n| **[Import / Export](docs/import-export-an-agent.md)**        | ZIP-based agent portability and merge              |\n| **[Prompt Snippets](docs/prompt-snippets-guide.md)**         | Reusable system prompt building blocks             |\n| **[Attachments](docs/attachments-guide.md)**                 | Multimodal attachment pipeline                     |\n| **[Capability Matching](docs/capability-match-guide.md)**    | A2A skill discovery and routing                    |\n| **[Security](docs/security.md)**                             | SSRF protection, sandboxing, and hardening         |\n| **[Workspaces](docs/workspaces.md)**                         | Per-user and per-team isolation, and sharing       |\n| **[Secrets Vault](docs/secrets-vault.md)**                   | Envelope encryption and auto-vaulting              |\n| **[Global Variables](docs/global-variables.md)**             | Deployment-wide values for every config            |\n| **[Audit Ledger](docs/audit-ledger.md)**                     | EU AI Act-compliant audit trail                    |\n| **[Tenant Quotas](docs/tenant-quotas.md)**                   | Per-tenant usage limits, editable at runtime       |\n| **[Kubernetes](docs/kubernetes.md)**                         | Deploy with Kustomize or Helm                      |\n| **[Configuration Reference](docs/configuration-reference.md)** | Every `eddi.*` property, its default and env var |\n| **[Upgrading from 5.x](docs/upgrading-from-5x.md)**          | First boot of an EDDI 5 database on 6.x            |\n| **[Upgrading from 6.4](docs/upgrading-from-6.4.md)**         | What an existing 6.4 deployment must change for 6.5 |\n| **[Monitoring & Tracing](docs/monitoring/monitoring-guide.md)** | Prometheus, Grafana, OpenTelemetry, alerting     |\n| **[Red Hat & OpenShift](docs/redhat-openshift.md)**          | RHEL support, certified container, automated release |\n| **[Full Documentation](https://docs.labs.ai/)**              | Complete documentation site                        |\n\n---\n\n## 📋 Compliance & Privacy\n\nEDDI provides built-in infrastructure for regulatory compliance:\n\n| Guide                                                    | Covers                                                                                                |\n| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |\n| **[GDPR / CCPA](docs/gdpr-compliance.md)**               | Data erasure, export, Art. 18 restriction of processing, per-category retention, and consent guidance |\n| **[HIPAA](docs/hipaa-compliance.md)**                    | Healthcare deployment guide — encryption, BAAs, LLM provider matrix, session management               |\n| **[EU AI Act](docs/eu-ai-act-compliance.md)**            | AI risk classification, decision traceability, immutable audit ledger                                 |\n| **[Privacy & Data Processing](PRIVACY.md)**              | Data flows, LLM provider matrix, international regulations (PIPEDA, LGPD, APPI, POPIA, PDPA, PIPL)    |\n| **[Compliance Data Flow](docs/compliance-data-flow.md)** | Single-page data flow diagram for auditors                                                            |\n| **[Incident Response](docs/incident-response.md)**       | Breach response runbook (GDPR 72h, CCPA 45 days, HIPAA 60 days)                                       |\n\n---\n\n## 🏗️ Development\n\n### Prerequisites\n\n| Tool           | Version | Notes                                                             |\n| -------------- | ------- | ----------------------------------------------------------------- |\n| **Java (JDK)** | 25      | [Eclipse Temurin](https://adoptium.net/) recommended              |\n| **Maven**      | 3.9+    | Bundled via `mvnw` / `mvnw.cmd` wrapper — no install needed       |\n| **MongoDB**    | 6.0+    | Local instance or Docker (`docker run -d -p 27017:27017 mongo:7`) |\n| **Docker**     | Latest  | For integration tests and container builds                        |\n| **Node.js**    | —       | Not required: Maven downloads Node 24 into `ui/node/` to build the Manager and Chat UIs. Install it only to run `npm run dev` in `ui/manager` or `ui/chat` |\n| **mise**       | Optional | [`mise.toml`](mise.toml) pins the exact JDK, Maven and Node versions and offers the common commands as tasks (`mise run dev`, `mise run test`) |\n\n> **Windows users:** Replace `./mvnw` with `.\\mvnw.cmd` in all commands below.\n\n### Quarkus Dev Mode\n\nDev mode starts the application with **live reload** — code changes are picked up automatically without restarting:\n\n```bash\n# Linux / macOS\n./mvnw compile quarkus:dev '-Djvm.args=--add-modules=jdk.incubator.vector'\n\n# Windows (PowerShell)\n.\\mvnw.cmd compile quarkus:dev '-Djvm.args=--add-modules=jdk.incubator.vector'\n```\n\n`-Djvm.args` hands the forked dev JVM the same `--add-modules=jdk.incubator.vector` flag the container image sets. Only `jlama` (in-process) agents need it — without it Jlama silently falls back to scalar tensor operations and answers far too slowly — so you may drop it if you never run one. `mise run dev` passes it for you.\n\nThen open [http://localhost:7070](http://localhost:7070). The Quarkus Dev UI is available at [http://localhost:7070/q/dev](http://localhost:7070/q/dev).\n\n> **💡 The Manager and Chat UI build with Maven, at packaging time.** Their sources live in `ui/manager` and `ui/chat`. `./mvnw package` (and `verify`, `install`) builds them into the jar, about two minutes; `compile`, `test` and dev mode never touch npm, so dev mode serves `/manage` only after a `package`. For frontend work run `npm run dev` in `ui/manager` (port 3000, proxying to the backend on 7070). Upgrading an older checkout? Run `./mvnw clean` once.\n\nDev mode also enables:\n\n- **Continuous testing** — press `r` in the terminal to re-run tests on changes\n- **Dev UI** — browse endpoints, CDI beans, configuration, and health checks\n- **Live reload** — Java and resource changes apply instantly\n\n> **💡 Secrets Vault:** To use the secrets vault (storing API keys encrypted), set the master key before starting:\n>\n> ```bash\n> # Linux/macOS\n> export EDDI_VAULT_MASTER_KEY=my-dev-passphrase\n>\n> # Windows (PowerShell)\n> $env:EDDI_VAULT_MASTER_KEY = \"my-dev-passphrase\"\n>\n> # Or in a .env file (already in .gitignore)\n> echo \"EDDI_VAULT_MASTER_KEY=my-dev-passphrase\" > .env\n> ```\n>\n> Without this, the vault is disabled and secret management returns HTTP 503. Any passphrase works for local development. See [Secrets Vault](docs/secrets-vault.md) for production setup.\n\n### Maven Command Reference\n\n| Command                                                       | What It Does                                                                |\n| ------------------------------------------------------------- | --------------------------------------------------------------------------- |\n| `./mvnw compile quarkus:dev '-Djvm.args=--add-modules=jdk.incubator.vector'` | **Start dev mode** with live reload (port 7070). The flag is for `jlama` agents — see above |\n| `./mvnw compile`                                              | Compile sources only (fast feedback). Also runs the two `validate`-phase style gates, so it **fails** on an unused import (Checkstyle) or an unformatted file (`formatter:validate`) — neither edits your sources; run `./mvnw formatter:format` to fix formatting |\n| `./mvnw clean compile`                                        | Clean build — delete `target/` and recompile from scratch                   |\n| `./mvnw test`                                                 | Run **unit tests** (excludes `*IT.java` integration tests)                  |\n| `./mvnw package -DskipTests -DskipUi=true` | Build the jar **without** the Manager and Chat UIs (`compile` and `test` never build them) |\n| `./mvnw verify`                                               | Compile + unit tests + package. **Integration tests are skipped** — `skipITs` defaults to `true` in `pom.xml` |\n| `./mvnw verify -DskipITs=false`                               | **Full build** — adds the `*IT.java` integration tests (requires Docker). This is what CI runs |\n| `./mvnw validate`                                             | Run the **blocking style gates** — Checkstyle (`UnusedImports`/`RedundantImport` fail the build; `FileLength`/`LineLength` stay advisory) and `formatter:validate`, which reports unformatted files without touching them |\n| `./mvnw formatter:format`                                     | **Auto-format** Java sources using the project Eclipse formatter — the fix for a `formatter:validate` failure |\n| `./mvnw package -DskipTests`                                  | Build the JAR without running tests (for `install.sh --local`)              |\n| `./mvnw clean package '-Dquarkus.container-image.build=true'` | Build the app **+ Docker image**                                            |\n| `./mvnw package -Plicense-gen -DskipTests`                    | Generate **third-party licenses** (Red Hat certification)                   |\n| `./mvnw quarkus:dev -Dsuspend '-Djvm.args=--add-modules=jdk.incubator.vector'` | Start dev mode and **wait for debugger** on port 5005 |\n| `./mvnw quarkus:dev -Ddebug=false '-Djvm.args=--add-modules=jdk.incubator.vector'` | Start dev mode **without** the debug agent |\n\n<details>\n<summary><strong>Code coverage</strong></summary>\n\nJaCoCo is configured to run automatically during `./mvnw test`. After tests complete, find the coverage report at:\n\n```\ntarget/site/jacoco/index.html\n```\n\n</details>\n\n<details>\n<summary><strong>Useful system properties</strong></summary>\n\n| Property                                    | Default                     | Description                                    |\n| ------------------------------------------- | --------------------------- | ---------------------------------------------- |\n| `-Dquarkus.http.port=<port>`                | `7070`                      | Override the HTTP port                         |\n| `-Dmongodb.connectionString=<uri>`          | dev: `mongodb://localhost:27017/eddi`  | MongoDB connection, read by `PersistenceModule`. `quarkus.mongodb.connection-string` is a different key that only the health check reads |\n| `-Dmongodb.database=<name>`                 | `eddi`                      | MongoDB database name                          |\n| `-Dquarkus.profile=<profile>`               | `dev`                       | Active Quarkus profile (`dev`, `test`, `prod`) |\n| `-DskipTests`                               | `false`                     | Skip all tests                                 |\n| `-DskipITs`                                 | `true`                      | Skip integration tests only                    |\n| `-DskipUi` | `false` | Skip the npm build of `ui/manager` and `ui/chat` (the jar then serves no UI) |\n\n</details>\n\n### Build & Docker\n\n```bash\n# Build app + Docker image\n./mvnw clean package '-Dquarkus.container-image.build=true'\n\n# Build without container (for install.sh --local)\n./mvnw package -DskipTests\n\n# Generate third-party licenses (Red Hat certification)\n./mvnw package -Plicense-gen -DskipTests\n```\n\n### ☸️ Kubernetes\n\nNo shipped manifest creates the `eddi-secrets` Secret that holds the vault master\nkey — a Secret in the manifests would be reconciled on every `kubectl apply` and\noverwrite a live key, making everything already encrypted with it undecryptable.\nSo the Secret is created out-of-band, **before** the first apply. Without it the\nEDDI pod sits in `ContainerCreating` (`MountVolume.SetUp failed: secret\n\"eddi-secrets\" not found`) and never starts.\n\n```bash\n# Kustomize overlays — create the vault Secret first, then apply\nbash k8s/create-secrets.sh                 # PowerShell 7: pwsh -File .\\k8s\\create-secrets.ps1\n# ...plus the database credentials, which are no longer shipped: mongodb-secrets\n# (MongoDB runs authenticated) or postgres-secrets — commands in the Kubernetes Guide\nkubectl apply -k k8s/overlays/mongodb/     # MongoDB backend\nkubectl apply -k k8s/overlays/postgres/    # PostgreSQL backend\n\n# Quickstart (one-file manifest; same Secret step, see the Kubernetes Guide)\nkubectl apply -f https://raw.githubusercontent.com/labsai/EDDI/main/k8s/quickstart.yaml\n\n# Helm (renders the Secret itself, so the key is a required value). Local,\n# port-forward shape without OIDC: the two opt-ins are required, see the guide.\nhelm install eddi ./helm/eddi \\\n  --set eddi.vaultMasterKey=\"$(openssl rand -base64 24)\" \\\n  --set mongodb.rootPassword=\"$(openssl rand -base64 24)\" \\\n  --set eddi.security.allowUnauthenticatedMcp=true \\\n  --set eddi.security.allowUnauthenticatedSecretStore=true \\\n  --namespace eddi --create-namespace\n```\n\nIncludes overlays for auth (Keycloak), monitoring (Prometheus/Grafana), NATS messaging, Ingress, and production hardening (PDB, NetworkPolicy — deliberately no HPA).\nSee the [Kubernetes Guide](docs/kubernetes.md) for details, including the Keycloak upgrade note for existing installs.\n\n---\n\n## 🤝 Contributing\n\nWe welcome contributions! Please read our [Contributing Guide](CONTRIBUTING.md) for details on setting up your development environment, code style, commit conventions, and the pull request process.\n\nEvery PR is automatically checked by CI (build + tests), CodeQL (security), dependency review, and AI-powered code review.\n\n## 🔒 Security\n\nEDDI ships with security-by-default for production deployments:\n\n- **Authentication enforced** — `AuthStartupGuard` fails startup if OIDC is disabled in production without explicit opt-out; tokens must carry the `eddi-backend` audience and name a user\n- **Secrets encrypted at rest** — Envelope encryption (PBKDF2 → AES-256-GCM) with per-deployment salt. Never plaintext in DB. A weak vault master key stops a production boot\n- **Credentials only where configured** — A `${vault:…}`, `${connection:…}` or `${caller:…}` reference resolves only where the configuration wrote it, not when it arrives through conversation data (a value EDDI auto-vaulted itself is the one exception)\n- **SSRF protection** — All LLM tool HTTP calls go through `SafeHttpClient` with private IP blocking, redirect validation, and scheme enforcement\n- **Security headers** — `X-Content-Type-Options`, `X-Frame-Options`, `Content-Security-Policy` configured out of the box\n- **Loopback by default** — The Docker Compose files publish EDDI, Keycloak and the datastores on `127.0.0.1`, and the Helm chart and Kustomize overlays ship no default credentials\n- **CI/CD security gates** — Every push/PR is scanned by:\n  - **CodeQL** — Semantic SAST analysis with `security-extended` queries\n  - **Trivy** — CVE scanning for both filesystem dependencies and Docker images (blocking on CRITICAL/HIGH)\n  - **Gitleaks** — Git history scanning to prevent secret/credential leakage\n  - **CycloneDX** — SBOM generation for supply chain transparency\n  - **Jazzer** — Coverage-guided fuzz testing for security-critical parsers (PathNavigator, MatchingUtilities)\n  - All actions SHA-pinned to prevent supply-chain attacks\n\nFor vulnerability reports, see our [Security Policy](SECURITY.md). For architecture details, see [Security Architecture](docs/security.md).\n\n## 📜 Code of Conduct\n\nThis project follows the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).\n"}