The REST API exposes the shared AnalysisEngine over HTTP. Every route
delegates to a single cached engine instance, so the API has zero business logic of its own —
it only marshals JSON. The response models are the same ones the SDK returns, so the two contracts
never drift.
pip install 'devops-ai-toolkit[api]'
devops-ai serve --host 0.0.0.0 --port 8000
# or
uvicorn devops_ai_toolkit.api.app:app --host 0.0.0.0 --port 8000Interactive documentation is generated automatically:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- OpenAPI JSON: http://localhost:8000/openapi.json
| Method | Path | Purpose |
|---|---|---|
| GET | /health |
Liveness/readiness + KB & provider status |
| GET | /version |
Running version |
| POST | /analyze/log |
Analyze a log or command output |
| POST | /analyze/yaml |
Analyze a YAML / Kubernetes manifest |
| POST | /analyze/terraform |
Analyze Terraform config or plan/apply output |
| POST | /explain |
Explain a known error |
| POST | /validate |
Validate a YAML / Kubernetes / Terraform doc |
curl -s localhost:8000/health | jq{
"status": "ok",
"signatures": 42,
"provider": "null",
"provider_available": false
}provider and provider_available reflect your configuration. Offline by
default (null / false).
curl -s localhost:8000/version | jq{ "name": "devops-ai-toolkit", "version": "0.1.0" }All three analyze endpoints accept the same body shape:
They return an AnalysisResult (Output format).
# Log
curl -s localhost:8000/analyze/log \
-H 'content-type: application/json' \
-d '{"content": "OOMKilled exit code 137"}' | jq .summary
# YAML / Kubernetes manifest
curl -s localhost:8000/analyze/yaml \
-H 'content-type: application/json' \
--data-binary @<(jq -Rs '{content: .}' < deploy.yaml) | jq .root_causes
# Terraform (technology + source kind are inferred as terraform)
curl -s localhost:8000/analyze/terraform \
-H 'content-type: application/json' \
-d '{"content": "Error: Error acquiring the state lock"}' | jq .summarycurl -s localhost:8000/explain \
-H 'content-type: application/json' \
-d '{"error": "CrashLoopBackOff"}' | jq '{title, matched}'Body: { "error": "<name or message>" }. Returns an ExplainResult
(Output format).
curl -s localhost:8000/validate \
-H 'content-type: application/json' \
-d '{"content": "apiVersion: v1\nkind: Pod\n", "filename": "pod.yaml"}' \
| jq '{valid, error_count, issues}'Body:
{
"content": "...", // required
"technology": null, // optional
"source_kind": null, // optional
"filename": "pod.yaml" // optional
}Returns a ValidationResult (Output format).
The response models are pure Pydantic, so any HTTP client works:
import httpx
r = httpx.post(
"http://localhost:8000/analyze/log",
json={"content": "ImagePullBackOff"},
)
r.raise_for_status()
data = r.json()
print(data["summary"])Start the server with provider env vars set, then pass "enrich": true:
DEVOPS_AI_PROVIDER=anthropic ANTHROPIC_API_KEY=sk-ant-... devops-ai serve
curl -s localhost:8000/analyze/log \
-H 'content-type: application/json' \
-d '{"content": "CrashLoopBackOff", "enrich": true}' | jq .enrichmentSee AI providers and Configuration.
- The engine is read-only — the API performs no mutations and needs no write access. See Security.
- The engine instance is process-wide and cached (
lru_cache); the knowledge base loads once. - Put it behind your own auth/proxy if exposing it beyond localhost; the toolkit ships no auth.
- For a fully hosted alternative, see the AI incident assistant.
{ "content": "Back-off restarting failed container", // required, non-empty "technology": "kubernetes", // optional hint, auto-detected if omitted "source_kind": "log", // optional hint, auto-detected if omitted "filename": "app.log", // optional, aids detection "enrich": false, // add LLM narrative if a provider is configured "max_root_causes": 5 // 1-20 }