Skip to content

Commit ea487fd

Browse files
feat: containerize DeepSQL Agent as fifth Compose service
Enterprise self-host no longer needs a host-side agent runtime. The new `deepsql-agent` service (agent/Dockerfile) serves the Agent tab, AI dashboards, Slack/CLI agent turns, and per-user profile provisioning on the compose network (:8787 / :8788). - Add agent/Dockerfile + docker-entrypoint.sh (DeepSQL-branded surface) - Wire deepsql-agent into docker-compose.yml; nginx proxies /agent-api to it - Default AGENT_WEBUI_URL / AGENT_PROVISIONER_URL to deepsql-agent - install.sh generates AGENT_PROVISION_SECRET and builds the agent image - Host setup-agent.sh remains for native/dev only (opt-in) - Docs, smoke-test, and status scripts refer to DeepSQL Agent throughout Co-authored-by: Venkat SF <venkatesh.sakamuri@stayflexi.com>
1 parent 4d0c523 commit ea487fd

17 files changed

Lines changed: 539 additions & 143 deletions

.dockerignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Shared by frontend (./Dockerfile) and deepsql-agent (agent/Dockerfile),
2+
# both of which use the repo root as build context.
3+
.git
4+
.github
5+
**/.venv
6+
**/venv
7+
**/node_modules
8+
**/__pycache__
9+
backend/target
10+
backend/.mvn/wrapper/maven-wrapper.jar
11+
*.log
12+
.env
13+
.env.*
14+
!.env.example
15+
dist
16+
coverage
17+
tmp
18+
.cursor
19+
.hermes

.env.example

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,23 @@ DEEPSQL_EMBEDDING_MODEL=text-embedding-3-large
128128
# profile which defaults to false.
129129
EMBEDDING_FAIL_OPEN=false
130130

131-
# ── Hermes agent (Agent tab + AI dashboards) ────────────────────────────────
132-
# Backend → Hermes for dashboards / Slack / CLI. Compose defaults this; only
133-
# override if Hermes listens elsewhere. Requires scripts/self-host/setup-agent.sh
134-
# (also run by install.sh unless DEEPSQL_SKIP_AGENT_SETUP=1).
135-
#AGENT_WEBUI_URL=http://host.docker.internal:8787
136-
#DEEPSQL_SKIP_AGENT_SETUP=0
131+
# ── DeepSQL Agent (Agent tab + AI dashboards) ───────────────────────────────
132+
# The fifth Compose service (`deepsql-agent`) serves the Agent tab, AI
133+
# dashboards, and Slack/CLI agent turns. install.sh auto-generates
134+
# AGENT_PROVISION_SECRET; Compose wires the rest. Override only for native
135+
# (non-Compose) development or a custom agent hostname.
136+
#
137+
# AGENT_WEBUI_URL Agent HTTP API. Compose default: http://deepsql-agent:8787
138+
# AGENT_PROVISIONER_URL Per-user profile provisioner. Compose default:
139+
# http://deepsql-agent:8788/provision
140+
# AGENT_PROVISION_SECRET Shared secret between backend and agent (required).
141+
# DEEPSQL_AGENT_PORT / DEEPSQL_AGENT_PROVISIONER_PORT — host port mappings.
142+
#
143+
#AGENT_WEBUI_URL=http://deepsql-agent:8787
144+
#AGENT_PROVISIONER_URL=http://deepsql-agent:8788/provision
145+
AGENT_PROVISION_SECRET=change-me-agent-provision-secret
146+
#DEEPSQL_AGENT_PORT=8787
147+
#DEEPSQL_AGENT_PROVISIONER_PORT=8788
137148
#DEEPSQL_SMOKE_AGENT=1
138149

139150
# ── Demo Data Seeding ───────────────────────────────────────────────────────
@@ -156,31 +167,15 @@ EMBEDDING_FAIL_OPEN=false
156167
# code reads any azure.openai.* property any more, so setting them changes nothing.
157168

