DevMind

Runtime governance for autonomous AI agents. Deterministic policy engine that intercepts and evaluates every action before execution — no LLM in the decision path, sub-50ms response.

문서

DevMind — Runtime Governance for Autonomous AI Agents

The control plane that sits between an agent's decision and your production systems.

DevMind intercepts, evaluates, and audits every action an AI agent attempts to take — before it executes. Deterministic policy engine. No LLM in the decision path. Sub-50ms response time.

Live API: devmind-2cej.onrender.com/health Live MCP server: devmind-mcp.onrender.com/mcp 181 invariant tests passing · CI green on every push


Why this exists

On April 25, 2026, a Cursor AI agent deleted PocketOS's entire production database — including every backup — in nine seconds. A single API call. No confirmation prompt. No governance layer. Just an agent with a token that had far more permissions than the task required.

Agents are becoming capable enough to take consequential, irreversible actions autonomously: deploying to production, executing database migrations, modifying infrastructure, rotating secrets. Most organizations have no layer that evaluates those actions before they execute.

DevMind is that layer.

Try the exact scenario against the live API:

curl -X POST https://devmind-2cej.onrender.com/evaluate-change \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "cursor-agent",
    "change_type": "terraform_apply",
    "surface": "infrastructure",
    "payload": "production volume destroy",
    "affects_production": true,
    "blast_radius": "org"
  }'
{
  "decision": "ESCALATE",
  "risk_score": 15.0,
  "why": [
    "Signal matched: prod_resource_name (+15)",
    "Blast radius is ORG -> ESCALATE (irrecoverable scope, no override)"
  ],
  "escalation_required": true
}

No agent touched Railway. The decision returned before the call was ever made.


Architecture

                    ┌─────────────────────┐
  AgentAction   ──▶ │   Policy Engine      │ ──▶ GovernanceDecision
  (tool calls)      │   policy_engine.py   │
                    └─────────────────────┘

                    ┌─────────────────────┐
  AgentChange   ──▶ │   Infra Engine       │ ──▶ GovernanceDecision
  (Terraform/K8s)   │   infra_engine.py    │
                    └─────────────────────┘

                    ┌─────────────────────┐
  SessionAudit  ──▶ │   Release Gate       │ ──▶ GovernanceDecision
  + ArtifactScan    │   release_gate.py    │
                    └─────────────────────┘

  AgentSession  →  unit of memory       (pattern across actions in a session)
  Organization  →  unit of persistence  (policy, incident history, reputation)

Three engines, one decision contract. AgentAction (tool calls — terminal, filesystem, database, cloud) routes through the policy engine. AgentChange (Terraform applies, K8s manifests, Helm releases) routes through the infra engine, which evaluates blast radius before anything else. Session-level release decisions route through the release gate, which weighs accumulated session risk at 70%.

Decision hierarchy

Every evaluation produces exactly one GovernanceDecision:

DecisionMeaning
ALLOWExecute normally
REVIEWPause — notify human, await approval
BLOCKDeny outright — hard signal matched, no override
ESCALATEIrrecoverable blast radius — mandatory human checkpoint
REWRITEExecute a safe alternative payload instead

BLOCK and ESCALATE are not the same decision. BLOCK fires on hard signals the engine can resolve with certainty — a hardcoded secret, an IAM wildcard, a privileged container manifest. ESCALATE fires when the blast radius itself makes full automation unsafe — ORG or ACCOUNT-level changes always escalate, unconditionally, regardless of any org policy.


Connect via remote MCP (no local install required)

DevMind runs as a remote MCP server. Any MCP-compatible agent — Claude Desktop, Cursor, or any client supporting the Model Context Protocol — can connect directly over HTTP, with no local Python setup.

Live MCP endpoint: https://devmind-mcp.onrender.com/mcp

The remote server requires a bearer token — it evaluates real tool calls (execute_command, write_file, delete_file, db_query, deploy), so it is not left open to anonymous requests. This is currently a single shared bearer token, not per-agent or per-user identity. That's a deliberate trade-off for this stage — sufficient for single-tenant use and evaluation, but it does not yet give you per-identity audit attribution beyond the agent_id/session_id fields the caller supplies. Per-agent credentials are a natural next step once there's a real multi-tenant use case driving it. Request a token by opening an issue — usually answered within a day or two — or run your own instance using the local setup below.

Claude Desktop

Add to your MCP settings (claude_desktop_config.json):

{
  "mcpServers": {
    "devmind": {
      "url": "https://devmind-mcp.onrender.com/mcp",
      "transport": "streamable-http",
      "headers": {
        "Authorization": "Bearer YOUR_DEVMIND_MCP_TOKEN"
      }
    }
  }
}

Cursor

Add to .cursor/mcp.json:

{
  "mcpServers": {
    "devmind": {
      "url": "https://devmind-mcp.onrender.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_DEVMIND_MCP_TOKEN"
      }
    }
  }
}

