AgentStack
MCP verified Apache-2.0 Self-run

Simian Agent

mcp-go-steer-simian-agent · by go-steer

AI-native chaos engineering orchestrator for Kubernetes — autonomous planning loop, DPv2-compatible engines (NetworkPolicy + Envoy fault injection), and MCP tools for arena/SUT/baseline.

No reviews yet
0 installs
18 views
0.0% view→install

Install

$ agentstack add mcp-go-steer-simian-agent

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Simian Agent? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Simian Agent

AI-native chaos engineering orchestrator for Kubernetes. Milestone 1 shipped (directed-mode end-to-end on Chaos Mesh). Milestone 2 adds the provisioner — simian arena for namespace eligibility and RBAC, and simian sut for deploying / verifying the System Under Test. Milestone 3 adds autonomous mode — the planning loop that drafts and executes attack plans against a baseline-checked arena.

> Docs: Getting started · Design · Requirements · Roadmap

What works today

Arena lifecycle (M2 Part A)

  • simian arena create — annotates a namespace simian.chaos/eligible="true" and creates the chaos-SA Role + RoleBinding for it. Idempotent on re-run; refuses to overwrite a namespace someone else owns.
  • simian arena destroy — removes RoleBinding + namespace. Refuses if simian-managed chaos resources are still active (override with --force).
  • simian arena describe — eligibility annotation, exclusion list, RoleBinding state, active-fault count.
  • ValidatingAdmissionPolicy backstop — even a buggy or compromised simian-provisioner SA cannot create non-eligible namespaces or grant the chaos SA into namespaces that aren't arenas.
  • Annotation-driven eligibility in simian serve — when --eligible-namespace is omitted, the controller honors simian.chaos/eligible="true" live (no restart needed after simian arena create).

SUT lifecycle (M2 Part B)

  • simian sut list — show built-in SUTs from the registry. Online Boutique ships by default; the registry is pluggable for future SUTs.
  • simian sut deploy --namespace [--sut online-boutique] [--create-arena] — apply the SUT manifests via server-side apply, wait for declared workloads to reach Ready, hold for the configured stability window, capture and cache the Baseline. With --create-arena, composes arena create first.
  • simian sut destroy --namespace [--with-arena] [--force] — remove SUT resources; with --with-arena, also tear down the arena (RoleBinding + namespace).
  • get_baseline MCP tool — read-only access to the controller's cached baseline; returns {exists: false} until M3 unifies the deploy + serve processes (today the deploy CLI's cache is local to the CLI).