158169
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
159-
# OPTIONAL — DeepSQL Agent runtime (chat TUI + the web Agent tab)
170+
# OPTIONAL — Native (non-Compose) DeepSQL Agent
160171
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
161-
# The agent surfaces — `deepsql agent` and the Agent tab — are served by a separate
162-
# runtime, not by the backend. There is no deepsql-agent container in this stack:
163-
# setup-agent.sh installs Hermes on the *host*, listening on :8787. That is why the
164-
# chat default reaches out of the container instead of across the Compose network.
165-
# Everything else in DeepSQL works without any of this.
166-
#
167-
# AGENT_WEBUI_URL where the agent runtime serves its API. Default
168-
# http://host.docker.internal:8787 (AgentChatClient.java:58),
169-
# which is right under Compose — but a native backend run has no
170-
# such host, so there it must be set to http://127.0.0.1:8787.
171-
# AGENT_PROVISIONER_URL per-user profile provisioning endpoint. Default
172-
# http://deepsql-agent:8788/provision (AgentBridgeService.java:65)
173-
# still names the container that does not exist here, so this one
174-
# must be set explicitly — under Compose and natively alike.
175-
# AGENT_PROVISION_SECRET shared secret for the above. Unset, the backend logs
176-
# "agent.provision-secret is unset — skipping" and never creates
177-
# the u-<user> profile, so the agent has no identity to run as.
178-
#
179-
# Native runs: start the provisioner with `python3 scripts/local-agent-provisioner.py`.
180-
# See AGENTS.md for the full sequence, and agent/README.md for the runtime itself.
172+
# Only needed when you run the backend with `mvn spring-boot:run` instead of
173+
# Compose. Point at a local agent process and start the provisioner:
174+
# python3 scripts/local-agent-provisioner.py
175+
# Or use the legacy host installer: ./scripts/self-host/setup-agent.sh
176+
# (set DEEPSQL_HOST_AGENT_SETUP=1). Prefer Compose for self-host / enterprise.
181177
#AGENT_WEBUI_URL=http://127.0.0.1:8787
182178
#AGENT_PROVISIONER_URL=http://127.0.0.1:8788/provision
183-
#AGENT_PROVISION_SECRET=
184179

185180
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
186181
# VECTOR STORE — choose one mode

CLAUDE.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ docker compose down # Stop
5454

5555
**Vault DB**: `jdbc:postgresql://localhost:5432/dba_agent` (postgres/postgres)
5656

57+
### Self-host Compose (5 services)
58+
59+
```bash
60+
./scripts/self-host/install.sh # builds + starts everything
61+
docker compose ps # postgres, valkey, backend, deepsql-agent, frontend
62+
```
63+
64+
The **DeepSQL Agent** is the fifth container (`agent/Dockerfile`): Agent tab, AI
65+
dashboards, Slack/CLI agent turns, and per-user profile provisioning on :8787/:8788.
66+
No host-side agent install is required for Compose deployments.
67+
5768
## Architecture
5869

5970
```
@@ -90,7 +101,7 @@ src/ # Frontend (React)
90101
91102
docs/ # Documentation
92103
mcp/ # DeepSQL Phase 1 MCP server (Node stdio wrapper around backend APIs)
93-
agent/ # DeepSQL Agent customization (persona, skills, skins; customized Hermes runtime)
104+
agent/ # DeepSQL Agent (persona, skills, skins, Dockerfile for the Compose service)
94105
```
95106

96107
## MCP Server

