Skip to content

About

An agentic AI platform for CI/CD, cloud infrastructure, containers, deployments and DevOps operations.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

DevOps Autopilot

An agentic AI platform for CI/CD, cloud infrastructure, containers, deployments and DevOps operations.

From repository to production through one intelligent workspace.

Python FastAPI Next.js TypeScript Tests Evals

DevOps Autopilot landing page


Contents


Overview

Most "AI DevOps" tools answer questions about DevOps. DevOps Autopilot does the work.

You connect a project folder. It builds a structured model of the repository, tells you what is wrong, writes the change, shows you the diff and — once you approve — applies it, runs the command, reads the real exit code and reports what actually happened.

The design rests on one division of labour:

Skills contain the engineering. The model chooses which skill to run and explains the result.

Dockerfiles, pipelines and diagnoses come from deterministic code that reads the repository, not from a language model's recollection. That makes "never fabricate output" a structural property rather than a prompt instruction — and it is why the platform still does real work with no model configured at all.

Quality gates 326 backend tests · 28 browser checks · 37-step end-to-end test · ruff, mypy, TypeScript strict and ESLint clean
Evaluation 14/14 DevOps task cases, 66/66 checks across 7 scored dimensions
Backend Python 3.10+ · FastAPI · SQLAlchemy 2 (async) · Server-Sent Events
Frontend Next.js 16 · React 19 · TypeScript 5.9 · Tailwind CSS 4
Models Provider-agnostic: NVIDIA NIM · OpenAI · Anthropic · Azure OpenAI · AWS Bedrock · Ollama · none

Demo

Every recording below is the real application driving the real backend: the repository is scanned for real, the pipeline is generated by the real skill, the provider is connected through the real connector. Nothing is mocked or re-enacted.

Ask for a pipeline, get a reviewable diff. "Create CI/CD for this project" — the agent scans the repository, generates a workflow from the commands it found, and stops at the approval gate.

Agent generating a CI/CD pipeline

Paste a failed deploy, get the first failure. A retry storm collapses into a handful of events, and the cause is separated from the cascade.

Log root-cause analysis

Connect a provider. The registry renders the card, the connector does the work, and the card fills with what the provider itself reported back.

Connecting an integration

The delivery pipeline, explained. Eight stages, five statuses, every icon labelled.

CI/CD pipeline visualisation

Landing page transitions · full walkthrough video

Landing page

The complete tour — landing page, capabilities, integrations and a containerisation run — is in docs/media/demo.mp4.


Quick Start

Requirements: Python 3.10+, Node.js 20+ and Git. No database, container runtime or API key is needed to start.

git clone https://github.com/Singhsh01/devops-autopilot.git
cd devops-autopilot
./start.sh

start.sh checks your toolchain, creates the Python virtual environment, installs both applications on first run (and again whenever dependencies change), starts the API and the web app, waits until both answer, and prints the URLs:

  DevOps Autopilot is running

    Web         http://localhost:3000
    API docs    http://localhost:8000/docs
    Mode        deterministic   (check it in the UI: Integrations → Model provider)

Open http://localhost:3000. Press Ctrl-C in the terminal to stop both services. On macOS you can double-click Start DevOps Autopilot.command instead.

To use a language model, open Integrations → Model provider → Change model or key, choose a provider, paste a key and press Test and save. NVIDIA NIM has a free tier at build.nvidia.com.


Usage Guide

1. Connect a workspace

Open Workspace, enter the absolute path of a project folder under Connect a folder, choose a permission level and press Connect. The repository is scanned immediately; the Context panel shows what was found — languages, frameworks, package manager, build and test commands, ports, health route, containers, CI, infrastructure-as-code and findings.

Start at L1 · Read. Raise the level only when you want the agent to change something:

Level Grants Use it for
L1 · Read Read files and configuration Reviews, explanations, diagnosis, log analysis
L2 · Write Change files — every change is a diff you approve Generating Dockerfiles, pipelines, manifests
L3 · Execute Run classified commands Builds, tests, terraform plan, kubectl get
L4 · External Reach cloud providers through their CLIs Deployments, cloud inventory

2. Ask for work

Type a request in the composer and press Enter (Shift+Enter for a new line). Useful starting points:

Ask What happens
Inspect this project Repository model, findings and recommended next steps
Create CI/CD for this project A GitHub Actions workflow built from your real commands (L2)
Build CI/CD with Jenkins A declarative Jenkinsfile with real stages (L2)
Containerize this service A multi-stage Dockerfile and .dockerignore (L2)
Review security Committed credentials, container and IaC misconfiguration
Paste a failed build or deploy log First failure, cascade, root cause, checks and fixes

Progress streams live: which specialist took the request, which tools ran and how long each took. Long replies are continued automatically — you never need to type "continue".

3. Review and approve changes

Nothing is written without your decision. A proposed change appears as an approval card with its risk class, blast radius and a unified diff (switch between Unified and Split). Press Approve to write the files or Cancel to discard them. Mutating commands follow the same flow; destructive ones additionally require a typed confirmation.

4. Configure the model

Integrations → Model provider shows the active provider, where its key comes from, and the models your key can reach.

  • Test the model sends two tiny real requests — a completion and a tool call — and reports the latency of each. Use it whenever answers are slow or missing.
  • Change model or key switches provider, model, key or reply length. The new configuration is tested against the real provider and saved only if it works. It takes effect on the next message, with no restart.
  • Use .env settings discards what was saved in the interface and returns to .env.