Autonomous mode (M3)

  • simian plan --namespace [--hypothesis "..."] — generate an AttackPlan against a real arena (informer-backed topology snapshot, cached baseline, fault catalog, recent-fault history) and emit it as JSON. Default --dry-run=true does not apply.
  • simian serve --autonomous --autonomous-namespace [--cycle-interval 5m] — run the planning loop. Each cycle: health gate (baseline cached, all baseline workloads Ready, no active simian-managed faults) → topology snapshot → Generator.Generate (Gemini structured output → AttackPlan) → bounded execution under per-cycle caps (--max-faults-per-cycle, --max-severity-per-cycle, the executor's existing --duration-ceiling / --max-concurrent-faults / --min-cooldown).
  • DAG-aware execution — plan steps with depends_on are layered topologically; within a layer, fan-out is capped by MaxConcurrentFaults (set to 1 to fully serialize). Steps exceeding the severity cap are skipped with audit reason severity-cap.
  • LLM-down clean skip — if the LLM is unreachable or returns schema-invalid output twice, the cycle emits cycle.llm_unavailable + cycle.skipped and applies nothing.
  • New read-only MCP toolsget_topology(ns), get_recent_faults(ns, limit), establish_baseline(ns, sut), plus get_metrics (stub until a metrics provider is wired in a later milestone).

DPv2-compatible chaos engines (post-M3)

  • network-policy engine — partition chaos via standard networking.k8s.io/v1 NetworkPolicy. Works on GKE Dataplane V2, where Chaos Mesh's NetworkChaos is silently bypassed. Partition only (deny ingress / egress / both for a labeled pod set); no delay / loss / jitter.
  • envoy-fault engine — HTTP-layer delay + abort via an Envoy sidecar injected at SUT-deploy time. Two kinds: EnvoyHttpDelay and EnvoyHttpAbort. The driver pokes each pod's Envoy admin API (port 15000) to flip the fault filter on/off — no Kubernetes resources are created or destroyed at chaos-time.
  • Envoy injectionsimian sut deploy injects the Envoy sidecar + iptables init container ONLY when explicitly requested (chart default sutInjection.envoyFaults: false; CLI --no-envoy-faults is the inverted flag). Opt out per-workload at injection time with the simian.chaos/no-envoy-injection: "true" pod-template annotation. The topology snapshot flags injected workloads as envoy=true so the autonomous planner only proposes envoy-fault chaos against eligible workloads.
  • Background: see DPv2-compatible chaos engines for the full rationale (chaos-mesh#3302, cilium#19975) and design decisions.
Using the new engines (deterministic-control mode)

Both engines accept simian chaos --engine ... --kind ... --spec ''. Examples:

# network-policy: 60s ingress+egress partition of cartservice
simian chaos --engine network-policy \
  --kind NetworkPolicy --api-version networking.k8s.io/v1 \
  --namespace boutique-m3 --workload cartservice --duration 60s \
  --spec '{"labelSelectors":{"app":"cartservice"},"directions":["ingress","egress"]}'

# envoy-fault: 60s 300ms delay on 100% of inbound HTTP/gRPC requests to frontend
# (requires the workload to have been deployed with --with-envoy-faults
# AND to be HTTP-probed or TCP-probed — see "Known limitation" below)
simian chaos --engine envoy-fault \
  --kind EnvoyHttpDelay --api-version simian.io/v1 \
  --namespace boutique-m3 --workload frontend --duration 60s \
  --spec '{"percentage":100,"fixed_delay_ms":300,"labelSelectors":{"app":"frontend"}}'

# envoy-fault: 60s 503 abort on 100% of inbound requests
simian chaos --engine envoy-fault \
  --kind EnvoyHttpAbort --api-version simian.io/v1 \
  --namespace boutique-m3 --workload frontend --duration 60s \
  --spec '{"percentage":100,"http_status":503,"labelSelectors":{"app":"frontend"}}'

For autonomous mode, the LLM has a strong bias toward Chaos Mesh's larger catalog. To exercise the new engines, pass an explicit hypothesis hint:

simian serve --autonomous --autonomous-namespace boutique-m3 \
  --hypothesis-hint "Verify alternative chaos engines work. Test network-policy
                     to partition a service, and envoy-fault for HTTP delay/abort
                     against any workload flagged envoy=true in topology."
Known limitation: Envoy injection breaks gRPC kubelet probes

This is why the chart default is sutInjection.envoyFaults: false. The current Envoy injection model intercepts ALL inbound TCP on the SUT-declared service ports via iptables PREROUTING REDIRECT to Envoy's listener (port 15006). Envoy speaks HTTP at the L7 layer; it does not understand gRPC health-probe payloads. So:

| Workload probe type | Behavior with Envoy injection | |---|---| | HTTP httpGet probes (e.g. Online Boutique frontend) | ✅ Works — Envoy responds to the probe | | TCP tcpSocket probes (e.g. redis-cart) | ✅ Works — Envoy accepts the TCP handshake | | gRPC grpc: probes on a redirected port (most Online Boutique services) | ❌ Probe fails → kubelet kills the container → CrashLoopBackOff | | gRPC grpc: probes on a NON-redirected port | ✅ Works — no interception |

For Online Boutique specifically, --with-envoy-faults will leave 9 of 12 deployments crash-looping. Until probe rewriting (Istio's pilot-agent style) or an outbound-only redirect mode is implemented, only enable Envoy injection for SUTs whose probes you've audited as HTTP-only or TCP-only.

Workaround for testing envoy-fault against an arbitrary workload: deploy the SUT with --no-envoy-faults, then manually inject Envoy into a single test Deployment whose probes you control. See acceptance-m3b-results.md § "DPv2 chaos engines acceptance — round 3" for an end-to-end recipe.

Directed-mode chaos (M1)

  • simian serve — runs the Fault Executor + MCP server on port 8081 (default).
  • simian chaos --intent "..." — plain-text intent → Gemini translates to a FaultManifest → executor validates and applies.
  • simian chaos --kind ... --spec ... — deterministic-control path; bypasses LLM, builds a manifest from CLI flags.
  • simian chaos --manifest — submit a fully-formed manifest verbatim.
  • simian chaos --list-active / --list-catalog / --clear — inspect and manage.
  • Lease + reaper — every applied fault has a hard duration cap (default 15 min); the in-process reaper sweeps expired leases and clears the underlying CRD.
  • Safety stages — namespace-eligibility (annotation + RBAC AND), workload exclusions, blast-radius tier policy (default permits namespace + node; external opt-in), duration ceiling, concurrency budget.
  • Pluggable LLM — Gemini default (Vertex/ADC and API key both supported); stub provider for tests.
  • Audit log — structured events at every pipeline stage, JSON-formatted via slog.

simian evaluate ships as a stub until M5 (scenario data export). The simian provision command is deprecated; use simian arena and simian sut directly.

Quick start

# Build and test
make all

# One-shot: create the arena, deploy Online Boutique, capture baseline.
bin/simian sut deploy --namespace boutique-1 --create-arena

# Start the controller. With no --eligible-namespace flag, it honors the
# annotation set by `arena create` (live, no restart needed).
source ~/scripts/gemini.sh
bin/simian serve

# In another shell — LLM-translated path against the freshly-deployed arena.
bin/simian chaos --intent "kill one paymentservice pod in boutique-1 for 30 seconds" \
                 --namespace boutique-1

# Deterministic-control path
bin/simian chaos --manifest examples/network-latency-manifest.json

# Tear down both layers (refuses if simian-managed faults are still leased;
# pass --force to override after clearing them via 'simian chaos --clear').
bin/simian sut destroy --namespace boutique-1 --with-arena

Autonomous-mode quick start (M3)

# Set up arena + SUT, capture baseline IN the controller process so the
# autonomous loop can read it via get_baseline.
bin/simian sut deploy --namespace boutique-1 --create-arena --use-controller

# Dry-run plan: emit an AttackPlan as JSON, do NOT apply.
bin/simian plan --namespace boutique-1 --hypothesis "frontend tolerates one cartservice pod restart"

# Run the autonomous loop (every 90s; serializes at MaxConcurrentFaults=1).
bin/simian serve --autonomous --autonomous-namespace boutique-1 \
                 --cycle-interval 90s \
                 --max-faults-per-cycle 2 \
                 --max-severity-per-cycle namespace

For more granular control, simian arena create/destroy/describe and simian sut list/deploy/destroy can be invoked independently.

Project layout

cmd/simian/        single binary, cobra subcommands (serve, chaos, arena, sut, plan, evaluate)
pkg/simian/        core types and interfaces (FaultManifest, AttackPlan, ChaosDriver, LLMProvider, …)
pkg/arena/         arena CRUD (Manager) + annotation-driven eligibility checker (M2 Part A)
pkg/sut/           SUT lifecycle (Manager: apply manifests, wait for Ready, capture Baseline) (M2 Part B)
  onlineboutique/  built-in Online Boutique SUT (embedded manifests from upstream v0.10.2)
pkg/topology/      informer-backed read-only topology Discoverer (M3) — workloads, services, dep graph
pkg/executor/      Fault Executor — single chokepoint for all fault application + recent-faults ring (M3)
pkg/driver/
  chaosmesh/       generic dynamic-CRD driver for the full chaos-mesh.org/v1alpha1 catalog
  litmus/          (M6 placeholder)
pkg/llm/
  gemini/          Vertex AI + Gemini Developer API
  stub/            deterministic test double
pkg/planner/       LLM bridge: translate.go (intent → FaultManifest), generate.go (context → AttackPlan, M3)
pkg/loop/          autonomous-mode planning loop + health gate (M3)
pkg/mcp/           MCP server with directed-mode + autonomous-mode tools
pkg/lease/         in-memory ActiveFault registry + duration-based reaper (Reaper.OnExpire feeds M3 history)
pkg/audit/         structured event logger
pkg/catalog/       blast-radius tier classification (static map + per-spec re-classification)
internal/testutil/ fake driver + fake auditor for tests
deploy/
  manifests/       raw YAML for kubectl apply
  helm/simian/     Helm chart (chaos SA, provisioner SA + admission policy under provisioner.enabled)
examples/          example FaultManifest + spec JSON
docs/              requirements, design, roadmap

Deploying to a cluster

The Helm chart in deploy/helm/simian/ runs the controller in-cluster. It pulls the image from ghcr.io/go-steer/simian-agent, which is published automatically by .github/workflows/release.yml on each v* tag push.

# Default install (uses Chart.AppVersion as the image tag).
helm upgrade --install simian deploy/helm/simian -n simian-system --create-namespace

# Pin a specific published tag.
helm upgrade --install simian deploy/helm/simian -n simian-system \
    --set image.tag=v0.1.0-dev

# Enable the M3 in-controller SUT path (required for `simian sut deploy --use-controller`).
helm upgrade --install simian deploy/helm/simian -n simian-system \
    --set sutInController.enabled=true

# Recommended starting point: layer the "fully-baked-defaults"
# overlay on top of the chart defaults. Pins a known-verified image
# tag, tightens the executor safety policy, leaves experimental
# features off. See examples/values-baked-defaults.yaml for what
# each value is doing and the maintenance contract.
helm upgrade --install simian deploy/helm/simian -n simian-system \
    --create-namespace \
    -f examples/values-baked-defaults.yaml

For ad-hoc dev builds without cutting a release tag, push your own image:

# Build + push to your own ghcr.io path (overrides via env vars).
echo "$GITHUB_TOKEN" | docker login ghcr.io -u "$GITHUB_USER" --password-stdin
make image-push VERSION=mybranch IMAGE_NAME=myorg/simian-agent

helm upgrade --install simian deploy/helm/simian -n simian-system \
    --set image.repository=ghcr.io/myorg/simian-agent \
    --set image.tag=mybranch

Tests

# Unit tests (fast, no external deps)
go test ./...

# Gemini integration (requires Vertex/ADC or GEMINI_API_KEY)
source ~/scripts/gemini.sh
go test -tags=integration ./pkg/llm/gemini/...

Verified manually

  • Vertex/ADC end-to-end against gemini-2.5-pro: plain text + JSON structured output both pass on the integration tests.
  • Binary builds + --help for every subcommand renders.
  • Unit tests cover: blast-tier classification + per-spec escalation, lease registry + expiry, executor pipeline (happy path + 4 rejection types), translator (happy path + schema-invalid retry).
  • Real-cluster smoke against GKE Standard + Chaos Mesh: catalog discovery (14 user-facing fault types), deterministic-control path round-trips a NetworkChaos apply (kernel-level tc -s qdisc confirmed netem delay 250ms installed on paymentservice eth0), explicit --clear and lease.expired reaper paths both fire. PodChaos pod-kill independently observable via pod rotation (AGE=5s, RESTARTS=0 on the new pod).

Known cluster-side gotchas

These bit us during M1 verification. Documenting so the next person doesn't lose 30 minutes:

  • GKE Dataplane V2 (Cilium / anetd) silently breaks NetworkChaos. Chaos Mesh installs a netem qdisc on the pod's `

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.