Using Claude to Automate Cisco NX-OS Configuration and Operations
NX-OS Automation with Claude
Cisco NX-OS powers the Nexus switching platform — the backbone of most enterprise data centers. Its configuration complexity, especially for VXLAN EVPN fabrics, makes it an ideal target for AI-assisted automation. Claude can generate correct, best-practice NX-OS configurations from plain descriptions, analyze complex show output, and power intelligent fabric management tooling.
This post covers practical automation patterns using the Claude API directly against NX-OS devices via NX-API REST and Netmiko.
Setup
import anthropic
import requests
import json
from netmiko import ConnectHandler
client = anthropic.Anthropic()
def ask_claude(prompt: str, system: str = None) -> str:
kwargs = {
"model": "claude-opus-4-5",
"max_tokens": 3000,
"messages": [{"role": "user", "content": prompt}]
}
if system:
kwargs["system"] = system
return client.messages.create(**kwargs).content[0].text
# NX-API helper
def nxapi_call(host: str, username: str, password: str, commands: list[str]) -> dict:
url = f"https://{host}/ins"
payload = {
"ins_api": {
"version": "1.0",
"type": "cli_show",
"chunk": "0",
"sid": "1",
"input": " ; ".join(commands),
"output_format": "json"
}
}
response = requests.post(
url, json=payload,
auth=(username, password),
verify=False,
timeout=30
)
return response.json()
Pattern 1: VXLAN EVPN Leaf Configuration Generator
Generating VXLAN BGP EVPN configuration is error-prone manually. Claude can produce complete, consistent leaf configs from a simple data structure:
def generate_vxlan_leaf_config(leaf_params: dict) -> str:
prompt = f"""
Generate a complete Cisco NX-OS VXLAN BGP EVPN leaf switch configuration for:
Leaf Parameters:
- Hostname: {leaf_params['hostname']}
- Loopback0 IP (Router-ID/VTEP source): {leaf_params['loopback0']}
- Loopback1 IP (Anycast VTEP): {leaf_params['loopback1']}
- BGP ASN: {leaf_params['bgp_asn']}
- Spine Route Reflectors: {leaf_params['spine_rrs']}
- Underlay Protocol: {leaf_params.get('underlay', 'ISIS')}
- Tenant VRFs: {leaf_params['vrfs']}
- Layer 2 VNIs (VNI: VLAN mapping): {leaf_params['l2_vnis']}
Include:
- Feature enables (nv overlay, bgp, interface-vlan, vn-segment-vlan-based, fabric forwarding)
- ISIS underlay config (or OSPF if specified)
- iBGP EVPN overlay with spine RRs as route-reflector-clients
- NVE interface with ingress-replication BGP
- Distributed anycast gateway with fabric forwarding anycast-gateway-mac
- VRF configs with L3 VNI and EVPN route-targets
- VLAN to VNI mappings
- SVI configs with anycast gateway
Output ONLY NX-OS CLI commands, no explanations.
"""
return ask_claude(
prompt,
system="You are a Cisco data center expert. Generate only correct NX-OS CLI configuration."
)
# Example usage
config = generate_vxlan_leaf_config({
"hostname": "leaf-01",
"loopback0": "10.0.0.1/32",
"loopback1": "10.1.0.1/32",
"bgp_asn": "65000",
"spine_rrs": ["10.0.0.101", "10.0.0.102"],
"underlay": "ISIS",
"vrfs": [
{"name": "TENANT-A", "l3_vni": 50001, "rd": "auto", "rt": "65000:50001"},
{"name": "TENANT-B", "l3_vni": 50002, "rd": "auto", "rt": "65000:50002"},
],
"l2_vnis": [
{"vni": 10010, "vlan": 10, "vrf": "TENANT-A"},
{"vni": 10020, "vlan": 20, "vrf": "TENANT-A"},
{"vni": 20010, "vlan": 30, "vrf": "TENANT-B"},
]
})
print(config)
Pattern 2: NX-OS Show Output Parser via NX-API
Pull structured JSON from NX-API and let Claude make sense of it:
def analyze_fabric_health(host: str, username: str, password: str) -> dict:
# Pull key fabric state via NX-API
commands = [
"show bgp l2vpn evpn summary",
"show nve peers",
"show nve vni",
"show interface nve1",
]
raw = nxapi_call(host, username, password, commands)
prompt = f"""
Analyze this NX-OS VXLAN EVPN fabric health data and return JSON with:
- overall_status: "healthy" | "degraded" | "critical"
- issues: list of specific problems found
- vtep_count: number of active VTEP peers
- vni_count: number of active VNIs
- bgp_neighbors_up: count of established BGP EVPN neighbors
- recommendations: list of actions to take
Raw NX-API data:
{json.dumps(raw, indent=2)}
Output ONLY valid JSON.
"""
return json.loads(ask_claude(prompt))
health = analyze_fabric_health("10.0.0.1", "admin", "password")
print(f"Fabric status: {health['overall_status']}")
for issue in health['issues']:
print(f" ⚠️ {issue}")
Pattern 3: VPC Configuration Generator and Validator
vPC misconfiguration is a common source of outages. Claude generates correct config and validates existing setups:
def generate_vpc_config(primary: dict, secondary: dict) -> tuple[str, str]:
prompt = f"""
Generate Cisco NX-OS vPC configuration for a vPC pair:
Primary Switch:
- Hostname: {primary['hostname']}
- Management IP: {primary['mgmt_ip']}
- vPC domain ID: {primary['vpc_domain']}
- Peer-link interfaces: {primary['peer_link_ports']}
- Keepalive source: {primary['keepalive_src']}
- Keepalive destination: {secondary['keepalive_src']}
- Role priority: 100 (primary wins)
Secondary Switch:
- Hostname: {secondary['hostname']}
- Role priority: 200
Return a JSON object with keys "primary_config" and "secondary_config",
each containing the complete NX-OS vPC configuration block.
Include: feature vpc, vpc domain, peer-link port-channel, keepalive,
peer-gateway, auto-recovery, delay restore timers, ip arp synchronize.
Output ONLY valid JSON.
"""
result = json.loads(ask_claude(prompt))
return result['primary_config'], result['secondary_config']
def validate_vpc_consistency(switch1_output: str, switch2_output: str) -> dict:
prompt = f"""
Compare these two NX-OS 'show vpc' outputs and identify any consistency issues.
Return JSON with:
- consistent: true/false
- mismatches: list of specific parameter mismatches
- risk_level: "low" | "medium" | "high"
- fix_commands: list of commands to resolve mismatches
Switch 1 output:
{switch1_output}
Switch 2 output:
{switch2_output}
Output ONLY valid JSON.
"""
return json.loads(ask_claude(prompt))
Pattern 4: Automated Change Window Assistant
Before a maintenance window, Claude helps build the runbook and validates readiness:
def pre_change_checklist(host: str, change_description: str, conn) -> dict:
# Gather current state
state_commands = {
"bgp_summary": "show bgp l2vpn evpn summary",
"vpc_status": "show vpc",
"interface_errors": "show interface counters errors | grep -v '0 0 0 0'",
"nve_peers": "show nve peers",
"spanning_tree": "show spanning-tree summary",
}
current_state = {}
for key, cmd in state_commands.items():
current_state[key] = conn.send_command(cmd)
prompt = f"""
Pre-change assessment for NX-OS switch {host}.
Planned change: {change_description}
Current device state:
{json.dumps(current_state, indent=2)}
Analyze and return JSON with:
- ready_for_change: true/false
- blockers: list of issues that must be resolved before proceeding
- warnings: list of non-blocking concerns
- baseline_snapshot: key metrics to verify after the change
- rollback_commands: NX-OS commands to revert the change
- estimated_impact: description of traffic impact during change
Output ONLY valid JSON.
"""
return json.loads(ask_claude(prompt))
device = {"device_type": "cisco_nxos", "host": "10.0.0.1", "username": "admin", "password": "pass"}
with ConnectHandler(**device) as conn:
assessment = pre_change_checklist(
"10.0.0.1",
"Upgrade VXLAN leaf from NX-OS 9.3.8 to 10.2.5",
conn
)
print(f"Ready: {assessment['ready_for_change']}")
for blocker in assessment['blockers']:
print(f" BLOCKER: {blocker}")
Pattern 5: NX-OS Upgrade Readiness Checker
def check_upgrade_readiness(host: str, target_version: str, conn) -> dict:
# Pull upgrade-relevant data
commands = {
"version": "show version",
"modules": "show module",
"fex": "show fex",
"features": "show feature | grep enabled",
"memory": "show system resources",
"boot_config": "show boot",
}
device_data = {}
for key, cmd in commands.items():
device_data[key] = conn.send_command(cmd)
prompt = f"""
Assess NX-OS upgrade readiness from current version to {target_version}.
Device data:
{json.dumps(device_data, indent=2)}
Return JSON with:
- upgrade_path: list of intermediate versions if direct upgrade not supported
- pre_upgrade_steps: ordered list of actions before upgrading
- compatibility_issues: list of features/modules with known issues in {target_version}
- estimated_downtime: string description
- post_upgrade_verification: list of commands to verify success
- rollback_procedure: steps to revert if upgrade fails
Output ONLY valid JSON.
"""
return json.loads(ask_claude(prompt))
Working with NX-OS Structured Output
NX-OS supports JSON output natively — combine this with Claude for maximum efficiency:
def get_mac_owner(host: str, mac_address: str, username: str, password: str) -> str:
"""Find which port a MAC address is learned on, with context"""
data = nxapi_call(host, username, password, [
f"show mac address-table address {mac_address}",
f"show ip arp | include {mac_address}"
])
prompt = f"""
A network engineer is trying to locate MAC address {mac_address}.
Based on this NX-OS data, provide a clear, one-paragraph explanation of:
- Where this MAC is learned (interface, VLAN, VNI if VXLAN)
- What IP address it maps to (if in ARP table)
- Whether it appears to be a local or remote VTEP endpoint
Data: {json.dumps(data, indent=2)}
"""
return ask_claude(prompt)