5. Connect integrations

Integrations lists every provider in the registry with its live state on this machine. Press Connect, choose an authentication method, and the backend verifies it against the real provider before storing anything. Connected cards show the identity the provider reported — subscription, account, server, cluster — and offer Test connection and Disconnect.

6. Audit what happened

Activity is the audit trail: every tool call, command, file write, approval, connection and configuration change, with details passed through the secret redactor before they are stored.


Features

Repository intelligence One scan produces a structured model: language, package manager, entry points, real build and test commands, ports, health route, containerisation, CI, IaC, Kubernetes kinds, datastores and cloud hints — each traceable to the file it came from
CI/CD generation and repair Jenkins, GitHub Actions, GitLab CI and Azure Pipelines, built from the commands in your manifests
Containerisation Multi-stage builds, pinned bases, production-only dependency stages, non-root runtime users, health probes pointed at the route your code declares
Kubernetes operations Workloads, services, probes, rollout state and crash-loop diagnosis through kubectl
Infrastructure as code Terraform plan analysis — replacement detection, destructive change calling-out, module structure
Log root-cause analysis Parse, group, match against 26 failure signatures, then order causally so the first failure is separated from the cascade
Security review Credential detection with masked previews, container and IaC misconfiguration, graded critical through informational
Real execution Commands run without a shell, rooted in the workspace, classified before they start — you see the command, cwd, duration, exit code and both streams
Diff-first editing Every file change is a unified diff behind an approval gate before it touches disk
Audit trail and rollback Every tool call, command, write and approval recorded, redacted, and reversible
Provider-agnostic models Switch provider, model or key from the interface — tested before saving, encrypted at rest, applied without a restart
Resilient turns Long replies continue automatically; a hung model falls back to the deterministic planner
Works without a model LLM_PROVIDER=none runs a deterministic planner over the same skills

Capability showcase


Supported Integrations

Providers come from a registry (apps/api/app/integrations/registry.py), not from the UI. Each entry declares its id, name, description, category, icon, capabilities, connection methods and the configuration each method requires; the web app renders whatever the registry returns. Adding a provider is a registry entry plus a connector — no frontend change.

Provider Category Connection methods What it stores Level
Microsoft Azure Cloud Azure CLI session · Service principal · Microsoft identity (declared, not built) Nothing / encrypted client secret L4
Amazon Web Services Cloud Named profile · IAM Identity Center (SSO) Profile name only L4
GitHub Source control gh CLI session · Personal access token · OAuth app (declared, not built) Nothing / encrypted token L4
Jenkins CI/CD URL + username + API token Encrypted API token L4
Kubernetes Orchestration Selected kubectl context Context name only L3
Terraform IaC Local CLI detection Nothing L3
Docker Containers Local CLI + daemon detection Nothing L3
Helm Orchestration Local CLI detection Nothing L3
Git Source control Local CLI detection Nothing L3

Integrations page

Connection states

Each card shows one of five states, and the page spells all five out before any card uses them. A state is never carried by colour alone — it is always icon and text.

State Meaning
Not connected Nothing is configured for this provider yet. The agent cannot reach it.
Connecting A connection attempt is in flight — the backend is talking to the provider now.
Connected The backend reached this provider and confirmed the identity shown on the card.
Connection error The last attempt failed. The reason is on the card; nothing secret was kept.
Needs re-authentication The configuration is still here, but the session or token has expired.

When connected, the card shows the non-secret facts the provider itself returned — Azure subscription and tenant, AWS account id and region, the GitHub account and token scopes, the Jenkins server URL and version, the active Kubernetes context and server version, the Terraform version and workspace. Never a token, password, private key or secret value.

A connected provider

Every card also offers Test connection and Disconnect. Test re-runs the connector against the live provider and updates the facts; disconnect deletes the record, including any stored credential.

How credentials are handled

The honest summary, method by method:

  • Local CLI / local configuration methods store nothing. The agent uses the session already signed in on the machine that hosts it. This covers Git, Docker, Helm, Terraform, Kubernetes, and the CLI options for Azure and GitHub.
  • Credential methods — a Jenkins API token, a GitHub PAT, an Azure service-principal secret — are encrypted with Fernet before they reach the database, using a key read from CREDENTIAL_ENCRYPTION_KEY or a 0600 key file that is gitignored. They are decrypted only inside the connector that needs them.
  • Nothing secret ever comes back out. Responses pass through a filter that strips any key shaped like a secret, recursively, on the way to the browser. Secrets are never put into a model prompt, never written to the audit trail (which records field names, never values), and never stored in browser storage.
  • A failed connection attempt stores no credential at all — it records the reason and stops.
  • If credential encryption is unavailable, methods that need it are refused rather than falling back to plaintext.

Model Providers

The LLM layer is an abstraction, not a dependency. Every provider sits behind the same interface (apps/api/app/llm/), and the rest of the platform never knows which one is active.

Provider LLM_PROVIDER Authentication Notes
NVIDIA NIM nvidia API key (nvapi-…) Free tier; OpenAI-compatible endpoint
OpenAI openai API key Any OpenAI-compatible endpoint via base URL
Anthropic anthropic API key Native Messages API adapter
Azure OpenAI azure_openai API key + endpoint + deployment
AWS Bedrock bedrock AWS credential chain on the host No key stored by the app
Ollama ollama None Runs models on your own machine
None none — Deterministic planner — skills still run

Two ways to configure