README.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,15 @@ is rejected. Changing width means migrating the column.
174174
./scripts/self-host/install.sh
175175
```
176176

177-
The installer generates your JWT secret, the credential-vault encryption key and the vault
178-
DB password, prompts for the first admin account, builds both images, starts the stack, and
179-
verifies pgvector is live. Unless you set `DEEPSQL_SKIP_AGENT_SETUP=1`, it also runs
180-
[`scripts/self-host/setup-agent.sh`](scripts/self-host/setup-agent.sh) to install Hermes under
181-
`~/.hermes/`, wire DeepSQL MCP, and start the webui on `0.0.0.0:8787` (required for the
182-
**Agent** tab and AI dashboard generation).
177+
The installer generates your JWT secret, the credential-vault encryption key, the vault
178+
DB password, and the DeepSQL Agent provision secret; prompts for the first admin account;
179+
builds the backend, frontend, and DeepSQL Agent images; starts the stack; and verifies
180+
pgvector is live. The **Agent** tab and AI dashboard generation are served by the
181+
`deepsql-agent` Compose service — no host-side agent install is required.
183182

184183
**The first build takes several minutes** — it compiles the Spring Boot backend with Maven
185-
inside the container and bundles the frontend with Vite. It has not hung. Later builds reuse
186-
the Docker layer cache.
184+
inside the container, bundles the frontend with Vite, and builds the DeepSQL Agent image.
185+
It has not hung. Later builds reuse the Docker layer cache.
187186

188187
Then open **http://localhost:3000** and log in with the admin email and password you entered.
189188

agent/Dockerfile

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# DeepSQL Agent — self-contained container for the Agent tab, AI dashboards,
2+
# Slack/CLI agent turns, and per-user profile provisioning.
3+
#
4+
# Built from this checkout. The runtime engine is an upstream dependency
5+
# installed at image-build time; the product surface (persona, skills, MCP,
6+
# branding) is owned by DeepSQL and is what operators interact with.
7+
8+
FROM python:3.12-slim-bookworm
9+
10+
ENV DEBIAN_FRONTEND=noninteractive \
11+
PYTHONDONTWRITEBYTECODE=1 \
12+
PYTHONUNBUFFERED=1 \
13+
# Product home — operators never need to know the upstream layout.
14+
DEEPSQL_AGENT_HOME=/var/lib/deepsql-agent \
15+
DEEPSQL_AGENT_ROOT=/opt/deepsql-agent \
16+
PATH="/opt/deepsql-agent/runtime/venv/bin:/usr/local/bin:${PATH}"
17+
18+
RUN apt-get update && apt-get install -y --no-install-recommends \
19+
ca-certificates \
20+
curl \
21+
git \
22+
nodejs \
23+
npm \
24+
build-essential \
25+
&& rm -rf /var/lib/apt/lists/*
26+
27+
# Node 20+ is required by the DeepSQL MCP server. Debian bookworm ships
28+
# Node 18; replace with NodeSource 20.
29+
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
30+
&& apt-get install -y --no-install-recommends nodejs \
31+
&& rm -rf /var/lib/apt/lists/* \
32+
&& node --version && npm --version
33+
34+
# Install uv for fast Python env management.
35+
RUN curl -fsSL https://astral.sh/uv/install.sh | sh \
36+
&& ln -sf /root/.local/bin/uv /usr/local/bin/uv
37+
38+
WORKDIR /opt/deepsql-agent
39+
40+
# Upstream runtime clones. Refs are overridable at build time; defaults track
41+
# what scripts/self-host/setup-agent.sh installs for host-based installs.
42+
ARG AGENT_RUNTIME_REPO=https://github.com/NousResearch/hermes-agent.git
43+
ARG AGENT_RUNTIME_REF=main
44+
ARG AGENT_API_REPO=https://github.com/nesquena/hermes-webui.git
45+
ARG AGENT_API_REF=main
46+
47+
# Runtime engine (Python agent)
48+
RUN git clone --depth 1 --branch "${AGENT_RUNTIME_REF}" "${AGENT_RUNTIME_REPO}" runtime \
49+
&& cd runtime \
50+
&& UV_NO_CONFIG=1 uv sync \
51+
&& if [ -d .venv ] && [ ! -d venv ]; then ln -sfn .venv venv; fi \
52+
&& if [ -d venv ] && [ ! -d .venv ]; then ln -sfn venv .venv; fi \
53+
# Pin MCP SDK below 2.0 — SDK 2.x renamed CallToolResult.isError → is_error
54+
# and breaks every DeepSQL tool call until the runtime catches up.
55+
&& UV_NO_CONFIG=1 uv pip install --python venv/bin/python 'mcp>=1.0,<2' 'pyyaml>=6'
56+
57+
# HTTP API surface the frontend / backend talk to (:8787)
58+
RUN git clone --depth 1 --branch "${AGENT_API_REF}" "${AGENT_API_REPO}" api \
59+
&& cd api \
60+
&& if [ -f requirements.txt ]; then \
61+
/opt/deepsql-agent/runtime/venv/bin/pip install -r requirements.txt; \
62+
fi
63+
64+
# DeepSQL product surface — persona, skills, branding, MCP, provisioner.
65+
COPY agent/SOUL.md /opt/deepsql-agent/SOUL.md
66+
COPY agent/skills /opt/deepsql-agent/skills
67+
COPY agent/webui /opt/deepsql-agent/webui-overlay
68+
COPY agent/skins /opt/deepsql-agent/skins
69+
COPY agent/distribution.yaml /opt/deepsql-agent/distribution.yaml
70+
COPY mcp /opt/deepsql-agent/mcp
71+
COPY scripts/local-agent-provisioner.py /opt/deepsql-agent/provisioner.py
72+
COPY agent/docker-entrypoint.sh /opt/deepsql-agent/docker-entrypoint.sh
73+
74+
RUN chmod +x /opt/deepsql-agent/docker-entrypoint.sh \
75+
&& cd /opt/deepsql-agent/mcp && npm install --omit=dev --ignore-scripts \
76+
&& mkdir -p /var/lib/deepsql-agent/logs /var/lib/deepsql-agent/profiles \
77+
# Apply DeepSQL Agent branding to the API UI (idempotent overlay).
78+
&& bash /opt/deepsql-agent/webui-overlay/apply-overlay.sh /opt/deepsql-agent/api || true
79+
80+
# Expose the agent API (:8787) and the secret-gated provisioner (:8788).
81+
EXPOSE 8787 8788
82+
83+
VOLUME ["/var/lib/deepsql-agent"]
84+
85+
# Provisioner /health is unauthenticated and always 200 when the process is up.
86+
# The API on :8787 may require a session, so we don't use it for the healthcheck.
87+
HEALTHCHECK --interval=30s --timeout=5s --start-period=90s --retries=5 \
88+
CMD curl -fsS http://127.0.0.1:8788/health >/dev/null || exit 1
89+
90+
ENTRYPOINT ["/opt/deepsql-agent/docker-entrypoint.sh"]

agent/README.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,31 @@ agent HTTP API (`/agent-api/*`), not the Hermes webui skin.
4444
These mirror workflows the in-house `AgentOrchestrator` performed, re-expressed as
4545
agent persona + skills over the DeepSQL MCP tools.
4646

47-
## Install (local / self-host)
47+
## Install (self-host / enterprise)
4848

49-
1. Install the upstream agent runtime (see [AGENTS.md](../AGENTS.md) Cursor Cloud notes
50-
or the [Hermes install docs](https://hermes-agent.nousresearch.com/)).
51-
2. Apply DeepSQL customization (requires `AZURE_OPENAI_KEY` in the environment or
49+
**Preferred:** the `deepsql-agent` Compose service. `./scripts/self-host/install.sh`
50+
builds `agent/Dockerfile` and starts the Agent API (:8787) + profile provisioner
51+
(:8788) on the compose network. No host-side agent install is required.
52+
53+
```bash
54+
./scripts/self-host/install.sh
55+
# or
56+
docker compose up -d --build deepsql-agent
57+
```
58+
59+
### Native / local development (optional)
60+
61+
1. Install the upstream agent runtime (see [AGENTS.md](../AGENTS.md) Cursor Cloud notes).
62+
2. Apply DeepSQL customization (requires `DEEPSQL_CHAT_API_KEY` in the environment or
5263
the repo `.env`):
5364

5465
```bash
5566
bash agent/install.sh
5667
```
5768

58-
It configures `~/.hermes/config.yaml` from this repo:
69+
It configures the agent home from this repo:
5970

60-
- **model**Azure OpenAI via its OpenAI-compatible `…/openai/v1` endpoint (key from env/.env, never committed)
71+
- **model** — via OpenAI-compatible endpoint (key from env/.env, never committed)
6172
- **mcp_servers.deepsql** — this repo’s `mcp/deepsql-phase1-server.js`
6273
- **skills.external_dirs** — this repo’s `agent/skills` (source of truth; must be a YAML list)
6374
- **approvals.mode: smart**, **SOUL.md** persona, and disables host-affecting toolsets
@@ -66,11 +77,15 @@ It configures `~/.hermes/config.yaml` from this repo:
6677
Verify:
6778

6879
```bash
69-
cd ~/.hermes/hermes-agent && uv run hermes mcp test deepsql # → Connected, DeepSQL tools
80+
# Compose
81+
curl -fsS http://localhost:8788/health
82+
83+
# Native (after setup-agent.sh)
84+
./scripts/self-host/setup-agent.sh
7085
```
7186

7287
The DeepSQL MCP server and the Spring backend remain the DBA brain; the agent consumes them.
73-
Optional upstream webui skin: see [`webui/`](webui/).
88+
Optional upstream UI skin: see [`webui/`](webui/).
7489

7590
### Approval UX (operator note)
7691

0 commit comments

Comments
 (0)