diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ae442a8 --- /dev/null +++ b/.env.example @@ -0,0 +1,15 @@ +# Copy this file to .env and set real values: cp .env.example .env +# .env is gitignored — never commit real secrets. +# +# These are LOCAL-DEV placeholders. Generate fresh values for any +# non-local use (e.g. `openssl rand -hex 32`). + +# API key AgentLens uses to call the Lore service. Must match a key the +# Lore instance accepts. +LORE_API_KEY=lore_sk_localdev_replace_me + +# AgentGate admin API key. +ADMIN_API_KEY=agentkit-local-dev-admin-key + +# AgentGate JWT signing secret. +JWT_SECRET=agentkit-local-dev-jwt-secret-change-me diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e3a369f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + smoke: + name: Compose smoke test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Seed .env from example + run: cp .env.example .env + + - name: Validate compose config + run: docker compose config -q + + - name: Bring the stack up (wait for healthchecks) + run: docker compose up -d --wait --wait-timeout 180 + + - name: Poll documented health endpoints + run: | + set -e + curl -fsS http://localhost:3000/api/health/overview > /dev/null + curl -fsS http://localhost:3002/health > /dev/null + curl -fsS http://localhost:8765/health > /dev/null + curl -fsS http://localhost:8766/health > /dev/null + echo "All four services healthy." + + - name: Dump logs on failure + if: failure() + run: docker compose logs --no-color + + - name: Tear down + if: always() + run: docker compose down -v diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/README.md b/README.md index ff40fb3..e4184e2 100644 --- a/README.md +++ b/README.md @@ -18,26 +18,31 @@ ```bash git clone https://github.com/agentkitai/agentkit-stack.git cd agentkit-stack +cp .env.example .env # then edit .env and set real secrets docker compose up -d ``` -AgentLens and AgentGate pull from Docker Hub; Lore and Mesh build locally. +All four services pull pinned images from Docker Hub. Secrets are read from +`.env` (gitignored); `docker compose up` will refuse to start until the +required keys in `.env` are set. ## Services | Service | Port | Image | Description | |------------|------|-------|-------------| -| AgentLens | 3000 | [`pazgaz/agentlens`](https://hub.docker.com/r/pazgaz/agentlens) | Observability dashboard | -| AgentGate | 3002 | [`pazgaz/agentgate`](https://hub.docker.com/r/pazgaz/agentgate) | Approval gateway | -| Lore | 8765 | *(built from source)* | Semantic memory (pgvector) | +| AgentLens | 3000 | [`pazgaz/agentlens:0.12.2`](https://hub.docker.com/r/pazgaz/agentlens) | Observability dashboard | +| AgentGate | 3002 | [`pazgaz/agentgate:0.12.1`](https://hub.docker.com/r/pazgaz/agentgate) | Approval gateway | +| Lore | 8765 | [`pazgaz/lore:1.1.1`](https://hub.docker.com/r/pazgaz/lore) | Semantic memory (pgvector) | | Lore DB | — | `pgvector/pgvector:pg16` | PostgreSQL + pgvector | -| Mesh | 8766 | *(built from source)* | Agent discovery registry | +| Mesh | 8766 | [`pazgaz/agentkit-mesh:1.3.0`](https://hub.docker.com/r/pazgaz/agentkit-mesh) | Agent discovery registry | ## Docker Hub Images ```bash -docker pull pazgaz/agentlens # ~1GB (dashboard + server) -docker pull pazgaz/agentgate # ~241MB (approval gateway) +docker pull pazgaz/agentlens:0.12.2 # dashboard + server +docker pull pazgaz/agentgate:0.12.1 # approval gateway +docker pull pazgaz/lore:1.1.1 # semantic memory +docker pull pazgaz/agentkit-mesh:1.3.0 # agent discovery registry ``` ## Health Checks @@ -51,7 +56,10 @@ curl http://localhost:8766/health # Mesh ## Rebuild from Source -To build AgentLens/AgentGate locally instead of pulling from Docker Hub, uncomment the `build:` lines in `docker-compose.yml` and remove the `image:` lines, then: +By default every service pulls a pinned image from Docker Hub. To build any of +them from a local checkout instead, uncomment that service's `build:` lines in +`docker-compose.yml` (each expects the sibling repo checked out alongside this +one), then: ```bash docker compose up -d --build diff --git a/docker-compose.yml b/docker-compose.yml index bc39308..7131252 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: agentlens: - image: pazgaz/agentlens:latest + image: pazgaz/agentlens:0.12.2 # build: # context: ../agentlens # dockerfile: Dockerfile @@ -16,7 +16,7 @@ services: - LORE_ENABLED=true - LORE_MODE=remote - LORE_API_URL=http://lore:8765 - - LORE_API_KEY=lore_sk_a01079a5b4b6c6f194b6419a69ff92dd + - LORE_API_KEY=${LORE_API_KEY:?set LORE_API_KEY in .env (copy from .env.example)} - MESH_ENABLED=true - MESH_URL=http://mesh:8766 volumes: @@ -27,13 +27,17 @@ services: depends_on: lore: condition: service_healthy + agentgate: + condition: service_healthy + mesh: + condition: service_healthy deploy: resources: limits: memory: 256M agentgate: - image: pazgaz/agentgate:latest + image: pazgaz/agentgate:0.12.1 # build: # context: ../agentgate # dockerfile: Dockerfile @@ -44,21 +48,28 @@ services: - PORT=3002 - NODE_ENV=production - LOG_FORMAT=json - - ADMIN_API_KEY=agentkit-local-dev-key-1234 - - JWT_SECRET=agentkit-local-dev-jwt-secret-1234567890abcdef + - ADMIN_API_KEY=${ADMIN_API_KEY:?set ADMIN_API_KEY in .env (copy from .env.example)} + - JWT_SECRET=${JWT_SECRET:?set JWT_SECRET in .env (copy from .env.example)} - AGENTLENS_URL=http://agentlens:3000 volumes: - agentgate-data:/app/data networks: - agentkit restart: unless-stopped + healthcheck: + # node-based probe: the agentgate image (node:22-alpine) has no curl + test: ["CMD-SHELL", "node -e \"require('http').get('http://localhost:3002/health',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))\""] + interval: 5s + timeout: 3s + retries: 10 + start_period: 10s deploy: resources: limits: memory: 256M lore: - image: pazgaz/lore:latest + image: pazgaz/lore:1.1.1 # build: # context: ../lore # dockerfile: Dockerfile.server @@ -109,7 +120,7 @@ services: memory: 128M mesh: - image: pazgaz/agentkit-mesh:latest + image: pazgaz/agentkit-mesh:1.3.0 # build: # context: ../agentkit-mesh # dockerfile: Dockerfile