From the interface (recommended). Integrations → Model provider → Change model or key. Pick the provider, type the model name (suggestions come from the models your key can reach), paste the key and press Test and save.

  • The configuration is tested against the real provider — a completion and a tool call — and saved only if both succeed. A rejected key, an unknown model or a blocked network is reported in plain language and nothing changes.
  • The key is encrypted with Fernet before it reaches the database, decrypted only into the API process's memory, and never returned to the browser, written to the audit trail or included in a prompt. The page is only ever told where the active key comes from.
  • A stored key is bound to the provider it was entered for, so switching provider can never send one vendor's key to another vendor's endpoint.
  • Changes apply to the next message — no restart. Use .env settings reverts.

From .env. The baseline for fresh installs, CI and containers:

LLM_PROVIDER=nvidia
LLM_MODEL=meta/llama-3.3-70b-instruct
NVIDIA_API_KEY=nvapi-…
LLM_MAX_TOKENS=8192

Verify a configuration from the command line before starting anything:

make check-llm

It reports whether the key is present (never printing it), whether the provider answers, whether the model is one your key can reach — with alternatives if not — and sends a one-token test completion. It also distinguishes a rejected key from a proxy or firewall blocking the host.

Long replies and tool use

A single turn may need many tool calls and a long answer. The turn loop handles both without user intervention:

Situation Behaviour
Reply cut off by the length limit Continued automatically, up to 4 times, and stitched into one answer
Tool budget reached (16 rounds) The model is asked to answer from what it has already read
Model ends with an empty message One explicit request for the write-up; otherwise the tools that ran are listed
Model stops responding After LLM_TIMEOUT_SECONDS the turn continues with the deterministic planner
Inline reasoning (<think>…</think>) Stripped — never shown as an answer

Reasoning models spend part of the reply budget thinking; LLM_MAX_TOKENS=8192 or higher suits them.


Agent Architecture

A specialist is a tool set plus domain guidance — never a private capability. All twelve draw from the same registry under the same permission gate, which is what keeps the security model legible with a dozen of them in play.

Agent Domain
DevOps Orchestrator Understands the request, selects tools and specialists, sequences the work
Repository Stack, dependencies, entry points, build and test systems
Container Dockerfiles, Compose, image optimisation, container debugging
CI/CD Jenkins, GitHub Actions, GitLab CI, Azure Pipelines — design, generation, failure analysis
Kubernetes Workloads, services, probes, resources, RBAC, Helm, Kustomize
Infrastructure-as-Code Terraform, Bicep, CloudFormation — plan analysis, replacement, drift
Azure App Service, Container Apps, AKS, Functions, ACR, Key Vault, Monitor, managed identity
AWS ECS, EKS, Lambda, S3, CloudWatch, IAM, CloudFormation, ECR
Observability Logs, metrics, traces; turning output into a diagnosis
Incident Timeline reconstruction, correlation, mitigation, postmortems
Security Secret exposure, container and IaC misconfiguration, IAM and RBAC risk
Cost Oversizing, idle resources, container resource allocation

Routing is keyword-weighted, with provider-scoped terms weighted higher — "read the logs" goes to Observability, "read the CloudWatch logs" goes to AWS, because that decides which credentials and CLI the task needs. A pasted log always goes to Observability, even when its lines mention images, pods or containers.

Tools

Tool Level What it does
inspect_repository L1 Build the repository map
list_files · read_file · search_files L1 Sandboxed filesystem access
analyze_logs L1 Parse, group, match signatures, order causally — available to every specialist
plan_containerization L1 Generate a Dockerfile + .dockerignore (writes nothing)
plan_pipeline L1 Generate a CI/CD pipeline (writes nothing)
scan_for_secrets L1 Credential detection with masked previews
detect_tool_versions L1 Probe what is actually installed
propose_file_changes L2 Diff + approval + write — the only way to modify files
run_command L3 Classified execution with real exit codes
cloud_cli L4 az / aws / gcloud against the machine's existing credentials

Skills

Skill Level Risk Composition
InspectWorkspace L1 safe inspect_repository
AnalyzeLogs L1 safe analyze_logs
SecurityReview L1 safe scan_for_secrets → inspect_repository
EnvironmentReport L1 safe detect_tool_versions
GenerateDockerfile L2 produces changes inspect → plan → diff → approve → write
CreateJenkinsfile L2 produces changes inspect → plan → diff → approve → write
CreatePipeline L2 produces changes Jenkins · GitHub Actions · GitLab CI · Azure Pipelines
BuildContainer L3 executes run_command (docker build)

Machine-readable contracts live in packages/tool-schemas/, generated by scripts/export_schemas.py. That directory is the seam an MCP bridge plugs into: a remote MCP server's tools register with the same Tool shape and permission level, and no agent code changes.


Workspace Access

Four cumulative levels, granted per workspace. Every tool declares the level it needs; a tool cannot raise its own. Ask for something above the grant and the agent names the level required and stops.

Level Name What it allows Example request
L1 Read Inspect files, structure, configuration "Explain this Dockerfile"
L2 Write Modify files in the workspace, diff-first "Fix my Dockerfile"
L3 Execute Run classified commands "Build the image"
L4 External Reach cloud providers and external platforms "Deploy to Azure"

The workspace console

Command classification

Every command is classified before it runs. Classification is deny-biased: anything unrecognised is treated as mutating, never as safe.

