# ai AI VM services of the self-healing lab (experiment design 6). Module `github.com/selfheal-lab/selfheal-lab-apps/ai`. | command | role | port | |---|---|---| | `cmd/agent` | `POST /diagnose`: Responses API tool loop over the read-only tools (`internal/tools`, design 6.2), strict `submit_diagnosis` (design 6.3, `internal/diag`), sessions and prompt versions in pgvector (`internal/rag`), then proposal + HITL post or escalation (design 6.5/6.6, `internal/agent`) | 8080 | | `cmd/hitl` | Discord gateway bot (`internal/hitl`): Approve/Reject buttons, harness approval + execution, expiry to the escalation channel, escalation threads with the runbook | 8081 | Contracts: harness `POST /diagnose {"alert","run_id","scenario_id"}` -> diagnosis fields at top level plus `session_id`, `model`, `prompt_version`, `disposition`. Harness side: `POST /proposals` (registers the proposal at diagnosis time, returns the approval token), `POST /proposals/{token}/approve`, `POST /proposals/{token}/reject`, `POST /actions/execute`. OpenAI: `POST /v1/responses` with function tools (`strict: true`, every property required, `additionalProperties: false`), `previous_response_id` chaining, `function_call_output` items; embeddings `text-embedding-3-small` (1536). Model id from `OPENAI_MODEL`. Build: `gcloud builds submit ai --project cms-d-414903 --config ai/cloudbuild.yaml --substitutions=_TAG=$(git rev-parse --short HEAD)`. Tests: `cd ai && go test ./...` (mock Responses API and Mimir; no network).