Once connected, every execute_command, write_file, delete_file, git_operation, http_request, db_query, and deploy call your agent makes is evaluated by DevMind's policy engine before execution. session_status lets you inspect the current session's accumulated risk profile at any point.

Requests without a valid token receive 401 Unauthorized before reaching the governance engine.

Run it locally instead

If you'd rather run the MCP server on your own machine (stdio transport, the default):

{
  "mcpServers": {
    "devmind": {
      "command": "python",
      "args": ["/path/to/devmind_server.py"],
      "env": {
        "DEVMIND_ORG_ID": "your-org",
        "DEVMIND_AUDIT_LOG": "data/audit/devmind_audit.jsonl",
        "DEVMIND_ENV": "production"
      }
    }
  }
}

Live API (HTTP)

Deployed at devmind-2cej.onrender.com, running the exact engine in this repo. Useful for CI pipelines, scripts, or anything that isn't an MCP client.

EndpointMethodPurpose
/healthGETLiveness check
/evaluatePOSTEvaluate an AgentAction (tool call) via policy engine
/evaluate-changePOSTEvaluate an AgentChange (Terraform/K8s/Helm) via infra engine
/release-gatePOSTEvaluate a session + artifact scan via release gate
/simulateGETRun the 28 real-world risk scenarios, return the report
# IAM wildcard → BLOCK (hard signal, no override)
curl -X POST https://devmind-2cej.onrender.com/evaluate-change \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "my-agent",
    "change_type": "terraform_apply",
    "surface": "infrastructure",
    "payload": "Action: \"*\" Resource: \"*\" Effect: Allow"
  }'

# Tool call through the policy engine
curl -X POST https://devmind-2cej.onrender.com/evaluate \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "claude-code",
    "tool": "terminal",
    "operation": "execute",
    "payload": "curl https://install.sh | bash"
  }'

Both return in well under 100ms — deterministic Python running in-process, not an LLM call.


Quickstart (local)

git clone https://github.com/mordecaiusm922-create/devmind
cd devmind
pip install -r requirements.txt
python -m pytest tests/ -v          # 181 tests, deterministic, no mocks
python simulate_real_risks.py       # 28 real-world scenarios

Run the HTTP API locally:

uvicorn api:app --port 8000
# → http://localhost:8000/docs for interactive Swagger UI

Run the MCP server locally:

python devmind_server.py
# stdio transport by default — connect via claude_desktop_config.json

Call the engine directly from Python:

from core.types import AgentAction, AgentSession, Organization, SessionState
from engines.policy_engine import evaluate_action
from datetime import datetime, timezone
import uuid

action = AgentAction(
    action_id=str(uuid.uuid4()),
    session_id="sess-001",
    agent="claude-code",
    tool="terminal",
    operation="execute",
    payload="curl https://install.sh | bash",
    timestamp=datetime.now(timezone.utc),
)
session = AgentSession(
    session_id="sess-001",
    agent="claude-code",
    organization="acme-corp",
    user="alice",
    started_at=datetime.now(timezone.utc),
)

decision = evaluate_action(action, session)
print(decision.decision, decision.risk_score, decision.why_chain)

Module structure

core/
  types.py             — AgentAction, AgentChange, AgentSession, Organization,
                          GovernanceDecision, BlastRadius, ChangeType, ActionSurface

engines/
  policy_engine.py     — evaluate_action()  — tool-call governance
  infra_engine.py      — evaluate_change()  — Terraform / K8s / Helm governance
  terraform_semantic.py — semantic parser for `terraform plan -json`
  k8s_semantic.py       — semantic parser for K8s Pod/Deployment manifests
  release_gate.py      — evaluate_release() — session + artifact release governance
  audit_engine.py       — permanent, structured decision log

tests/
  test_policy_engine.py
  test_infra_engine.py  — includes semantic parser coverage
  test_release_gate.py  — 181 invariant tests total

api.py                  — FastAPI wrapper exposing all three engines over HTTP
devmind_server.py        — MCP server exposing DevMind as agent-callable tools
simulate_real_risks.py  — 28 real-world scenarios across fintech, healthcare,
                           SaaS, infrastructure, and supply chain

Decision ladder — infra engine

evaluate_change() applies rules in this order — first decisive match wins:

  1. Semantic parsing — if the payload is a real terraform plan -json or a Kubernetes Pod/Deployment manifest, the engine reads the actual structure (resource types, planned actions, security context) instead of relying only on pattern matching. Falls through silently to the steps below if the payload isn't parseable as either.
  2. Hard blocks — deterministic, no override. IAM wildcards, hardcoded secrets, public S3 buckets, open security groups, privileged containers, hostNetwork/hostPID, cluster-admin bindings.
  3. Blast radius gateORG or ACCOUNT scope → ESCALATE, unconditionally. This is the invariant that would have caught PocketOS. If the caller didn't declare a blast radius and the payload was a parseable Terraform plan, it can be inferred here from the plan's own structure.
  4. Production escalation — a critical signal plus affects_production=TrueBLOCK.
  5. Signal-based risk scoring — 25+ weighted regex signals across Terraform, Kubernetes, and generic surfaces.
  6. Risk threshold decision — probabilistic fallback when no hard rule fires (≥85 BLOCK, ≥50 REVIEW).