Class Behaviour Examples
READ_ONLY Runs immediately at L3 git status · terraform plan · kubectl get · docker ps
MUTATING Pauses for approval, offers the dry run terraform apply · kubectl apply · docker push
DESTRUCTIVE Approval plus typed confirmation terraform destroy · kubectl delete · helm uninstall
BLOCKED Never runs, at any level rm -rf · curl … | sh · sudo · git push --force · IAM mutation

Commands run through shlex argv — never shell=True — so chaining, substitution and redirection are refused rather than executed. Only the 88 known DevOps binaries on the allowlist can be invoked at all.


CI/CD

Stages are built from the repository's own commands. A stage with no detected command is omitted, not filled with a plausible guess — and the omission is reported:

"No Dockerfile was found, so image build and publish stages were left out. Run the containerisation skill first if you want them."

Supported: Jenkins (declarative), GitHub Actions, GitLab CI, Azure Pipelines.

The landing page models a full delivery pipeline — Source → Build → Test → Security Scan → Containerize → Publish → Deploy → Monitor — with the five statuses a real run moves through. Switch it to the failing scenario and a non-zero exit stops the pipeline and skips the rest, which is the behaviour the generated pipelines actually have.

Status Meaning
Queued Waiting for an earlier stage. Nothing has run yet.
Running Executing now. Output streams into the run log as it goes.
Passed Finished with exit code 0 and met the stage's own gate.
Failed Exited non-zero. The pipeline stops here and later stages are skipped.
Skipped Never started, because an earlier stage failed or a condition excluded it.

A failing pipeline run

Pipeline repair works the other way round: paste the failing run's log, and the log analyser finds the first failure, then the pipeline skill proposes a minimal diff against the workflow file — with the cause quoted from the log before any edit is suggested.


Containers

From a Node service whose package.json declares engines.node: ">=20", whose src/server.js listens on 4000 and serves /healthz:

# syntax=docker/dockerfile:1

# ---------- dependencies ----------
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci

# ---------- production dependencies ----------
FROM node:20-alpine AS prod-deps
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci --omit=dev && npm cache clean --force

# ---------- build ----------
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NODE_ENV=production
RUN npm run build

# ---------- runtime ----------
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production \
    PORT=4000

RUN addgroup -g 1001 -S app && adduser -u 1001 -S app -G app

COPY --from=builder --chown=app:app /app ./
COPY --from=prod-deps --chown=app:app /app/node_modules ./node_modules

USER app
EXPOSE 4000

HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD wget -qO- http://127.0.0.1:4000/healthz >/dev/null 2>&1 || exit 1

CMD ["npm", "run", "start"]

Every choice above traces to a file that was read:

  • node:20 — the engines constraint in package.json, not a default
  • npm ci — a package-lock.json is present
  • EXPOSE 4000 — app.listen(4000, …) in src/server.js
  • /healthz — the route declared in the source, so the probe hits something real
  • prod-deps stage — dev dependencies never reach the runtime image
  • manifests copied before source — a code edit does not invalidate the install layer

When the stack is one the generators do not cover, it says so and generates nothing. Guessing a Dockerfile is worse than admitting the gap.


Azure

Connect: Azure CLI session (nothing stored) or a service principal (client secret encrypted at rest). A Microsoft-identity OAuth method is declared in the registry and reported as not configured in this build rather than shown as if it worked.

You are never asked for a Microsoft username and password. The CLI method uses the session az login already created; the service-principal method is validated by requesting a token from login.microsoftonline.com — which changes nothing on your machine and proves the credential works before it is stored.

When connected the card shows the subscription name and id, the tenant, and the signed-in account — never a secret.

What the Azure specialist covers: App Service, Container Apps, AKS, Functions, ACR, Key Vault, Monitor and managed identity, through az at L4.


AWS

Connect: a named profile from ~/.aws/config, or IAM Identity Center (SSO). Only the profile name is stored — the credential file itself is never read or copied. Access-key entry is deliberately not offered: there is a better mechanism on every supported path.

Connecting runs aws sts get-caller-identity --profile <name>, so the connection is proven, not assumed. An expired SSO session is reported as Needs re-authentication with the aws sso login command to fix it, rather than as a generic failure.

When connected the card shows the account id, the caller ARN and the region.

What the AWS specialist covers: ECS, EKS, Lambda, S3, CloudWatch, IAM, CloudFormation and ECR, through aws at L4.


Jenkins

Connect: server URL, username and API token.

Use an API token, not your password. Jenkins issues tokens from Your name → Security → API tokens. The form rejects a value containing spaces with exactly that advice, because that is what a pasted password usually looks like.

The token is encrypted before it reaches the database and is never returned to the browser. Connecting performs an authenticated GET {url}/api/json and reads the X-Jenkins header, so the version on the card is the server's own.

When connected the card shows the server URL, the Jenkins version and the authenticated user.

What the CI/CD specialist covers: declarative Jenkinsfile generation with real stages, credentials referenced by id, build-failure analysis, and migration between Jenkins and the other three systems.


Kubernetes

Connect cluster: pick a context that already exists in your kubeconfig. Only the context name is stored; the kubeconfig is never copied, and the current context is never changed — every command the agent runs passes --context explicitly.

Connecting runs kubectl --context <name> version -o json against the API server, so a cluster you cannot reach is reported as unreachable instead of as connected.

When connected the card shows the context, the cluster server version and the active namespace.

What the Kubernetes specialist covers: workloads, services, probes, resources, RBAC, Helm and Kustomize. Crash-loop diagnosis reads pod status, events and the previous container's logs, then names the cause with the evidence attached.


