Onboarding
A working mental model for engineers new to this repository. Content is derived from the actual repo state — not aspiration. Where the design diverges from what is shipped, that is called out explicitly.
What is AMTP? #
AMTP = Automated Multi-Agent Testing Pipeline. It is a ZagTrader internal system whose one-line description is:
Connect a private GitHub repository → three isolated LLM agents take turns analysing it → a pull request containing ready-to-run Playwright or Maestro test code appears on GitHub. AMTP never executes the tests.
Two things follow from that one sentence:
-
AMTP is a code-generation service, not a test runner.
It produces
.spec.ts(Playwright, web) and.yaml(Maestro, mobile) files and opens a PR. Reviewing, merging, and running those tests is left to humans and the target repo’s own CI. AMTP therefore needs no staging environment, no browser install, no device farm. - AMTP is built around a three-agent pipeline. Each agent is stateless and consumes/produces structured JSON. A deterministic orchestrator (Temporal, planned) sequences them and provides retries + durable state.
The three agents are:
| Agent | Role | Output |
|---|---|---|
| Repo Crawler | Reads the target repo, summarises structure | JSON repo map |
| Test Case Generator | Turns repo map into test scenarios | JSON scenarios |
| Test Engineer | Writes the actual test code | .spec.ts / .yaml files in a PR |
What is and isn’t built yet #
This is the most important thing to internalise before reading the code, because the documentation site describes the intended architecture, not the current one.
Implemented and running today #
-
GitHub MCP server
(apps/github-mcp/) — TypeScript MCP server
exposing seven tools over Streamable HTTP on port
8090. Three read tools (repo.tree,repo.read_file,repo.search_code) and four write tools (repo.branch_create,git.blob.create,git.tree.create,git.commit.create) implement the complete Git write path for the Test Engineer agent. -
Code Intelligence MCP server scaffold
(apps/code-intel-mcp/) — sibling MCP server on
port
8091. Currently returns an emptytools/list— tool implementation is in-progress under AUT-3. See apps/code-intel-mcp/PLAN.md for the full roadmap. -
Shared workspace package
(packages/mcp-lib/) —
@amtp/mcp-libnpm workspace package exposinglogger,health, andotelshared across both MCP apps. Repo is now an npm workspace; single rootpackage-lock.json. -
Healthcheck service
(apps/healthcheck/) — Node service that pings
Valkey and exposes
/healthon port8083. - OTel verifier (apps/otel-verify/) — small Python script (verify_trace.py) for confirming the observability stack accepts and stores traces.
-
Database — Postgres 15 + PgBouncer (port
6432), schema applied via Flyway migrations (migrations/sql/V1..V6). - Cache / queue — Valkey 8.0 (Redis-compatible).
-
Documentation site
(docs/AMTP_Docs_Website/) — static HTML site,
built with
node build.jsand indexed with Pagefind, served by thedocsnginx container. - Observability stack — OTel collector, Tempo, Loki, Prometheus, Grafana (see docker-compose.observability.yml and infra/observability/).
- Secrets management — SOPS + age encrypted secrets committed as secrets/dev.sops.env; CI/CD materialises them via .github/actions/materialize-env/action.yml. See infra/sops/README.md.
- CI/CD — seven self-hosted GitHub Actions workflows under .github/workflows/, one per service (including code-intel-mcp-ci-cd.yml).
Planned, not yet in the repo #
- The three LLM agents (Repo Crawler, Test Case Generator, Test Engineer).
- Temporal orchestrator.
- Web frontend / API gateway for users to connect repos and trigger runs.
-
AUT-3 tool implementations —
ast.summarize_file,ast.extract_routes,ast.extract_components,ast.extract_selectors,ast.find_symbolin apps/code-intel-mcp/. Scaffold is shipped and healthy; tools are what remain.
Repository Layout #
-
apps/
- github-mcp/MCP server: 7 tools (3 read + 4 write); port 8090
- code-intel-mcp/AST/code-intel MCP server (AUT-3 scaffold); port 8091
- healthcheck/Tiny Node health probe service
- otel-verify/Python script to verify traces reach the OTel stack
-
packages/
- mcp-lib/@amtp/mcp-lib workspace package — shared logger, health, otel
-
docs/
- AMTP_Docs_Website/Static HTML docs (built to dist/, served by nginx container)
-
migrations/
- flyway.conf
- sql/V1..V6 — projects / runs / stages / artifacts / approvals / indexes
-
infra/
- bootstrap.shServer bootstrap (firewalld rules, etc.)
- nginx/docs site nginx config
- observability/OTel collector, Grafana, Loki, Tempo, Prometheus configs
- sops/SOPS + age secrets tooling (README.md + merge-env.sh)
- postgres/
- valkey/
-
secrets/
- dev.sops.envSOPS + age encrypted env file committed to repo
-
.github/
- actions/materialize-env/Reusable action: decrypt + export env vars for CI
- workflows/Seven per-service CI/CD pipelines
- docker-compose.ymlBase stack: Postgres, PgBouncer, Valkey, healthcheck, github-mcp, code-intel-mcp, docs
- docker-compose.override.ymlLocal dev overrides
- docker-compose.observability.ymlOTel + Grafana + Loki + Tempo + Prometheus
- package.jsonnpm workspace root (workspaces: packages/*, apps/*)
- .env.exampleCopy to .env and fill in
Data Model #
Five tables, all in migrations/sql/, all UUID-keyed, all
with ON DELETE CASCADE from parent → child. See
Data Model for the full schema
reference.
projects one row per connected GitHub repo
│
└── runs one row per pipeline invocation
│ (depth_level: smoke|core|standard|deep)
├── stages one row per agent step within a run
│ │ (sequence + attempt for retries)
│ └── artifacts JSONB outputs produced by a stage
│ │
│ └── approvals human-in-the-loop sign-offs on a stage
│
└── artifacts run-level artifacts (not tied to a specific stage)
-
stages.UNIQUE(run_id, sequence, attempt)lets a failed stage be retried without losing prior attempt history. -
artifacts.contentis JSONB with ajsonb_typeof = 'object'check — every artifact is a structured agent output, never a free-form blob. -
runs.statusis the orchestrator’s source of truth:pending → running → passed | failed | cancelled.
GitHub MCP Server #
apps/github-mcp/ is the part of the codebase you will spend the most time near, because (a) it is the working reference for “how an MCP server is built in this org” and (b) the AUT-3 Code Intelligence server you are about to build will sit alongside it. See GitHub MCP for the full reference.
Read tools (Stage 1 — Repo Crawler) #
-
repo.tree— filtered, sorted, deterministic file tree for a repo subtree at a given ref. Honours gitignore-style patterns. -
repo.read_file— UTF-8 contents of a single file, truncated atmax_bytes(default 64 KiB, cap 1 MiB), with binary-detection guard. -
repo.search_code— wraps GitHub’s Code Search API with auto-detectedextension:/path:qualifiers, jittered retry on rate-limit, and ranked{ path, snippet }[]output.
Write tools (Stage 3 — Test Engineer) #
-
repo.branch_create— creates a new Git branch from an existing committish; idempotent if the ref already exists at the same SHA. -
git.blob.create— creates a Git blob from UTF-8 text or base64 content; returns the blob SHA. -
git.tree.create— creates a Git tree from a base tree SHA + an array of blob items; passingsha: nullfor a path deletes it. -
git.commit.create— creates a Git commit pointing at a tree SHA; appends aRun-Id: {run_id}Git trailer to the message for pipeline traceability.
Auth #
A GitHub App (not a PAT). Three pieces of config:
| Variable | Where it lives |
|---|---|
GITHUB_APP_ID |
.env |
GITHUB_APP_INSTALLATION_ID |
.env |
GITHUB_APP_PRIVATE_KEY (PEM) |
Docker secret, mounted at
/run/secrets/github_app_key
|
Internal structure (read in this order) #
- src/index.ts, src/server.ts — entry point and MCP server wiring.
- src/tools/ — seven tool files; each is a Zod input schema + validated handler. The write tools (repo-branch-create.ts, git-blob-create.ts, git-tree-create.ts, git-commit-create.ts) are the newer additions and show the idiomatic pattern most clearly.
- src/lib/schema.ts — all Zod schemas and TypeScript output types.
-
src/lib/github.ts — Octokit client factory (App
auth, throttling,
resolveRef). - src/lib/otel.ts, telemetry.ts, logger.ts — observability wiring (template for any new service).
Infrastructure Stack #
Base file (docker-compose.yml) stands up these services. See Infrastructure for full configuration details.
| Service | Image | Host port | Notes |
|---|---|---|---|
postgres |
postgres:15-alpine |
— (internal) | scram-sha-256 auth, log_min_duration_statement=500 |
pgbouncer |
edoburu/pgbouncer:1.22.1-p0 |
6432:5432 |
Apps connect here, not directly to postgres |
flyway |
flyway/flyway:10-alpine |
— |
Profile migrate, opt-in
(docker compose --profile migrate up flyway)
|
valkey |
valkey/valkey:8.0 |
— (internal) | Cache + queue, AUTH-protected, allkeys-lru |
healthcheck |
local build | 8083:8080 |
Published deliberately — bootstrap.sh opens 8083 and CI curls it after deploy |
github-mcp |
local build | 8090:8090 |
MCP server — 7 tools (3 read + 4 write) |
code-intel-mcp |
local build | 8091:8091 |
AST MCP server scaffold — currently
tools/list returns []
|
docs |
nginx:alpine |
${DOCS_HOST_PORT:-80}:80 |
Serves docs/AMTP_Docs_Website/dist/. Not on
amtp_net — it has no business reaching the
DB
|
The shared Docker network is explicitly named
amtp_net (not the default
<project>_amtp_net) so the observability compose
file can reference it as external: true. Don’t
change that name without also fixing the observability compose file.
CI/CD #
Seven self-hosted GitHub Actions workflows, one per deployable surface. See CI/CD for job-level detail.
| Workflow | Triggers on changes to |
|---|---|
| ci-cd.yml | Top-level (compose, infra, etc.) |
| db-ci-cd.yml | migrations/ |
| docs-ci-cd.yml | docs/AMTP_Docs_Website/ |
| github-mcp-ci-cd.yml | apps/github-mcp/ |
| code-intel-mcp-ci-cd.yml | apps/code-intel-mcp/ |
| healthcheck-ci-cd.yml | apps/healthcheck/ |
| observability-ci-cd.yml | infra/observability/ and docker-compose.observability*.yml |
Where AUT-3 (Code Intelligence) Fits #
AUT-3 is the Code Intelligence (AST) MCP Server — a sibling MCP server to the GitHub MCP one. Same transport, same observability conventions, different tools. See Code Intelligence MCP for the full reference page.
Purpose: wrap tree-sitter parsers for TypeScript, JavaScript, TSX, JSX, Python, Kotlin, Swift, and Dart, and expose tools that return AST-derived JSON summaries of source files instead of raw text.
Why it matters: token cost of feeding raw source files to LLM agents is the dominant bottleneck in this pipeline. AST-summarized output preserves the structural information agents actually use (function signatures, exports, class shapes) while dropping bodies they don’t need. Spec target: a 300-line TS file (~8,000 chars) → a 60-line JSON summary (~1,200 chars), ~85% reduction with no semantic loss.
Where to start #
-
The scaffold is already shipped at
apps/code-intel-mcp/. Server starts,
/healthzreturns healthy,tools/listreturns[]. Read Phase 1 + 1.5 of apps/code-intel-mcp/PLAN.md to understand what was scaffolded. - Read Phase 2 of the plan for the three open design questions (WASM vs native, output JSON shape, cache key strategy) — these must be answered before writing tool code.
- The 85% reduction target is the design constraint for every schema choice.
Quick Orientation #
| You want to… | Look at |
|---|---|
| Understand the intended end-state architecture | architecture.html and concepts.html |
| Understand what is actually shipped | This page + docker-compose.yml |
| Learn the MCP server pattern | apps/github-mcp/src/server.ts then src/tools/repo-tree.ts (read) or src/tools/git-blob-create.ts (write) |
| Learn the write-tool Git commit flow |
git.blob.create →
git.tree.create →
git.commit.create →
repo.branch_create (update branch)
|
| Trace a request |
OTel: services emit to otel-collector:4318, view
in Grafana → Tempo
|
| Check a deploy succeeded |
curl http://<host>:8083/health,
curl http://<host>:8090/healthz, and
curl http://<host>:8091/healthz
|
| See the DB schema | migrations/sql/V*.sql (six files, in order) |
| Add a new env var | .env.example first, then the relevant compose service, then code |
| Run a fresh DB migration locally |
docker compose --profile migrate up flyway
|
Open Questions #
Things not derivable from the repo that you should clarify with the team before assuming:
-
AUT-3 design questions (Phase 2 of PLAN.md).
Output JSON shape for
ast.summarize_file, cache key strategy, and WASM-vs-native binding decision must be answered and written down before AUT-35 code lands. -
Self-hosted runner build tools. CI uses WASM
(
web-tree-sitter) so no C compiler is needed today, but verify before switching to native bindings. - Secrets rotation process. infra/sops/README.md documents the age key setup and rotation procedures. Make sure your local key is registered in .sops.yaml before editing secrets.