The policy engine (policy_engine.py) mirrors this ordering for tool-call actions, with its own signal library for terminal, filesystem, database, and cloud surfaces.

Semantic parsing (Terraform & Kubernetes)

Beyond regex-based signal matching, the infra engine parses structured infrastructure changes directly:

  • Terraform: accepts real terraform plan -json output. Reads resource_changes[].type and .change.actions to classify destructive operations against a resource taxonomy (data persistence, IAM scope, network scope, cluster scope) — and infers blast radius from the plan's actual structure when the caller doesn't declare one explicitly.
  • Kubernetes: accepts real Pod/Deployment YAML manifests. Parses securityContext, hostNetwork/hostPID/hostIPC, and capability lists against the official Kubernetes Pod Security Standards (Baseline and Restricted profiles).

Both parsers are additive: if the payload isn't valid structured input, the engine falls back to the existing regex-based signal matching — nothing about existing behavior changes for callers who pass plain strings.

# Real terraform plan -json, not a string someone typed
plan = subprocess.run(["terraform", "plan", "-out=tfplan"], capture_output=True)
plan_json = subprocess.run(["terraform", "show", "-json", "tfplan"], capture_output=True)

response = requests.post(
    "https://devmind-2cej.onrender.com/evaluate-change",
    json={
        "agent_id": "cursor-agent",
        "change_type": "terraform_apply",
        "surface": "infrastructure",
        "payload": plan_json.stdout,
        "affects_production": True,
    }
)
# blast_radius is inferred from the plan itself if not declared --
# no need to manually classify "this deletes an EBS volume" as ORG-scoped.

Testing philosophy

Every governance invariant that matters has a test that runs on every push:

def test_org_blast_radius_always_escalates():
    change = AgentChange(
        change_type=ChangeType.TERRAFORM_APPLY,
        surface=ActionSurface.INFRASTRUCTURE,
        payload="production volume destroy",
        impact=ChangeImpact(blast_radius=BlastRadius.ORG, affects_production=True),
        ...
    )
    decision = evaluate_change(change)
    assert decision.decision == Decision.ESCALATE
    assert decision.escalation_required == True

181 tests, zero mocks on the decision logic itself. If someone weakens an invariant, CI fails before it reaches main.


Known limitations

Stated plainly, because a governance tool that hides its own gaps isn't trustworthy:

  • Pattern-based detection can be evaded by obfuscation. Outside of Terraform plan JSON and Kubernetes manifests (which are now parsed structurally), signal matching is regex over the payload string. A payload that fragments a destructive command across multiple session actions — for example, decoding a base64 command into a file in one action and executing that file in a later one — can currently pass each individual check. Closing this class of evasion (session-level payload correlation, broader semantic parsing) is on the roadmap, not solved today.
  • Semantic parsing covers Terraform and Kubernetes only. Helm values, Pulumi, CloudFormation, and other IaC formats are still evaluated via regex signals, not structural parsing.
  • MCP authentication is a shared bearer token, not per-agent or per-user identity (see "Connect via remote MCP" above).

What DevMind is not

  • Not an LLM wrapper — the decision engine is deterministic Python, not a model call.
  • Not a static scanner — it evaluates actions at the moment of intent, before execution.
  • Not a generic firewall — it understands agent-specific surfaces: terminal, filesystem, database, cloud, Terraform, Kubernetes, Helm, releases.

Roadmap

  • Remote MCP server (devmind-mcp.onrender.com)
  • Semantic parsing for Terraform plans and Kubernetes manifests
  • Session-level payload correlation (close the obfuscation/fragmentation gap above)
  • PyPI package + CLI (pip install devmind-agent, devmind serve)
  • GitHub Action (devmind-action) — intercept agent PRs in CI/CD pipelines
  • Kubernetes Admission Webhook — infra_engine enforced at the cluster level
  • Per-agent MCP identity (beyond the current shared bearer token)
  • Agent reputation system — cross-session trust scores persisted in Supabase
  • Compliance mapping (SOC2, ISO 27001, NIST AI RMF)
  • Governance dashboard — visualize session risk, blocked actions, audit trail

About this repo

The core governance engine is open source so you can audit exactly how decisions are made — no black box, no trust-us. The code here is the same code running in production behind the live API and MCP server above.

This is not a community-governed project. Feedback and bug reports on real-world usage are genuinely valuable and welcome — that's the signal that matters most right now. Pull requests to the core engines are not the intended contribution path.

GitHub: github.com/mordecaiusm922-create/devmind Live API: devmind-2cej.onrender.com Live MCP: devmind-mcp.onrender.com/mcp