Terraform

Terraform is a local tool integration, not a login provider. The card shows whether the CLI is installed, its version, and — when a workspace is initialised — the workspace and backend type, each read from Terraform's own output.

Plans are read, never applied, until you say so: terraform plan is READ_ONLY and runs at L3, terraform apply is MUTATING and pauses for approval, terraform destroy is DESTRUCTIVE and needs a typed confirmation on top of it. Plan analysis calls out replacements and destructive changes specifically, because those are the ones that lose data.


Log Analysis

The analyser does four things, in order:

  1. Parse — timestamps, severities, service tags, correlation IDs, stack frames
  2. Group — collapse repeats, so a 400-line retry storm reads as one fact
  3. Match — 26 signatures across Kubernetes, Docker, Node, Python, Java, Terraform, AWS, Azure, CI, networking and infrastructure
  4. Order — separate the first failure from everything that cascaded after it

The fourth step is the one that matters. Given a failed rollout ending in 503 Service Unavailable, it reports:

Root cause (high confidence) — The image reference cannot be resolved in the registry.

First failure — line 3: ERROR kubelet Failed to pull image "…:sha-9f3b21c": manifest unknown 2 later failure groups look like consequences.

The last line is the symptom. The first distinct failure is the cause.

You do not need a special affordance for this: paste the log into the message and the block is found inside the prose around it.

Log analysis

Documentation citations

Every generated artefact carries links to the vendor's own documentation, drawn from a curated registry of 35 authoritative sources. The agent can only cite what is in that registry, which is what makes "never fabricate a documentation link" enforceable rather than aspirational. A test asserts every URL is HTTPS and on an official host; a topic with no match cites nothing rather than reaching for something adjacent.


Security

Control Implementation
Path sandboxing Paths resolve symlinks and .. before containment is checked, so traversal fails closed
Exclusion rules .devopsaiignore (gitignore syntax) plus a default set covering .env, keys, VCS, dependencies, state files
Secret redaction Vendor token shapes, private-key blocks, connection strings, and entropy-scored KEY=value assignments — applied before content reaches a model or the audit log
Credential storage Fernet encryption with a key from CREDENTIAL_ENCRYPTION_KEY or a 0600 gitignored key file; if encryption is unavailable, credential methods are refused rather than stored in the clear
Model API keys Keys entered in the interface are encrypted the same way, bound to their provider, and never returned or audited
Credential exposure A recursive filter strips secret-shaped keys from every API response; secrets never enter a model prompt, the audit trail records field names only, and nothing is kept in browser storage
Approval gate Writes and mutating commands suspend until a human decides; a timeout resolves as rejected, never as consent
Audit trail Every tool call, command, write, approval and cloud call, with the detail passed through the redactor first
Binary allowlist Only the 88 known DevOps binaries on the allowlist can be invoked at all

Verified by tests/test_sandbox.py, test_redaction.py, test_classifier.py, test_ignore.py, test_permissions.py, test_local_agent.py, test_integrations.py, test_llm_config.py.

What it will not do

  • Never invents output. If a command did not run, there is no output to show.
  • Never writes silently. Every file change is a diff behind an approval gate.
  • Never leaves the sandbox. Symlinks and .. fail closed.
  • Never forwards secrets. Redaction happens before anything reaches a model or a log.

Architecture

flowchart TB
    subgraph browser["Browser"]
        UI["Next.js app<br/>landing · workspace · integrations · activity"]
    end

    subgraph api["Agent API — FastAPI"]
        ORCH["Orchestrator<br/>routing · turn loop"]
        LLM["LLM abstraction<br/>anthropic · openai · nvidia · azure · bedrock · ollama"]
        TOOLS["Tool registry<br/>12 tools, each with a permission level"]
        SKILLS["Skill registry<br/>8 skills, each with a risk class"]
        INTEG["Integration registry<br/>9 providers · connectors · encrypted secrets"]
        APPROVE["Approval gate"]
        AUDIT["Audit trail"]
        SEC["Security layer<br/>redaction · classifier · ignore rules"]
        MAP["Repository mapper"]
        DOCS["Documentation registry<br/>35 curated sources"]
    end

    subgraph machine["Machine that owns the code"]
        SANDBOX["Workspace sandbox"]
        SHELL["Classified shell"]
        CLI["docker · kubectl · helm<br/>terraform · az · aws · git"]
    end

    DB[("PostgreSQL / SQLite<br/>workspaces · tasks · audit · memory · integrations")]

    UI -- "HTTP + SSE" --> ORCH
    UI -- "HTTP" --> INTEG
    ORCH --> LLM
    ORCH --> TOOLS
    ORCH --> SKILLS
    SKILLS --> TOOLS
    TOOLS --> APPROVE
    TOOLS --> SEC
    TOOLS --> SANDBOX
    TOOLS --> SHELL
    INTEG --> SHELL
    INTEG --> SEC
    SHELL --> CLI
    MAP --> SANDBOX
    SKILLS --> DOCS
    ORCH --> AUDIT
    INTEG --> AUDIT
    APPROVE --> AUDIT
    AUDIT --> DB
    ORCH --> DB
    INTEG --> DB
Loading

Two deployment topologies

flowchart LR
    subgraph same["Same machine — default"]
        direction TB
        A1["Agent API"] --> S1["Sandbox + shell<br/>in-process"]
    end

    subgraph split["Split — LOCAL_AGENT_URL set"]
        direction TB
        A2["Agent API<br/>container or server"] -- "token-authenticated HTTP" --> LA["Local Workspace Agent<br/>on the developer's machine"]
        LA --> S2["Sandbox + shell"]
    end
