API Reference
The API server (src/index.ts) listens on PORT (default 3001).
Authentication
| Method | Header / Cookie | Used For |
|---|---|---|
| API key | Authorization: Bearer {key} | Job submission, event ingest, workspace uploads |
| HMAC | X-Hub-Signature-256 | GitHub webhook receiver |
| JWT | auth_token cookie (HttpOnly) | Dashboard API after OIDC login |
API keys are validated against the SUBMIT_API_KEYS env var (fast path) and against Secrets labeled labrats.work/type=ai-api-key (CRD-managed via ApiKeyWatcher).
Public endpoints (no auth required): /health, /ready, /metrics, /api/auth/*.
Health and Metrics
| Endpoint | Purpose |
|---|---|
GET /health | Liveness — returns {"status":"ok"}. |
GET /ready | Readiness — returns {"status":"ok"}. The engine has no external dependencies that require checking. |
GET /metrics | Prometheus exposition format. |
Jobs
Jobs map 1:1 to InferenceRequest CRDs. The frontend uses lowercase status strings derived from CRD phases:
| Phase | API status |
|---|---|
Pending | waiting |
Running | active |
Succeeded | completed |
Failed | failed |
Cancelled | cancelled |
Submit Job
POST /api/jobs/submit
Authorization: Bearer {api-key}
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
source | string | yes | Origin identifier (github, manual, dashboard, github-actions, …). |
type | string | yes | Job type label (implement-issue, code-review, document-extraction, error-reporting, …). |
prompt | string | no* | Stored in the per-job prompt ConfigMap. *Required unless type === "error-reporting". |
errors | ErrorEntry[] | no | Used when type === "error-reporting". |
priority | number | no | Default 2; lower runs first. |
agentRole | string | no | Match against AiAgent trigger name. |
workspaceSetup.gitRepo | string | no | Clone URL (may include token). |
workspaceSetup.gitRef | string | no | Branch / tag / commit. |
workspaceSetup.gitDepth | number | no | Shallow clone depth. |
workspaceFiles[] | array | no | [{name, data(base64)}] written into the workspace. |
workspaceUploads[] | array | no | [{id, name}] referencing files in the uploads PVC. |
config.model | string | no | Override model. |
config.effort | string | no | low / medium / high. |
config.provider | string | no | claude / codex / vllm / gemma / qwen / mock. |
config.fast | boolean | no | Enable fast mode (Claude only). |
config.timeoutMs | number | no | Per-job timeout (ms). Default 3,300,000 (55 min). |
config.maxTurns | number | no | Maximum conversation turns. Default 25. |
config.executorImage | string | no | Override executor container image. |
config.reactEnabled | boolean | no | Enable ReAct tool-calling loop (local inference only). |
callbackUrl | string | no | POSTed at lifecycle events. Must pass validateCallbackUrl. |
pipeline.type | string | no | Currently only pdf-sections. |
metadata | object | no | Free-form key-value (echoed in callbacks and the dashboard). |
Response (201):
{ "jobId": "ir-3ab1c2d4", "source": "github", "type": "implement-issue" }
jobId is the InferenceRequest CR name.
List Jobs
GET /api/jobs?page=1&limit=20&chainId={uuid}
limit is clamped to 1–100. Items expose CRD-derived fields: id, name (= type), source, agentRole, repo (from metadata), status, attempts, createdAt, processedAt, finishedAt, failedReason, chainId, chainDepth, parentJobId, chainPath, result.
Get Job Detail
GET /api/jobs/:id
Adds phase (raw CRD phase), accountName, k8sJobName, executorPodName, returnvalue (alias for status.result), logs[], the redacted workspace setup, and the promptRef.
Stream Job Logs (SSE)
GET /api/jobs/:id/logs
Accept: text/event-stream
Emits data: {"log":"..."} lines. Terminates with data: {"done":true,"status":"completed|failed|cancelled"}.
Source order: live executor pod logs (when an executorPodName is recorded) → persisted RWX log file (used by pipeline jobs) → fallback to status.logs[].
Retry Job
POST /api/jobs/:id/retry
Resets a Failed IR to Pending. Rejects (400) if the IR is not Failed, or if it carries an embedded git token and is older than 10 minutes (tokens have likely expired).
Cancel Job
POST /api/jobs/:id/cancel
Pending → set phase Cancelled. Running → delete the executor Job, set Cancelled, release the account. Other phases return 400.
Accounts
Removed. The AiAccount CRD and its /api/accounts endpoints were removed in spec 0003. Concurrency tracking moved to AiModel (see Models); credentials flow via the IR apiKeyRef (caller identity) and the optional AiModel.credentialsRef (backend token, claude only).
Agents
AiAgent CRDs.
| Endpoint | Description |
|---|---|
GET /api/agents | List. |
POST /api/agents | Create. Fields: name, triggerName, defaultModel, defaultEffort, defaultProvider, eventTriggers[], instructions[]. |
GET /api/agents/:id | Detail. |
PATCH /api/agents/:id | Update any subset, including enabled, instructions[], eventTriggers[]. |
DELETE /api/agents/:id | Remove. |
GET /api/agents/by-trigger/:triggerName | Lookup by trigger. 404 if missing. |
GET /api/agents/triggers | Optional ?source=…&event=…. Returns agents whose eventTriggers match. |
GET /api/agents/:id/instructions | Resolved instruction list (globals sorted by priority, then assigned locals). |
POST /api/agents/seed | Seed default agents. Returns { "seeded": n }. |
Event Triggers and Chains
Each entry in eventTriggers[]:
{
"source": "github",
"events": ["issues.labeled"],
"instruction": "implement",
"config": { "model": "opus", "effort": "high" },
"filters": {},
"enabled": true,
"next": {
"agentTriggerName": "ai-developer",
"condition": "on-success",
"failurePolicy": "stop"
}
}
See Agent Chains for chain semantics.
Instructions
AiInstruction CRDs.
| Endpoint | Description |
|---|---|
GET /api/instructions | List. Supports ?scope=global or ?scope=local. |
POST /api/instructions | Create. Fields: name, scope, displayName, description, priority, content. |
GET /api/instructions/:id | Detail. |
PATCH /api/instructions/:id | Update any subset of displayName, description, scope, priority, content. |
DELETE /api/instructions/:id | Remove. |
API Keys
API keys are stored as labeled Secrets; the watcher updates the in-memory index in seconds.
| Endpoint | Description |
|---|---|
GET /api/api-keys | List. Only the prefix is returned. |
POST /api/api-keys | Body: { "name": "..." }. Response includes the full key once — store it. |
DELETE /api/api-keys/:id | Revoke. |
Webhook Sources
WebhookSource CRDs. Each WebhookSource is reconciled by the API server, which auto-provisions a Deployment + Service + Ingress for the webhook receiver.
| Endpoint | Description |
|---|---|
GET /api/webhook-sources | List. |
POST /api/webhook-sources | Create. |
GET /api/webhook-sources/:id | Detail. |
PATCH /api/webhook-sources/:id | Update. |
DELETE /api/webhook-sources/:id | Remove (also tears down the provisioned Deployment/Service/Ingress). |
Configuration
Global Defaults (singleton AiConfig)
GET /api/config/defaults
PUT /api/config/defaults
Body / response shape:
{
"model": "sonnet",
"effort": "medium",
"executorImage": "ghcr.io/labrats-work/apps.ai-agents/executor:latest",
"executorResources": {
"requests": { "cpu": "500m", "memory": "1Gi" },
"limits": { "cpu": "2", "memory": "4Gi" }
},
"providers": {
"claude": { "model": "opus", "effort": "high" },
"codex": { "model": "o3" }
}
}
All fields are optional; PUT merges with the existing CR.
Source Config (Stubs)
Source-specific config moved to WebhookSource CRDs (repoOverrides, defaults). The legacy endpoints remain as stubs to avoid frontend errors:
GET /api/config/sources → { "sources": [] }
GET /api/config/sources/:source → { "source": "{name}", "model": "", "effort": "" }
PUT /api/config/sources/:source → echoes the body
DELETE /api/config/sources/:source → { "removed": "{name}" }
Stats
| Endpoint | Description |
|---|---|
GET /api/stats | Aggregated counts by type, model, repo, plus totals. Computed from in-memory IR cache. |
GET /api/stats/timeseries | Proxies queries to PROMETHEUS_URL. |
Uploads
PDF / file uploads stored under WORKSPACE_DIR/uploads. Used by the dashboard for pipeline runs.
| Endpoint | Description |
|---|---|
GET /api/uploads | List. |
POST /api/uploads | multipart/form-data with field file (PDF, max 100 MB). |
DELETE /api/uploads/:id | Remove. |
POST /api/uploads/:id/extract | Submit a pdf-sections pipeline IR. Body: prompt?, model?, effort?. Returns { "jobId": "ir-…" }. |
Workspace Uploads (RWX PVC)
Files made available to executor Jobs via the shared uploads PVC.
| Endpoint | Auth | Description |
|---|---|---|
POST /api/workspace-uploads | API key | Upload a file into UPLOADS_DIR/{id}/{name} (referenced by workspaceUploads in IR specs). |
GET /api/workspace-uploads/:id/:name/raw | API key | Download a workspace upload file. |
GET /api/workspace-uploads | JWT | Dashboard listing of files in the PVC. |
DELETE /api/workspace-uploads/:id | JWT | Delete a workspace upload (dashboard). |
Models
Manage local inference model files on the models-cache PVC.
| Endpoint | Description |
|---|---|
GET /api/models | List configured models (from AiConfig provider settings) and the PVC name. |
POST /api/models/scan | Trigger a k8s Job to scan the models PVC for downloaded files. 30-second cache. |
POST /api/models/download | Download a model file to the PVC. Body: { "provider", "model", "url" }. URL must match a configured model. |
GET /api/models/jobs | List model operation jobs (download, delete — excludes scan jobs). |
GET /api/models/jobs/:name/logs | Read logs from a completed model operation job. |
DELETE /api/models/:provider/:filename | Delete a model file from the PVC (creates a k8s Job). |
Auth
| Endpoint | Description |
|---|---|
GET /api/auth/oidc | Start Authelia OIDC login (sets state cookie, redirects). |
GET /api/auth/oidc/callback | Exchange code → set auth_token cookie → redirect. |
GET /api/auth/me | Returns user object or null, plus app version string. |
POST /api/auth/logout | Clear auth_token. |
Event Ingest
POST /api/events/ingest
Authorization: Bearer {api-key}
Content-Type: application/json
Body: { "source": "github", "event": "pull_request.opened", "payload": {...} }. Each agent with a matching enabled eventTriggers entry yields one IR.
Response: { "matched": n, "jobs": [{ "jobId", "agent" }, ...] }.
Webhooks
POST /api/webhooks/github
X-Hub-Signature-256: sha256=…
X-GitHub-Event: {event}
HMAC-verified GitHub webhook receiver. Resolves the WebhookSource CR (type github), reads the secret, normalizes the event, and creates IRs for matched agents. See GitHub Integration.
Callback Webhooks
When an IR has a callbackUrl, the engine POSTs at lifecycle points. Payloads are intentionally minimal — fetch full state via GET /api/jobs/:id.
{ "jobId": "ir-…", "phase": "in_progress", "metadata": {...} }
{ "jobId": "ir-…", "phase": "completed", "metadata": {...} }
{ "jobId": "ir-…", "phase": "failed", "details": "...", "metadata": {...} }
details only present on failed. Callbacks have a 10-second timeout and never affect IR status.