Batfish and rConfig: validate network changes against real configs with an AI agent
Batfish answers “what will this change do?” before you make it: which traffic an ACL will block, whether a route still reaches its destination, which rules can never match. Its weak point is input. It needs current, complete configs, and gathering them by hand is the step most teams skip. rConfig already holds them. An agent can build the Batfish snapshot from rConfig over MCP, apply the proposed change to a copy, run the questions, and explain the answer.
Best for: ACL and firewall changes, routing changes, change approval evidence.
Tools: rConfig, Batfish (Docker) and pybatfish, an agent that can write files and run Python (Claude Code, Codex CLI, Cursor, VS Code).
rConfig tools used: get_devices, get_latest_config, search_configs.
How it flows
flowchart LR
R["rConfig MCP<br/>current running configs"] --> C["snapshots/current/configs/"]
C --> K["snapshots/candidate/configs/<br/>+ proposed change"]
C --> B["Batfish"]
K --> B
B --> A["Agent explains:<br/>parse issues, dead ACL lines,<br/>traffic that changes"]
Set up Batfish
Batfish runs as a container, and pybatfish is its Python client:
docker run --name batfish -v batfish-data:/data -p 8888:8888 -p 9996:9996 batfish/allinonepython3 -m pip install --upgrade pybatfishCheck Batfish’s documentation for the vendors it parses. Cisco IOS, IOS XE, NX-OS and ASA, Juniper, Arista and Palo Alto are commonly used; coverage varies by feature.
The prompt
We plan to apply the change in
change/acl120.txttolon-edge-02.
- From rConfig, get the latest running config for every device in the London group. Check the command field. Write each to
snapshots/current/configs/<hostname>.cfg.- Copy the folder to
snapshots/candidateand apply the change tolon-edge-02’s file.- With pybatfish, load both snapshots and run initIssues, filterLineReachability, and a differential searchFilters for traffic to 10.40.0.0/16.
- Explain what the change does to traffic, and anything Batfish flags. Show me the code you ran.
The kind of code the agent writes and runs:
from pybatfish.client.session import Sessionfrom pybatfish.datamodel import HeaderConstraints
bf = Session(host="localhost")bf.set_network("london")bf.init_snapshot("snapshots/current", name="current", overwrite=True)bf.init_snapshot("snapshots/candidate", name="candidate", overwrite=True)
# Lines Batfish couldn't parse (expect warnings on obfuscated credential lines)print(bf.q.initIssues().answer(snapshot="candidate").frame())
# ACL lines that can never match after the changeprint(bf.q.filterLineReachability().answer(snapshot="candidate").frame())
# Traffic to 10.40.0.0/16 whose treatment changes between current and candidateheaders = HeaderConstraints(dstIps="10.40.0.0/16")print(bf.q.searchFilters(headers=headers).answer( snapshot="candidate", reference_snapshot="current").frame())Batfish’s question names and parameters change between releases; check them against the questions reference for the version you run. Ask the agent to show the code, so a person can see exactly what was tested.
Reading the result
- Parse issues on credential lines come from rConfig’s obfuscation and are safe to ignore. Parse issues anywhere else mean Batfish didn’t understand part of the config, and its answers about that part can’t be trusted.
- Unreachable ACL lines after a change usually mean a new broad permit or deny is shadowing lines below it.
- Differential results show flows whose permit or deny decision changes. That list should match the intent of the change request exactly; anything extra is a finding.
Limits to know
- Snapshot scope. Batfish only knows the devices in the snapshot. For reachability across a site, include every router and firewall on the path.
- Text edits approximate the device. The agent applies the change to the config file as text. Devices may reorder or rewrite lines when the change is really applied. Keep candidate changes small and specific.
- Stored, not live. rConfig’s configs are as of the last backup. Back the devices up first if they may have changed since.
- Large groups. Each
get_latest_configcall returns a whole config. For big snapshots, have the agent write files as it goes rather than hold everything in its context.
Related reference
- Connect an AI agent over MCP
- Config obfuscation
- Claude Code and Codex CLI for agents that run code
- Batfish documentation
Frequently asked questions
Where does Batfish get its configs from?
From a snapshot folder of device configuration files. rConfig already stores the current configuration of every device, so an agent can read them over MCP and write the snapshot in seconds instead of collecting configs by hand.
Do obfuscated secrets in rConfig's configs break Batfish?
They don't affect routing or ACL analysis. Batfish may report parse warnings on the obfuscated lines; check initIssues and ignore warnings that only concern credentials.
Does Batfish test the live network?
No. Batfish models the configurations you give it. It doesn't see live routing state from outside the snapshot, so include every device that matters to the question.
Can the agent push the change after Batfish passes?
Not through rConfig, whose MCP server is read-only. A passing Batfish run is evidence for the change request; the change itself goes through your normal process.