Loading

In the split topology the Local Workspace Agent re-classifies every command on its own side. A compromised API still cannot make it run something the classifier blocks.

The turn

sequenceDiagram
    participant U as User
    participant W as Web
    participant O as Orchestrator
    participant T as Tool registry
    participant A as Approval gate
    participant F as Workspace

    U->>W: "Containerize this project"
    W->>O: POST /api/chat
    O-->>W: task id + SSE stream
    O->>T: inspect_repository
    T->>F: scan (honouring .devopsaiignore)
    F-->>T: files, manifests, ports, health route
    T-->>O: repository map
    O-->>W: progress · repository map
    O->>T: plan_containerization
    T-->>O: Dockerfile + .dockerignore + reasons + citations
    O->>T: propose_file_changes
    T-->>W: unified diff
    T->>A: request approval (mutating)
    A-->>W: approval card
    U->>W: Approve
    W->>A: POST /api/approvals/{id}
    A-->>T: approved
    T->>F: write files
    T-->>O: written paths
    O-->>W: result + audit entry
Loading

Installation

Quick Start covers the default path: ./start.sh on a machine with Python 3.10+ and Node.js 20+. This section covers the alternatives.

Manual setup

For when you want the two services in separate terminals, or start.sh does not suit your environment:

cp .env.example .env                                  # then edit as needed
python3 -m venv .venv
.venv/bin/pip install -e "apps/api[dev]"              # API + test tooling
(cd apps/web && npm install)                          # web app

make api        # terminal 1 — Agent API on http://127.0.0.1:8000 (auto-reload)
make web        # terminal 2 — web app on http://localhost:3000

With a model

See Model Providers — configure it from the interface, or in .env.

Credential encryption key

Used for everything the app stores encrypted: integration credentials (Jenkins token, GitHub PAT, Azure service principal) and model API keys entered in the interface. For local use it is optional — the backend generates a 0600 key file next to the project and gitignores it. In any shared or hosted deployment, set it explicitly and keep it in your secret manager; losing it makes stored credentials unrecoverable.

# .env — generate with: python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
CREDENTIAL_ENCRYPTION_KEY=…

Full stack with Docker Compose

docker compose up --build     # web :3000 · api :8000 · postgres :5432

Mount the projects you want to connect with WORKSPACE_MOUNT, or run the Local Workspace Agent on the host and set LOCAL_AGENT_URL.

Split topology

Run the API anywhere; keep filesystem and shell access on the machine that owns the code.

# on the developer's machine
LOCAL_AGENT_TOKEN=$(openssl rand -base64 32) \
LOCAL_AGENT_ROOTS=/Users/you/projects \
make agent                                   # → :8100

# wherever the API runs
LOCAL_AGENT_URL=http://127.0.0.1:8100
LOCAL_AGENT_TOKEN=<same token>

Configuration

All settings are environment variables, read from .env at the repository root. Copy .env.example to start; start.sh does this for you on first run. .env is gitignored — never commit it.

Variable Default Purpose
LLM_PROVIDER nvidia nvidia · openai · anthropic · azure_openai · bedrock · ollama · none
LLM_MODEL meta/llama-3.3-70b-instruct Model identifier (deployment name for Azure OpenAI)
LLM_MAX_TOKENS 8192 Maximum tokens per model reply
LLM_TEMPERATURE 0.1 Sampling temperature
LLM_TIMEOUT_SECONDS 120 Per-request timeout before falling back to the deterministic planner
NVIDIA_API_KEY · OPENAI_API_KEY · ANTHROPIC_API_KEY — Provider keys
NVIDIA_BASE_URL · OPENAI_BASE_URL · OLLAMA_BASE_URL provider defaults Endpoint overrides
AZURE_OPENAI_API_KEY · AZURE_OPENAI_ENDPOINT · AZURE_OPENAI_DEPLOYMENT · AZURE_OPENAI_API_VERSION — Azure OpenAI
AWS_REGION us-east-1 Bedrock region
DATABASE_URL SQLite in .logs/ postgresql+asyncpg://user:pass@host/db for PostgreSQL
CREDENTIAL_ENCRYPTION_KEY generated key file Fernet key for stored credentials — set this in any real deployment
WORKSPACE_ROOTS (any) Comma-separated directories workspaces must live under
ALLOW_EXECUTE true Master switch for command execution
COMMAND_TIMEOUT_SECONDS 600 Per-command timeout
REDACT_SECRETS true Redact credentials before model or audit log
REQUIRE_APPROVAL_FOR_WRITE true Approval gate for file writes
REQUIRE_APPROVAL_FOR_MUTATING true Approval gate for mutating commands
LOCAL_AGENT_URL · LOCAL_AGENT_TOKEN — Split topology — see below
API_PORT · WEB_PORT 8000 · 3000 Ports used by start.sh

Generate an encryption key with:

python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

Model provider, model, key and reply length can also be set from the interface; those values override .env and are stored encrypted in the database (see Model Providers).


Running Locally

make up          # both apps, one command
make api         # just the Agent API        → :8000
make web         # just the web app          → :3000
make agent       # the Local Workspace Agent → :8100
make test        # 326 backend tests
make lint        # ruff + mypy + tsc + eslint
make build       # Next.js production build
make evals       # DevOps evaluation suite
make e2e         # end-to-end HTTP smoke test against a running API
make ui          # 28 browser checks against a running instance
make media       # re-record docs/media

