Documentation Index
Fetch the complete documentation index at: https://mintlify.com/joseluis-dev/harness-ai/llms.txt
Use this file to discover all available pages before exploring further.
Harness AI is composed of a set of Docker services that are introduced incrementally across deployment phases. From the very first commit, the topology enforces a strict boundary between the single public-facing service (harness-core) and everything else, which lives on a private Docker network. Understanding this map is a prerequisite before configuring environment variables or deploying to Dokploy.
Services by Deployment Phase
The table below lists every service in the system, the network it belongs to, and the phase in which it is introduced.
Phase 0 + Phase 0.b — Base Executable
These services form the entire stack required to run the harness locally and in production through Phase 0.b.
| Service | Role | Network |
|---|
harness-core | Astro SSR BFF — the only publicly-exposed service | public-net + private-harness-net |
admin-panel | Internal admin UI — IP/VPN-allowlisted only | private-harness-net |
mcp-auth-service | Centralised OAuth 2.0 authorisation server | private-harness-net |
postgres | Business database (harness_db) — executions, audit, RAG | private-harness-net |
postgres-auth | Auth database (harness_auth_db) — OAuth clients, tool registry, permissions | private-harness-net |
redis | RQ broker and operational cache | private-harness-net |
minio | Object storage for ingested documents (optional until Phase 4) | private-harness-net |
mcp-readonly-sql | MCP server — read-only SQL access via harness_db | private-harness-net |
mcp-identity-connector | Identity sidecar — resolves actor context from external IdP | private-harness-net |
model-gateway | LLM gateway — all inference traffic is routed through here | private-harness-net |
vllm | Local vLLM inference backend | private-harness-net |
Phase 4–5 — Document Ingestion
These services are added when the document-watcher and RAG pipeline are activated.
| Service | Role | Network |
|---|
document-watcher | Watches a directory for new or changed files | private-harness-net |
document-worker | Processes ingestion jobs from the watcher queue | private-harness-net |
embedding-worker | Generates vector embeddings for ingested documents | private-harness-net |
mcp-document-registry | MCP server — exposes document registry to the agent | private-harness-net |
Phase 7+ — Advanced Automation
These services are introduced in later phases and all require additional security controls before activation.
| Service | Role | Network |
|---|
langgraph-worker | Stateful multi-step agent runner | private-harness-net |
n8n | Workflow automation — activated only behind VPN or reverse proxy | private-harness-net |
mcp-expedientes | MCP server for institutional case-file integration | private-harness-net |
mcp-reportes | MCP server for institutional report integration | private-harness-net |
mcp-notificaciones | MCP server for notification dispatch | private-harness-net |
observability | Metrics, tracing, and log aggregation stack | private-harness-net |
Network Topology
Harness AI uses two Docker networks to enforce isolation at the infrastructure level.
public-net:
- harness-core ← ONLY service reachable from the outside
private-harness-net:
- admin-panel
- mcp-auth-service
- postgres
- postgres-auth
- redis
- minio
- model-gateway
- vllm
- runtime-python
- mcp-* services
- document-worker
- embedding-worker
- langgraph-worker
The public-net ↔ private-harness-net separation is enforced from Phase 0. Any service other than harness-core that appears on public-net is a deployment violation and must be corrected before a release can proceed.
Exposure Rules
Only one service is ever publicly exposed:
harness-core ← bound to :4321; TLS terminated by Dokploy / reverse proxy
The following services must never be reachable from the public internet:
admin-panel ← internal only; IP/VPN allowlist required
mcp-auth-service
postgres
postgres-auth
redis
vllm
model-gateway
runtime-python
mcp-* servers
minio (without access controls)
n8n may only be exposed if protected by all of the following: a VPN or reverse proxy, strong authentication, and an IP allowlist where applicable. It is not part of the MVP and is introduced no earlier than Phase 7.
admin-panel must never be placed on public-net. It is an internal administration interface and must only be reachable via VPN, a jump host, or an IP-allowlisted reverse proxy. Exposing it publicly is a critical security violation regardless of authentication controls placed in front of it.
minio is optional through Phase 3. The object store is only required once the document ingestion pipeline (Phase 4) is activated. You can omit the minio service entirely from your compose configuration until that point without affecting any Phase 0–3 acceptance criteria.
Dockerfile Locations
Each deployable service has its own Dockerfile under infra/docker/. The table below lists the files that exist in the repository for the Phase 0 + Phase 0.b services.
| Service | Dockerfile |
|---|
harness-core | infra/docker/Dockerfile.harness-core |
runtime-python | infra/docker/Dockerfile.runtime-python |
model-gateway | infra/docker/Dockerfile.model-gateway |
mcp-identity-connector | infra/docker/Dockerfile.mcp-identity-connector |
Docker Invariants
The following rules apply to every image and compose configuration in the repository.
- No hardcoded secrets in images. No
client_secret, database password, or API key is written into any Dockerfile or baked into an image layer. All sensitive values are injected at runtime by the Dokploy secrets manager or the host environment.
- All values injected via Dokploy secrets/env. The compose files read every variable from the environment using
${VARIABLE_NAME} interpolation. No defaults are provided for secret fields in the production compose file; missing values cause docker compose up to fail immediately.
harness_db and harness_auth_db are always separate clusters. The two PostgreSQL instances run as distinct compose services (postgres and postgres-auth) with different credentials and different named volumes. They may share the same PostgreSQL binary, but they must never share the same database instance. tool_registry lives in harness_auth_db because it defines technical authorisation state (scopes, risk_level, permissions); any copy in harness_db is a read-only cache derivative.
mcp-readonly-sql connects only to harness_db using a readonly PostgreSQL user. It must never be given a connection string pointing at harness_auth_db.
Health Check Pattern
Every service in the compose files declares an explicit Docker healthcheck. The pattern for Python-based services uses a stdlib one-liner rather than wget (which is absent from python:3.12-slim):
healthcheck:
test:
- "CMD-SHELL"
- "python -c \"import urllib.request,sys; r=urllib.request.urlopen('http://127.0.0.1:8000/healthz',timeout=2); sys.exit(0 if r.status==200 else 1)\""
interval: 5s
timeout: 3s
retries: 10
start_period: 15s
PostgreSQL containers use pg_isready:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U harness -d harness_db"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
Redis uses the native CLI ping:
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
The harness-core depends on postgres and redis reaching service_healthy before it starts. Services such as mcp-identity-connector and model-gateway use service_started in depends_on to avoid circular dependency chains.