Salt × AI · differential edge

Salt + AI — patterns that actually work.

AI writes plausible Salt YAML. Sometimes it runs. The patterns we use, and the failure modes worth knowing.

v1.0 · Updated 2026-05-09

Where AI shines, where it lies.

Most "AI for Salt" content reads like a sales deck. In practice it's good at four specific things and unreliable at four others.

What it's good at

Use AI here. Save hours.

  • Scaffolding. Generating the first 80% of a state file from a clear description. Read it, fix the 20%.
  • Reading errors. Paste a Salt traceback + the failing state. AI explains it faster than digging through -l debug output.
  • Pillar from prose. Translating "50 web servers, 3 envs, TLS varies" into structured pillar YAML.
  • Documenting your states. Generating human-readable runbooks from existing .sls files.
What it lies about

Verify everything here. No exceptions.

  • Module names. AI invents modules that sound right but don't exist in your Salt version.
  • Require chains. Wrong order or misspelled IDs that look plausible but don't compile.
  • Runtime state. AI doesn't know what's installed on your minion, so it guesses.
  • Anything pre-2022. Trained on docs that include patterns Salt removed years ago.

The pattern: AI drafts, you read every line, then you run on a test minion before production. Treat it like a junior.

Prompts that generate working states.

Whether AI-generated YAML runs first try or wastes your afternoon comes down to the prompt.

The format that works

Good prompt
Salt minion version: 3006.4
Target OS: Ubuntu 22.04
Goal: install nginx, enable+start the service, allow ports 80/443 in ufw

Generate a Salt state file (.sls) using these modules only:
- pkg.installed
- service.running
- cmd.run

Include explicit `require:` chains so order is unambiguous.
No comments. YAML only.

Why it works: it pins the version (no 2019-era patterns), names the OS (right package names), constrains the modules, and makes ordering explicit.

The format that wastes your time

Bad prompt
Set up a webserver with Salt

Why it fails: No version → mixed-era YAML. No OS → wrong package names. No module constraint → AI picks weird modules. No require: instruction → implicit ordering.

The "minimal first, then expand" pattern

For complex states, ask AI for the smallest possible working version first. Get it to apply cleanly on one test minion. Then ask it to expand: firewall rules, TLS, monitoring. Each iteration stays small enough that you can read every line.

Always pin the version. Salt's release cadence means modules and signatures shift. AI trained on Salt 3001 docs will hand you patterns that 3006+ rejects. One line at the top — Salt minion version: 3006.x — saves you hours of debugging deprecated syntax.

Paste-the-error troubleshooting.

When a state fails, AI is faster than -l debug for the first read. For the actual fix, less so.

STEP 01

Capture full debug

Run with -l debug. Copy the entire output, not just the red bit. AI uses the surrounding context.

STEP 02

Paste with context

Salt version, target OS, the failing state file, the full traceback.

STEP 03

Ask the surgical question

"What's wrong, and what's the minimum change?" Asking for the minimum forces a focused diagnosis instead of a rewrite.

Common AI wins on Salt errors

Where AI still loses to a senior

If the failure is a multi-minion race, a state that only fails under load, or a config quirk in your GPG/PKI setup, AI can't see your environment. A senior with shell access wins.

MCP for Salt — give Claude shell access (carefully).

MCP is Anthropic's protocol for letting Claude call real tools in your environment. No official Salt MCP server exists. There should be. The architecture we use:

The wire-up, in five lines

  • A small Python MCP server running on the Salt master (or a sidecar with API access)
  • Wraps salt-call locally — or hits the salt-master REST API if you have one
  • Read-only tools first: test.ping, grains.items, state.show_sls, cp.list_states
  • Mutating tools gated: anything that runs (state.apply, cmd.run) defaults to test=True and requires explicit confirmation
  • Every call logged — you want an audit trail when an LLM is targeting production

Why this matters

Without MCP, Claude generates Salt blindly. It can't see installed packages, your existing states, or grain values. With read-only MCP wired up, Claude can ask ("what version is minion-foo running?", "what's in your existing nginx state?") and write states that fit your environment.

Never expose cmd.run as an unconstrained tool. An LLM with arbitrary shell access is a vulnerability waiting to happen. Default everything to read-only, gate mutating calls behind explicit approval, and log every call.

Pillar data from prose.

Pillar generation is where AI saves the most time. Repetitive structure, predictable shape, low risk if you read the diff.

Where it works

Where it doesn't

The secret-sanitizing trick: before pasting any pillar to AI, search-and-replace your real values with <PLACEHOLDER> tokens. Get the AI's output back. Re-substitute the real values locally.

The "looks fine, doesn't run" problem.

AI-generated Salt that compiles plausibly but doesn't run is the biggest time-sink. Five real examples, with the quick checks that catch them.

1. Hallucinated modules

AI invents modules that sound right but don't exist.

ensure_running:
  systemd.unit_running:    # NOT A REAL MODULE
    - name: nginx
Fix: Salt has service.running, not systemd.unit_running. Verify against the state module index before applying.

2. Wrong require chains

AI generates require: blocks that reference state IDs that don't exist or are misspelled. Salt fails the compile step with a confusing error.

Fix: Always run salt-call --local state.show_sls your.state first. It compiles without applying. Compile errors surface in seconds.

3. Deprecated patterns

AI trained on 2019 docs will suggest module signatures that worked then but were removed in 3006+. Especially common with pkg.installed arguments and old file.managed options.

Fix: Pin the version in your prompt. Salt minion version: 3006.x at the top of every prompt cuts this in half.

4. Jinja in the wrong render phase

AI references grains inside pillar files (which render before grains are available), or pillar values inside states without remembering the lookup syntax. Looks fine, fails at compile.

Fix: If a state breaks with "undefined variable", suspect render order before suspecting your data. Pillar renders first, states render second, grains exist throughout but pillar can't see them.

5. Confidently wrong with no source

AI states something authoritatively that's just wrong. "Salt automatically retries failed states" — it doesn't, unless you wire it up. "onchanges is the same as watch" — they're different.

Fix: Cross-reference anything load-bearing against docs.saltproject.io. Your cheat sheet is also a sanity check — if AI suggests a flag that isn't on your cheat sheet, double-check it exists.

The 30-second sanity check that catches all five

# 1. Compile-only — catches typos, missing modules, bad requires
salt-call --local state.show_sls your.state

# 2. Dry-run — catches everything else, no changes made
salt 'minion-test' state.apply your.state test=True

# 3. Read the diff. Then apply for real.
salt 'minion-test' state.apply your.state

AI uplift — what we leave behind when we exit.

Saltify engagements include the AI tooling your team needs to keep using Salt without us in the room.

The handover kit

Why this changes the math

AI doesn't replace anyone, but it usually makes seniors faster and juniors functional. Routine state work moves in-house; we get called back for the architectural decisions, the blue/green cutovers, and the things that need real judgment.

Want this for your team? AI uplift is bundled with every Saltify engagement — blue/green build-outs, multi-master deployments, VCF Salt installs. We don't charge extra for the prompt library, MCP server, or runbook templates. Talk to us.

Built from production Saltify engagements + Anthropic's MCP spec. Patterns evolve as Salt and Claude both ship — last reviewed May 2026.