Open the workspace, connect a project folder at L1 Read, and ask it to inspect the project. Raise to L2 Write when you want it to generate files.

Browser checks and media

pip install playwright && playwright install chromium

python scripts/ui_smoke.py          # 28 browser checks against a running instance
python scripts/capture_media.py     # regenerate docs/media from the live app

ui_smoke.py drives the flows a visitor actually takes — the pipeline's passing and failing runs, the capability tabs, and the integrations page's full connect → test → disconnect cycle against the real backend — then checks every page for horizontal overflow at 375, 768, 1024, 1440 and 1920px. capture_media.py records the screenshots and GIFs in this README from that same running instance.

Project layout

devops-autopilot/
├── apps/
│   ├── api/                       Agent API — FastAPI
│   │   ├── app/
│   │   │   ├── agents/            specialist profiles, routing, prompts, orchestrator
│   │   │   ├── api/routes/        health · workspaces · tasks · approvals · catalog · analysis · integrations
│   │   │   ├── approvals/         approval gate
│   │   │   ├── audit/             redacted operation history
│   │   │   ├── core/              permissions · SSE event bus
│   │   │   ├── db/                SQLAlchemy models + async session
│   │   │   ├── integrations/      provider registry · connectors · encrypted credential store
│   │   │   ├── llm/               provider abstraction · adapters · interface-configured settings
│   │   │   ├── memory/            project-level memory
│   │   │   ├── rag/               curated documentation registry
│   │   │   ├── security/          redaction · command classifier · ignore rules
│   │   │   ├── skills/            skill registry + builtin skills
│   │   │   ├── tools/             tool registry · terminal · patching
│   │   │   └── workspace/         sandbox · scanner · repository map · local-agent client
│   │   └── tests/                 326 tests
│   ├── local-agent/               sandboxed shell + filesystem over a token-auth API
│   └── web/                       Next.js app
│       ├── app/                   landing · workspace · integrations · activity
│       ├── components/            pipeline · capability showcase · integration cards · diff · approval · terminal
│       └── lib/                   API client · SSE · event reducer · types
├── packages/tool-schemas/         generated machine-readable contracts
├── docs/design/                   the generated design system
├── docs/media/                    README screenshots and recordings
├── evals/                         DevOps evaluation suite
├── fixtures/                      sample project the E2E test drives
├── scripts/                       e2e smoke · UI smoke · media capture · schema export · LLM check
├── docker-compose.yml
└── .env.example

API

Method Path Purpose
GET /api/health Service, LLM mode, which DevOps CLIs are present, active policy
GET POST /api/workspaces · /api/workspaces/connect List / connect a workspace at a permission level
GET /api/workspaces/{id}/map The repository model (?refresh=true to rescan)
GET /api/workspaces/{id}/files · /file Sandboxed listing and redacted reads
POST /api/workspaces/{id}/permission Raise or lower the grant
GET POST /api/workspaces/{id}/memory Project memory
POST /api/chat · /api/tasks Start an agent turn (returns a task id + stream URL)
GET /api/tasks/{id} · /api/tasks/{id}/stream Task result · SSE event stream
GET POST /api/approvals · /api/approvals/{id} Pending approvals · decide one
GET POST /api/tools · /api/tools/execute Tool catalogue · direct gated invocation
GET /api/skills · /api/agents Capability catalogues
GET /api/integrations · /api/integrations/registry Providers with live state · the static registry alone
GET /api/integrations/{id} One provider: methods, probe, status, non-secret facts
POST /api/integrations/{id}/connect · /test Validate and store a connection · re-verify it
DELETE /api/integrations/{id} Forget the connection, including any stored credential
GET /api/llm/status · POST /api/llm/test Provider reachability · a live completion and tool-call check
GET PUT DELETE /api/llm/config Read · test-and-save · reset the interface model configuration (key never returned)
POST /api/logs/analyze Standalone log root-cause analysis
GET /api/activity Audit trail
GET /api/docs/sources The documentation registry citations resolve against

Streamed event types: status · progress · agent · token · tool_start · tool_end · command · changeset · approval · result · error · heartbeat. The bus refuses to publish an unknown event type, which is how model reasoning stays out of the stream.

Testing

make e2e drives the real HTTP API exactly as the browser does — connect a workspace, ask the agent to containerise, read the SSE stream, receive the diff, approve, confirm the files landed on disk — and asserts the security properties along the way: traversal refused, .env unreadable, execute tools refused at L2, destructive commands refused, no secret in the audit trail.

make evals scores fourteen DevOps task cases across seven dimensions:

accuracy         ████████████████████ 25/25 (100%)
tool_selection   ████████████████████  2/2  (100%)
completion       ████████████████████  5/5  (100%)
safety           ████████████████████ 12/12 (100%)
patch_quality    ████████████████████ 12/12 (100%)
validation       ████████████████████  2/2  (100%)
grounding        ████████████████████  8/8  (100%)

14/14 cases · 66/66 checks

Cases include: containerise Node and Python services · refuse to guess for an unknown stack · generate a Jenkinsfile and a GitHub Actions workflow · root-cause a CrashLoopBackOff · identify an OOMKill from exit 137 · explain a Terraform replacement · stay honest when nothing matches · detect a committed credential · diagnose a poor Dockerfile · avoid unsafe actions · enforce permission boundaries · route to the right specialist.

Design

The interface follows a dedicated design system: a dark graphite console palette with semantic blue, cyan, green and violet accents, Inter for prose and JetBrains Mono for machine output, and WCAG 2.2-level contrast and focus states. The full system — tokens, type scale, motion rules and accessibility checklist — is in docs/design/DESIGN_SYSTEM.md.

The rule that shapes every screen: anything a machine emitted renders in JetBrains Mono; anything a human reads as prose renders in Inter. Paths, commands, exit codes, image digests and log lines are visibly machine output. Colour is reserved for state and never carries meaning alone — every status is icon + text + colour, and every icon, status indicator and diagram symbol carries a label, tooltip or legend.

Verified at 375 / 768 / 1024 / 1440 / 1920px with zero horizontal overflow and no console errors, and prefers-reduced-motion collapses every animation to its final state.


Troubleshooting

Symptom Cause Resolution
Chat stays on Planning (llm mode) for a long time The model is slow or not responding Integrations → Model provider → Test the model. If it times out, choose another model with Change model or key
The model did not respond … continuing with the deterministic planner Provider timeout As above. The result shown is still real — the same skills ran
Credential storage unavailable The cryptography package is missing Restart with ./start.sh; it reinstalls when dependencies change
A connect dialog says the CLI was not found az, aws, gh, kubectl, terraform, docker or helm is not installed on the host Install it and sign in with it, then reopen the dialog
Azure shows Needs re-authentication No active az login session Run az login, then Connect Azure again
This request needs a higher permission level The workspace grant is below what the task needs Raise the level in the workspace sidebar; it applies from the next turn
make: .venv/bin/python: No such file or directory First run Any make target now bootstraps the virtual environment; or run ./start.sh
Port 3000 or 8000 already in use Another process holds the port WEB_PORT=3001 API_PORT=8001 ./start.sh
Web app fails with a native-module error after copying the project between machines node_modules built for another OS start.sh detects this and reinstalls; or delete apps/web/node_modules
Behind a corporate proxy the model test reports network or a proxy blocked the request Outbound HTTPS to the provider is blocked Allow the provider host, or use Ollama locally

Logs are written to .logs/api.log and .logs/web.log.


Screenshots

Landing page Integrations
Landing — the delivery pipeline, the capability showcase, the permission model Integrations — nine providers rendered from the registry, with their live state on this machine
Workspace Log analysis
Workspace — permission on the left, the execution timeline in the centre, the live repository model on the right Log analysis — first failure separated from the cascade, with checks, fixes and citations
Earlier screenshots (approval flow, responsive layouts)

Approval with diff Applied result Tablet Mobile


Limitations

This is a single-tenant v1, built to run on an engineer's machine or a private server. What is not built, stated plainly so nothing here oversells:

  • Multi-tenancy and authentication. There are no user accounts, organisations or roles, and the API itself is unauthenticated. Run it locally or behind your own authentication proxy.
  • OAuth connection flows. Microsoft identity and a GitHub OAuth app are declared in the integration registry and reported as not configured in this build — never presented as working.
  • Vector RAG. Citations come from a curated registry of 35 documentation roots, not an embedding index over fetched pages.
  • Cloud resource graphs. Azure and AWS are reached through their CLIs using the host's credentials; there are no SDK-based inventories or monitoring query builders.
  • Jenkins job API. Jenkinsfile generation, log analysis and a verified server connection work; fetching a specific build's metadata is not wired.
  • Kubernetes live watch. kubectl runs at L3 and connections are verified; there is no in-cluster event stream.
  • MCP client. The tool registry accepts remote tools with the same shape and permission level; no MCP transport is implemented yet.
  • Automated rollback. Change sets record original content hashes and the audit trail is complete, but automated restore and rollout undo are not implemented.
  • Docker Compose images are written and validated but were not built in the development environment; the zero-infrastructure path is the one exercised end to end.

Roadmap

Platform

  1. Multi-tenancy — organisations, SSO (OIDC/SAML), role-based access; every record scoped by tenant
  2. Managed secrets — per-tenant envelope encryption through AWS KMS, Azure Key Vault or HashiCorp Vault
  3. Model policy per organisation — managed models with usage metering, or bring-your-own-key, set by an org admin
  4. Federated cloud access — GitHub App, Microsoft Entra application, AWS cross-account role assumption; no long-lived keys

Capabilities

  1. OAuth connection flows for Azure and GitHub, with scopes shown before consent
  2. MCP client transport — GitHub, GitLab, Jenkins, Grafana, PagerDuty as registered tools
  3. Vector index over fetched documentation, keeping vendor docs and workspace knowledge separable
  4. Rollback execution — patch restore, kubectl rollout undo, previous-image redeploy
  5. Kubernetes live debugging — events, previous-container logs, endpoint correlation
  6. Editor surface — Monaco with completions for Dockerfile, Compose, Jenkinsfile, Kubernetes and Terraform

About

DevOps Autopilot is an independent project, designed and built end to end by Shammi: the agent architecture, the skills, the security model and the interface.

It started from a simple frustration. Most AI tools for DevOps explain what you should do and stop there. I wanted one that reads the actual repository, makes the change, shows the diff, and only runs something after a person has approved it. Everything else in this project follows from that.

Feedback, issues and pull requests are welcome.


Agentic AI applied to real DevOps engineering work.

About

An agentic AI platform for CI/CD, cloud infrastructure, containers, deployments and DevOps operations.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages