{"id":"fad0aa61-f335-413a-99d6-3e6d699baa37","entityType":"agent","slug":"clawhub-zw008-network-aiops","name":"network-aiops","canonicalUrl":"https://www.xpersona.co/agent/clawhub-zw008-network-aiops","canonicalPath":"/agent/clawhub-zw008-network-aiops","generatedAt":"2026-10-10T04:39:49.631Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:33:08.442Z","emptyReason":null},"description":"Use this skill whenever the user needs to operate a network device — read device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary and detail), ARP/MAC tables, VLANs, routes, hardware environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, and an aggregated device-health summary; run read-only RCA diagnostics on interface health and BGP neighbors; back up a switch/router config, diff a candidate config (dry-run), and merge/replace/rollback config — across Cisco IOS/IOS-XE, Nexus NX-OS, IOS-XR, Arista EOS, and Juniper Junos via NAPALM. An optional NetBox block adds source-of-truth lookups. Always use this skill for \"back up switch config\", \"show bgp neighbors\", \"diff network config\", \"push config to router\", \"show interfaces on the switch\", or tasks mentioning \"cisco\", \"arista\", \"juniper\", \"nexus\", \"ios-xr\", or \"napalm\". Do NOT use when the target is not a NAPALM-supported network device (Kubernetes clusters, hypervisor VMs, and cloud consoles are out of scope — route those elsewhere). Common multi-vendor device operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.9K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:network-aiops","sourceUrl":"https://clawhub.ai/zw008/network-aiops","homepage":"https://clawhub.ai/zw008/skills/network-aiops","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/zw008/network-aiops","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/zw008/skills/network-aiops","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":66,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"network-aiops technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:33:08.442Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:33:08.442Z","emptyReason":null},"stars":null,"forks":null,"downloads":1886,"packageName":null,"latestVersion":"0.12.3","tractionLabel":"1.9K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:33:08.441Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T23:33:08.442Z","lastCrawledAt":"2026-10-09T23:33:08.441Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T23:33:08.441Z","lastVerifiedAt":null,"highlights":[{"version":"0.12.3","createdAt":"2026-09-15T06:09:19.228Z","changelog":"- Removed the file: skill-card.md - No functional or code changes; this update is limited to file cleanup.","fileCount":7,"zipByteSize":25982},{"version":"0.12.2","createdAt":"2026-09-12T14:32:53.043Z","changelog":"network-aiops v0.12.2 - Documentation updated: SKILL.md revised with updated plugin install/example for OpenClaw. - Obsolete file removed: skill-card.md deleted.","fileCount":7,"zipByteSize":25854},{"version":"0.12.1","createdAt":"2026-09-12T10:16:40.210Z","changelog":"- Added OpenClaw plugin install instructions and integration notes to SKILL.md. - Updated quick install section to reflect OpenClaw usage and MCP server requirements. - No core functionality or CLI/API changes; documentation improvement only. - Removed obsolete skill-card.md file.","fileCount":7,"zipByteSize":25880},{"version":"0.12.0","createdAt":"2026-09-12T01:05:29.278Z","changelog":"network-aiops 0.12.0 - Updated requirements: now allows either the \"network-aiops\" or \"uvx\" binary for installation and operation. - Improved metadata to support more flexible runtime and installer environments. - Removed the skill-card.md file for a leaner package. - No breaking changes to core functionality or user-facing operations.","fileCount":7,"zipByteSize":25890},{"version":"0.11.0","createdAt":"2026-08-10T06:52:40.222Z","changelog":"- Removed the skill-card.md file to clean up redundant documentation. - No functionality or interface changes; this is a documentation cleanup release.","fileCount":7,"zipByteSize":25732},{"version":"0.10.0","createdAt":"2026-08-03T05:53:53.686Z","changelog":"- Removed the sample documentation file skill-card.md. - No changes to functionality or core features. - Documentation and usage details remain in SKILL.md only.","fileCount":7,"zipByteSize":25868},{"version":"0.9.0","createdAt":"2026-08-02T09:40:37.719Z","changelog":"- The skill-card.md file was removed. - No user-facing features or tools were added or changed in this release. - Documentation and feature list remain unchanged for end users.","fileCount":7,"zipByteSize":25845},{"version":"0.8.0","createdAt":"2026-07-21T15:31:12.610Z","changelog":"- Removed the sample file skill-card.md. - No changes to functionality, configuration, or user experience. - Documentation and package details remain unchanged.","fileCount":7,"zipByteSize":25876}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:network-aiops","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:network-aiops` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/zw008/network-aiops before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T04:39:49.627Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-network-aiops/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:33:08.442Z","emptyReason":null},"readme":"Skill: network-aiops\n\nOwner: zw008\n\nSummary: Use this skill whenever the user needs to operate a network device — read device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary and detail), ARP/MAC tables, VLANs, routes, hardware environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, and an aggregated device-health summary; run read-only RCA diagnostics on interface health and BGP neighbors; back up a switch/router config, diff a candidate config (dry-run), and merge/replace/rollback config — across Cisco IOS/IOS-XE, Nexus NX-OS, IOS-XR, Arista EOS, and Juniper Junos via NAPALM. An optional NetBox block adds source-of-truth lookups. Always use this skill for \"back up switch config\", \"show bgp neighbors\", \"diff network config\", \"push config to router\", \"show interfaces on the switch\", or tasks mentioning \"cisco\", \"arista\", \"juniper\", \"nexus\", \"ios-xr\", or \"napalm\". Do NOT use when the target is not a NAPALM-supported network device (Kubernetes clusters, hypervisor VMs, and cloud consoles are out of scope — route those elsewhere). Common multi-vendor device operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\n\nTags: latest:0.12.3\n\nVersion history:\n\nv0.12.3 | 2026-09-15T06:09:19.228Z | auto\n\n- Removed the file: skill-card.md\n- No functional or code changes; this update is limited to file cleanup.\n\nv0.12.2 | 2026-09-12T14:32:53.043Z | auto\n\nnetwork-aiops v0.12.2\n\n- Documentation updated: SKILL.md revised with updated plugin install/example for OpenClaw.\n- Obsolete file removed: skill-card.md deleted.\n\nv0.12.1 | 2026-09-12T10:16:40.210Z | auto\n\n- Added OpenClaw plugin install instructions and integration notes to SKILL.md.\n- Updated quick install section to reflect OpenClaw usage and MCP server requirements.\n- No core functionality or CLI/API changes; documentation improvement only.\n- Removed obsolete skill-card.md file.\n\nv0.12.0 | 2026-09-12T01:05:29.278Z | auto\n\nnetwork-aiops 0.12.0\n\n- Updated requirements: now allows either the \"network-aiops\" or \"uvx\" binary for installation and operation.\n- Improved metadata to support more flexible runtime and installer environments.\n- Removed the skill-card.md file for a leaner package.\n- No breaking changes to core functionality or user-facing operations.\n\nv0.11.0 | 2026-08-10T06:52:40.222Z | auto\n\n- Removed the skill-card.md file to clean up redundant documentation.\n- No functionality or interface changes; this is a documentation cleanup release.\n\nv0.10.0 | 2026-08-03T05:53:53.686Z | auto\n\n- Removed the sample documentation file skill-card.md.\n- No changes to functionality or core features.\n- Documentation and usage details remain in SKILL.md only.\n\nv0.9.0 | 2026-08-02T09:40:37.719Z | auto\n\n- The skill-card.md file was removed.\n- No user-facing features or tools were added or changed in this release.\n- Documentation and feature list remain unchanged for end users.\n\nv0.8.0 | 2026-07-21T15:31:12.610Z | auto\n\n- Removed the sample file skill-card.md.\n- No changes to functionality, configuration, or user experience.\n- Documentation and package details remain unchanged.\n\nv0.7.0 | 2026-07-21T09:42:05.167Z | auto\n\nnetwork-aiops v0.7.0\n\n- Governance harness docs and references updated for clarity and risk-tier labeling.\n- Governance description revised to highlight risk-tier tagging and budget guard details.\n- Removed obsolete skill-card.md file.\n- Documentation edits across all guides for consistency.\n- No breaking changes to core functionality.\n\nv0.6.0 | 2026-07-20T11:16:23.226Z | auto\n\nnetwork-aiops 0.6.0\n\n- Increased total tools from 32 to 33 MCP tools.\n- Documentation updates in SKILL.md and reference files to reflect the new tool count and recent changes.\n- Removed the obsolete skill-card.md file.\n- Improved and clarified coverage details and usage guidance in reference docs.\n- No changes to installer requirements or compatibility.\n\nv0.5.0 | 2026-07-19T03:52:23.549Z | auto\n\nnetwork-aiops 0.5.0\n\n- Added two new read-only RCA diagnostics: interface_health_rca and bgp_neighbor_rca for root-cause analysis of interface and BGP neighbor health issues.\n- Introduced undo support: tools for listing and applying undo actions (undo_list, undo_apply).\n- Increased total MCP tool coverage from 28 to 32.\n- Documentation improvements: reworked SKILL.md for clarity, added references/agent-guardrails.md, and removed outdated skill-card.md.\n- Minor metadata and tag updates for clarity and discoverability.\n\nv0.4.0 | 2026-07-17T05:54:25.229Z | auto\n\nnetwork-aiops 0.4.0\n\n- Removed the sample file skill-card.md from the project.\n- No user-facing functionality changes.\n\nv0.3.0 | 2026-07-13T13:07:52.614Z | auto\n\nnetwork-aiops 0.3.0\n\n- Updated documentation in SKILL.md for clarity and detailed usage instructions.\n- No changes to source code or functionality.\n- Improves guidance on supported devices, when to use the skill, and security handling.\n- Helps users better understand device, platform, and security support.\n\nv0.2.0 | 2026-06-27T02:23:28.645Z | auto\n\n**network-aiops 0.2.0**\n\n- Adds an encrypted secrets manager (Fernet/AES + scrypt) for device passwords and NetBox tokens; secrets are no longer stored in plaintext (.env).\n- Greatly expands supported read operations: now 28 tools including interface counters, MAC table, VLANs, route lookup, hardware environment/optics, NTP, SNMP info, VRFs, and device-health summary.\n- New CLI subcommands: `init` for interactive setup, `secret set`, and `secret migrate` for secret management.\n- Improved documentation and setup guidance.\n- Removes deprecated plaintext .env storage (still reads for fallback, but use of secrets.enc is strongly recommended).\n\nv0.1.0 | 2026-06-22T08:18:39.495Z | user\n\nv0.1.0 first release: standalone governed multi-vendor network ops (NAPALM) — 13 MCP tools with audit/budget/undo/risk-tier harness\n\nArchive index:\n\nArchive v0.12.3: 7 files, 25982 bytes\n\nFiles: references/agent-guardrails.md (11690b), references/capabilities.md (10561b), references/cli-reference.md (4989b), references/setup-guide.md (5363b), skill-card.md (2864b), SKILL.md (24455b), _meta.json (133b)\n\nFile v0.12.3:SKILL.md\n\n---\nname: network-aiops\nslug: network-aiops\ndisplayName: \"Network AIops\"\nsummary: \"Governed network device ops (NAPALM) — 33 MCP tools with audit/undo.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Network-AIops\ntags: [aiops, mcp, governance, network]\ndescription: >\n  Use this skill whenever the user needs to operate a network device — read device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary and detail), ARP/MAC tables, VLANs, routes, hardware environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, and an aggregated device-health summary; run read-only RCA diagnostics on interface health and BGP neighbors; back up a switch/router config, diff a candidate config (dry-run), and merge/replace/rollback config — across Cisco IOS/IOS-XE, Nexus NX-OS, IOS-XR, Arista EOS, and Juniper Junos via NAPALM. An optional NetBox block adds source-of-truth lookups.\n  Always use this skill for \"back up switch config\", \"show bgp neighbors\", \"diff network config\", \"push config to router\", \"show interfaces on the switch\", or tasks mentioning \"cisco\", \"arista\", \"juniper\", \"nexus\", \"ios-xr\", or \"napalm\".\n  Do NOT use when the target is not a NAPALM-supported network device (Kubernetes clusters, hypervisor VMs, and cloud consoles are out of scope — route those elsewhere).\n  Common multi-vendor device operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\ninstaller:\n  kind: uv\n  package: network-aiops\nargument-hint: \"[device name or describe your network task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"network-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"NETWORK_AIOPS_CONFIG\",\"NETWORK_AIOPS_HOME\",\"NETWORK_AIOPS_MASTER_PASSWORD\",\"NETWORK_NETBOX_TOKEN\"]},\"homepage\":\"https://github.com/AIops-tools/Network-AIops\",\"emoji\":\"🛜\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed network device operations over NAPALM. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency.\n  All write operations are audited to a local SQLite DB under ~/.network-aiops/ (relocatable via NETWORK_AIOPS_HOME).\n  Credentials: device login passwords AND the optional NetBox API token live in an ENCRYPTED store at ~/.network-aiops/secrets.enc (Fernet/AES + scrypt-derived key; chmod 600), never in plaintext. Device passwords are keyed by the device name; the NetBox token uses the reserved name \"netbox-token\". Unlock with the NETWORK_AIOPS_MASTER_PASSWORD env var (for the MCP server / non-interactive use) or an interactive prompt. Run `network-aiops init` (wizard) or `network-aiops secret set <name>` to populate it, and `network-aiops secret migrate` to import a legacy plaintext .env (NETWORK_<TARGET_UPPER>_PASSWORD / NETWORK_NETBOX_TOKEN are still honoured as a deprecated fallback). config.yaml holds only device names, drivers, hosts, usernames, and NAPALM optional_args — never secrets. The state dir ~/.network-aiops should be chmod 700.\n  Destructive operations (config merge, config replace, config rollback) require double confirmation at the CLI layer and support --dry-run (which prints the diff without committing). All write tools pass through the @governed_tool decorator (budget guard + audit + risk-tier tagging). config_merge and config_replace capture the pre-change running config and record an inverse config_replace-to-backup undo descriptor; config_rollback records none, and config_replace is risk_level=high.\n  Webhooks: none — no outbound network calls beyond the configured device sessions and the optional NetBox API.\n  TLS: NAPALM driver transports (eAPI/NX-API HTTPS, NETCONF/SSH) follow the device's own certificate/SSH host-key settings; the skill does not weaken them.\n  Transitive dependencies: napalm (device drivers), pynetbox (optional source-of-truth), typer/rich (CLI), pyyaml/python-dotenv (config), and the MCP SDK. No post-install scripts or background services.\n---\n\n# Network AIops\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox Labs, or any network vendor.** Vendor and product names are trademarks of their respective owners. Source code is publicly auditable at [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops) under the MIT license.\n\nGoverned multi-vendor network device operations — **33 MCP tools**, every one wrapped with the bundled `@governed_tool` harness: a local unified audit log under `~/.network-aiops/`, token/runaway budget guard, undo-token recording, and descriptive risk-tier labels. Devices are reached over NAPALM; an optional NetBox block adds source-of-truth lookups. Secrets (device passwords + NetBox token) are kept in an **encrypted store** (`secrets.enc`), unlocked by `NETWORK_AIOPS_MASTER_PASSWORD`.\n\n> **Standalone**: the governance harness is bundled in the package (`network_aiops.governance`) — network-aiops has no external skill-family dependency. Coverage focuses on common operations and is not yet exhaustive.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read or Write |\n|----------|-------|:-----:|:-------------:|\n| **Device facts** | facts, interfaces, interface counters, interface IPs, BGP (+detail), LLDP (+detail), ARP | 9 | 9 read |\n| **Inventory** | MAC table, VLANs, route lookup | 3 | 3 read |\n| **Platform / env** | environment, optics, NTP servers, NTP stats, users, SNMP info, VRFs, device_health | 8 | 8 read |\n| **Diagnostics / RCA** | interface_health_rca, bgp_neighbor_rca | 2 | 2 read |\n| **Config** | backup, diff (dry-run), merge, replace, rollback | 5 | 2 read / 3 write |\n| **NetBox** | list devices, get device, device interfaces | 3 | 3 read |\n| **Undo** | undo_list, undo_apply | 2 | 1 read / 1 write |\n\n## Quick Install\n\n```bash\nuv tool install network-aiops\nnetwork-aiops init            # interactive wizard: device + driver + host + encrypted password (+ optional NetBox)\nnetwork-aiops doctor          # checks config, encrypted secret store, and per-device password presence\n```\n\nOr as an OpenClaw plugin, which installs this skill and its MCP server together:\n\n```bash\nopenclaw plugins install clawhub:@zw008/network-aiops\nopenclaw skills info network-aiops          # expect: Visible to model: yes\n```\n\nNeeds `uvx` on `PATH`: the MCP server is fetched with uv, pinned to this release.\n\n`init` writes `~/.network-aiops/config.yaml` and stores secrets **encrypted** in `~/.network-aiops/secrets.enc`. Export `NETWORK_AIOPS_MASTER_PASSWORD` in your shell profile so the CLI and MCP server can unlock secrets non-interactively.\n\n## Supported Devices\n\n| Platform | NAPALM driver | Transport |\n|----------|---------------|-----------|\n| Cisco IOS / IOS-XE | `ios` | SSH |\n| Cisco Nexus NX-OS | `nxos` (NX-API) / `nxos_ssh` (SSH) | HTTPS / SSH |\n| Cisco IOS-XR | `iosxr` | SSH (XML agent) |\n| Arista EOS | `eos` | eAPI (HTTPS) |\n| Juniper Junos | `junos` | NETCONF (SSH) |\n\nOther platforms (Nokia SR OS / SR Linux, Huawei VRP, etc.) are reachable via NAPALM **community drivers** but are **not officially tested here** — see [Contributing](#contributing--request-a-device-or-feature).\n\n## When to Use This Skill\n\n- Inspect device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary + detail), ARP/MAC tables, VLANs, and route lookups\n- Check hardware health: environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, or a one-shot `device_health` summary\n- Root-cause a problem with read-only RCA: `interface_health_rca` (down/erroring/discarding/flapping ports) and `bgp_neighbor_rca` (down/shut/recently-reset/route-less peers) — each finding cites the measured number that tripped it, worst-first\n- Back up a switch/router running config to a file\n- Dry-run a config change as a diff before committing\n- Merge a config snippet, replace the full config, or roll back the last commit\n- Cross-check intended state in NetBox before pushing a change\n\n**Do NOT use when** the target is not a NAPALM-supported network device (Kubernetes clusters, hypervisor VMs, and cloud-provider consoles are out of scope for this skill).\n\n## Related Skills — Skill Routing\n\n| If the user wants… | Use |\n|--------------------|-----|\n| Network device config / facts (Cisco/Arista/Juniper) | **network-aiops** (this skill) |\n| Kubernetes cluster operations | a cluster ops skill |\n| Hypervisor VM lifecycle (power, snapshot, migrate) | a hypervisor ops skill |\n\n## Supported Actions\n\n| Tool | R/W | Risk | Driver support |\n|------|:---:|:----:|----------------|\n| `device_facts` | R | low | all 5 |\n| `get_interfaces` | R | low | all 5 |\n| `get_interfaces_counters` | R | low | all 5 |\n| `get_interfaces_ip` | R | low | all 5 |\n| `get_bgp_neighbors` | R | low | all 5 (varies by feature) |\n| `get_bgp_neighbors_detail` | R | low | ios/eos/junos/iosxr; nxos varies |\n| `get_lldp_neighbors` | R | low | all 5 |\n| `get_lldp_neighbors_detail` | R | low | all 5 |\n| `get_arp_table` | R | low | all 5 |\n| `get_mac_address_table` | R | low | all 5 (varies by image) |\n| `get_vlans` | R | low | eos/junos/nxos; ios varies |\n| `get_route_to` | R | low | all 5 (varies by feature) |\n| `get_environment` | R | low | all 5 (sensor coverage varies) |\n| `get_optics` | R | low | eos/junos/iosxr; ios/nxos varies |\n| `get_ntp_servers` | R | low | all 5 |\n| `get_ntp_stats` | R | low | all 5 |\n| `get_users` | R | low | all 5 (password hashes redacted) |\n| `get_snmp_information` | R | low | all 5 (community strings redacted) |\n| `get_network_instances` | R | low | eos/junos/iosxr; ios/nxos varies |\n| `device_health` | R | low | all 5 (environment section optional) |\n| `interface_health_rca` | R | low | all 5 (needs get_interfaces + counters) |\n| `bgp_neighbor_rca` | R | low | all 5 (varies by BGP feature) |\n| `config_backup` | R | low | all 5 |\n| `config_diff` (dry-run) | R | low | all 5 |\n| `config_merge` | W | medium | all 5 |\n| `config_replace` | W | **high** | ios/eos/junos/iosxr; nxos varies |\n| `config_rollback` | W | medium | device-dependent rollback depth |\n| `netbox_list_devices` | R | low | NetBox (optional) |\n| `netbox_get_device` | R | low | NetBox (optional) |\n| `netbox_device_interfaces` | R | low | NetBox (optional) |\n\n**Per-driver caveat**: NAPALM does not implement every getter on every platform. Any unsupported getter returns a teaching error (\"not supported by the `<driver>` driver\") instead of crashing — try a different getter or fall back to `config_backup`. `device_health` is resilient: if a driver lacks `get_environment` that section is reported as a note, not a failure.\n\n**Credentials**: `get_users` reduces password hashes to a boolean and `get_snmp_information` reduces community strings to a count — those two never return secrets at all. `config_backup` and every returned `diff` *mask* credential values (password/secret hashes, SNMP communities, pre-shared keys, RADIUS/TACACS and keychain keys) and report how many lines they changed in a `redaction` block; `include_secrets=True` returns the verbatim text. The masking is pattern-based across five vendor syntaxes, so it reduces exposure rather than guaranteeing none remains — notably it cannot see multi-line PKI key blocks. To hand a real config to a human, prefer the CLI's `-o <path>`, which writes raw to a file instead of into this transcript.\n\n## Common Workflows\n\n### Safely change a device config with a dry-run first\n\n1. `network-aiops config backup -t core-sw1 -o core-sw1.cfg` → keep a known-good copy\n2. `network-aiops config diff change.cfg -t core-sw1` → preview the diff (nothing committed)\n3. `network-aiops config merge change.cfg -t core-sw1` (double confirm) → commits **under a 300s device-side revert timer**; the harness also records a `config_replace`-to-backup undo descriptor\n4. `network-aiops device interfaces -t core-sw1` → verify the result **and that you can still reach the device**\n5. `network-aiops config confirm -t core-sw1` → cancels the revert timer, making the change permanent. If you skip this (or get locked out), the device reverts by itself — that is the point\n6. **Failure branch**: if the connection fails (`Could not connect/authenticate`), run `network-aiops doctor` — it shows whether `NETWORK_CORE_SW1_PASSWORD` is set and whether the host/port is reachable; the skill never retries a denied auth.\n\n### Change something that could lock you out (mgmt interface, VTY ACL, AAA)\n\n1. `network-aiops config backup -t core-sw1 -o core-sw1.cfg` → an off-box copy, independent of the tool\n2. `network-aiops config diff risky.cfg -t core-sw1` → confirm the diff touches only what you intend\n3. `network-aiops config merge risky.cfg -t core-sw1 --revert-in 120` → short timer: if the change severs your session, the device restores itself in 2 minutes with nobody logged in\n4. Re-connect and verify. **Do not confirm from a session opened before the commit** — it may survive a change that blocks *new* logins\n5. `network-aiops config confirm -t core-sw1` → only once a NEW session proves the path still works\n6. **Failure branch**: if the result carries `commit.warning` with `safetyNet: \"undo-only\"`, this driver could not arm a timer. The change is permanent on landing and the recorded undo needs a working session — arrange out-of-band access (console/OOB mgmt) before you commit anything of this kind.\n\n### Root-cause a flaky uplink / peering problem (RCA-first)\n\n1. `network-aiops diagnose interface-health -t edge-rtr` → worst-first interface findings; a link that is admin-up/oper-down with climbing `rx_errors+tx_errors` and a recent `last_flapped` is a physical-layer fault (cable/optic), each cited with its measured value\n2. `network-aiops diagnose bgp -t edge-rtr` → worst-first neighbor findings; if the peer riding that link shows `BGP session down` or `recently reset` (low uptime), the L1 fault — not routing — is resetting the session\n3. `network-aiops device counters -t edge-rtr` → confirm the error counters are still climbing before you touch anything\n4. `network-aiops config diff fix.cfg -t edge-rtr` → dry-run the remediation first, then `config merge` (double confirm) through the audited path\n5. **Failure branch**: if `interface_health_rca` / `bgp_neighbor_rca` returns \"not supported by the `<driver>` driver\", the platform's NAPALM driver lacks the underlying getter — fall back to `device facts` / `config_backup` and request the getter via a GitHub issue.\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models | **CLI** | fewer tokens than MCP |\n| Cloud models (Claude, GPT) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | type-safe parameters, audited |\n\n## MCP Tools (33 — 28 read, 5 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Facts | `device_facts`, `get_interfaces`, `get_interfaces_counters`, `get_interfaces_ip`, `get_bgp_neighbors`, `get_bgp_neighbors_detail`, `get_lldp_neighbors`, `get_lldp_neighbors_detail`, `get_arp_table` | Read |\n| Inventory | `get_mac_address_table`, `get_vlans`, `get_route_to` | Read |\n| Platform / env | `get_environment`, `get_optics`, `get_ntp_servers`, `get_ntp_stats`, `get_users`, `get_snmp_information`, `get_network_instances`, `device_health` | Read |\n| Diagnostics / RCA | `interface_health_rca`, `bgp_neighbor_rca` | Read |\n| Config | `config_backup`, `config_diff` | Read |\n| | `config_merge`, `config_replace`, `confirm_commit`, `config_rollback` | Write |\n| NetBox | `netbox_list_devices`, `netbox_get_device`, `netbox_device_interfaces` | Read |\n| Undo | `undo_list` | Read |\n| | `undo_apply` | Write |\n\n**Commit-confirm is the primary safety net.** `config_merge` and `config_replace` commit with a device-side revert timer (`revert_in`, default 300s): the device rolls the change back on its own unless `confirm_commit` follows. This is the only guard that survives the change severing your own management path — a commit that shuts the management interface, tightens the VTY ACL or breaks AAA also kills the session the recorded undo would need, so the *device* has to be the one enforcing the rollback. Workflow: **commit with timer → verify you can still reach the device → `confirm_commit`** (or do nothing and let it revert). Drivers that cannot arm a timer fall back to a plain commit and say so in `commit.warning` / `commit.safetyNet` — check that field, because for those devices the net is absent.\n\n**Harness features that light up**: `config_merge` and `config_replace` capture the pre-change running config and pass an `undo=` lambda so the harness records an inverse descriptor (with `_undo_id`) that restores the captured config via `config_replace` — the device must support config replace for the undo to apply. The raw config is handed to the harness out-of-band and kept only in `undo.db` (0600); the tool result returns a **digest** (size + SHA-256), never the config body, because a running config carries credential hashes, SNMP communities and PSKs that would otherwise land in the agent transcript. `config_rollback` declares no undo; `config_replace` is tagged `risk_level=high`. `config_diff` is a pure dry-run (stage candidate → compare → discard). The two RCA tools (`interface_health_rca`, `bgp_neighbor_rca`) are pure read-only analyses (`risk_level=low`) that collect getter output and rank findings worst-first. All 33 tools are audit-logged under `~/.network-aiops/` and pass through the budget/runaway guard, with a descriptive risk tier tagged on each audit row. Avoid tight poll loops — the runaway breaker backs this up.\n\n## Encrypted secret store\n\nSecrets never touch disk in plaintext. They live in `~/.network-aiops/secrets.enc` (Fernet/AES-128 + HMAC, key derived from a master password via scrypt; file chmod 600). Both kinds of secret share the one store: per-device login passwords keyed by device name, and the single NetBox API token keyed by the reserved name `netbox-token`.\n\n```bash\nnetwork-aiops init                       # wizard: collects devices + passwords (encrypted), optional NetBox\nnetwork-aiops secret set core-sw1        # store/replace a device password (hidden prompt)\nnetwork-aiops secret set netbox-token    # store the NetBox API token\nnetwork-aiops secret list                # names only — values are NEVER printed\nnetwork-aiops secret rm core-sw1\nnetwork-aiops secret migrate             # import a legacy plaintext .env (renamed to .env.migrated)\nnetwork-aiops secret rotate-password     # re-encrypt the whole store under a new master password\n```\n\nUnlock non-interactively by exporting `NETWORK_AIOPS_MASTER_PASSWORD` (used by the MCP server / cron / CI). Legacy plaintext env vars (`NETWORK_<TARGET_UPPER>_PASSWORD`, `NETWORK_NETBOX_TOKEN`) are still honoured as a deprecated fallback with a warning. An empty device password is allowed (valid for key-based SSH auth via `optional_args`).\n\n## CLI Quick Reference\n\n```bash\nnetwork-aiops init                                               # onboarding wizard (encrypted secrets)\nnetwork-aiops device facts [-t <device>]\nnetwork-aiops device interfaces [-t <device>]\nnetwork-aiops device counters [-t <device>]\nnetwork-aiops device bgp [-t <device>]\nnetwork-aiops device lldp [-t <device>]\nnetwork-aiops device arp [-t <device>]\nnetwork-aiops device mac [-t <device>]\nnetwork-aiops device vlans [-t <device>]\nnetwork-aiops device route <prefix> [-t <device>] [--protocol bgp]\nnetwork-aiops device environment [-t <device>]\nnetwork-aiops device health [-t <device>]\nnetwork-aiops diagnose interface-health [-t <device>]           # interface RCA (worst-first)\nnetwork-aiops diagnose bgp [-t <device>]                        # BGP-neighbor RCA (worst-first)\nnetwork-aiops config backup [-t <device>] [-o <file>]\nnetwork-aiops config diff <file> [-t <device>] [--replace]\nnetwork-aiops config merge <file> [-t <device>] [--dry-run]      # double confirm\nnetwork-aiops config replace <file> [-t <device>] [--dry-run]    # HIGH RISK\nnetwork-aiops config rollback [-t <device>] [--dry-run]          # double confirm\nnetwork-aiops netbox list [--name <q>] [--limit N]\nnetwork-aiops netbox get <name>\nnetwork-aiops netbox interfaces <device> [--limit N]\nnetwork-aiops secret set|list|rm|migrate|rotate-password\nnetwork-aiops doctor\nnetwork-aiops mcp                                                # start MCP server (stdio)\n```\n\nSee `references/cli-reference.md` for the full command list.\n\n## Troubleshooting\n\n### \"Could not connect/authenticate to '<device>'\"\nThe host/port, username, or password is wrong, or the device is unreachable. Run `network-aiops doctor` — it reports whether the encrypted secret store is present, whether a password is stored for the device, and whether the device answers. Store/replace the password with `network-aiops secret set <device>` (or re-run `network-aiops init`). For enable/secret, set it in `optional_args.secret`.\n\n### \"Master password not set\" / cannot unlock secrets\nThe encrypted store needs the master password. Export `NETWORK_AIOPS_MASTER_PASSWORD` for non-interactive use (MCP server / cron), or run a CLI command on a TTY to be prompted. If you forgot it, delete `~/.network-aiops/secrets.enc` and re-run `network-aiops init`.\n\n### \"Operation not supported by the '<driver>' NAPALM driver\"\nThat getter or config mode is not implemented for this platform. Try a different getter, or fall back to `config_backup` and inspect the relevant stanza. Request the capability via a GitHub issue/PR.\n\n### \"Driver '<x>' is not in the officially supported set\"\nOnly `ios`, `nxos`, `nxos_ssh`, `iosxr`, `eos`, `junos` are tested here. Community drivers may work but are untested — request official support via a GitHub issue/PR.\n\n### NetBox commands fail with \"NetBox is not configured\"\nAdd a `netbox: {url: ...}` block to `config.yaml` and store the API token encrypted with `network-aiops secret set netbox-token` (or run `network-aiops init`). NetBox tools degrade gracefully when unconfigured.\n\n### `config replace` failed mid-commit\nThe device may not support full config replace (some Nexus images do not). Use `config merge` for additive changes, or restore from your `config backup` file.\n\n## Audit & Safety\n\nThe skill delivers reads and writes and records them; it does **not** decide whether a write is permitted. That is your agent's judgement, or the permission of the account you connect it with (log in with a device account at a read-only privilege level, and give NetBox a read-only API token — writes then fail at the server). There is no read-only switch, policy file, or approval gate.\n\n- **Audit is the guarantee, and it is not bypassable.** Every operation — MCP and CLI alike — is logged to `~/.network-aiops/audit.db` (relocatable via `NETWORK_AIOPS_HOME`): params, result, status, duration, and the risk tier. The CLI writes the same row the MCP path does.\n- `NETWORK_AUDIT_APPROVED_BY` / `NETWORK_AUDIT_RATIONALE` are optional annotations recorded on the audit row (who/why); they are never required and never block.\n- **Runaway guard** — a safety backstop, not authorization: the same call looped in a tight window trips a circuit breaker. Disable with `NETWORK_RUNAWAY_MAX=0`.\n- Undo store records inverse descriptors for reversible writes (config merge/replace → restore captured running config).\n- Writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI.\n\nThe harness is bundled in the package — no external dependency, no manual setup. See `references/setup-guide.md` for security details.\n\nDriving these tools with a smaller / local model? See `references/agent-guardrails.md` — which guardrails the harness now enforces for you, a ready-to-paste system prompt, and the network-specific traps (config merge vs replace, per-vendor interface naming, NetBox intent vs live device state).\n\n## Contributing — request a device or feature\n\nCoverage is intentionally focused. **Need a device (Nokia SR OS, Huawei VRP, …) or an action that isn't here yet?** Open an issue or pull request at [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops/issues) — feature requests, contributions, and comments are all welcome.\n\n## License\n\nMIT — [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)\n\nFile v0.12.3:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"network-aiops\",\n  \"version\": \"0.12.3\",\n  \"publishedAt\": 1789452559228\n}\n\nFile v0.12.3:references/agent-guardrails.md\n\n# Agent guardrails — running network-aiops with a smaller / local model\n\nIf you drive these tools with a local model (Llama, Qwen, Mistral … via Goose,\nOllama, LM Studio, or any OpenAI-compatible runtime), you will get noticeably\nbetter results with a short system prompt. This page gives you one, and — more\nimportantly — tells you which guardrails you **no longer need to write**, because\nthe tool now enforces them itself.\n\nThe distinction matters. A guardrail in a prompt is a request. A guardrail in the\nharness is a guarantee. Anything below that we could move into the harness, we did.\n\nNetwork gear raises the stakes: a bad merge on a core switch takes the management\nplane with it, and the model cannot SSH back in to fix what it broke.\n\n## What the tool now enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Don't invent a value when a field is missing\" | A field the driver did not return comes back as `null`, never as `\"\"`. This is the norm, not the exception, on a multi-vendor fleet: `serial_number`, `model`, an interface `description`, an LLDP neighbour's `hostname` are all optional and driver-dependent. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | The NetBox listings return `{\"devices\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}` (and `{\"interfaces\": ...}` likewise). Truncation is measured — one extra record is fetched — not guessed from a length coincidence. |\n| \"Preserve the ordering / tell me what's most urgent\" | `interface_health_rca` and `bgp_neighbor_rca` findings carry an explicit 1-based `rank`, worst-first, and each cites the measured number that tripped it (`rx_errors+tx_errors = 412 >= 100`). Priority is in the payload, not implied by list position. |\n| \"Show me the diff before you commit anything\" | `config_diff` is a real dry run: it stages a candidate, returns `compare_config()` output, then always discards. Nothing is committed, and the response carries `\"committed\": false`. |\n| \"Confirm before anything destructive\" | The CLI write paths (`config merge`/`replace`/`rollback`) require a double confirmation, and every write supports `--dry-run` / `dry_run=True` to preview first. `config_replace` is `high` risk, carried into the audit row as a `review` tier so it stands out in the trail. |\n| \"Keep a copy of the old config so we can go back\" | `config_merge` and `config_replace` read the running config **before** touching the device and return it as `backup`, and the harness records an undo descriptor that restores it via `config_replace`. The before-state is captured, not reconstructed. |\n| \"Log what you did\" | Every governed call is audited to `~/.network-aiops/audit.db` regardless of what the model says it did. |\n| \"Never show me passwords or SNMP communities\" | `get_users` returns `has_password` (a boolean) instead of the hash; `get_snmp_information` returns `community_count` instead of the community strings. The secrets are not in the payload to leak. |\n| \"Don't crash if this platform doesn't support that command\" | A getter a driver does not implement returns a teaching error naming the driver (\"not supported by the `iosxr` NAPALM driver\"), not a traceback. |\n\n## What still needs a prompt\n\nThese are model-behaviour problems the harness cannot fix from the outside.\nCopy this into your agent's system prompt:\n\n```text\nYou operate multi-vendor network devices (Cisco IOS / NX-OS / IOS-XR, Arista EOS,\nJuniper Junos) and an optional NetBox source of truth through the network-aiops\nMCP tools.\n\nTOOL USE\n- Before answering any question about the current state of the network, you MUST\n  call a tool. Never answer from memory or assumption.\n- Actually invoke the tool. Do not describe the call you would make, and do not\n  emit an example JSON response in place of calling it.\n- If a tool call fails, report the real error verbatim. Never fill the gap with\n  a plausible-sounding answer. \"Not supported by the <driver> driver\" means the\n  platform lacks that getter — say so; do not substitute a different getter and\n  present its output as the answer to the original question.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result contains a \"truncated\"\n  field that is true, say so and re-run with a higher limit instead of treating\n  the partial result as complete.\n- A null field means the driver did not return that value. Report it as \"not\n  available\" — never infer it.\n- Report identifiers EXACTLY as returned. Interface naming is vendor-specific:\n  GigabitEthernet0/1, Ethernet1, ge-0/0/0 and Te0/0/0/1 are literal device\n  strings, not styles to normalise. Never abbreviate Gi0/1 to 0/1, never expand\n  Et1 to Ethernet1, never convert between vendors' forms.\n- Do not normalise, translate, or prettify VRF names, BGP connection states,\n  route protocols, or VLAN names either.\n- When an RCA result has findings, work in \"rank\" order and cite the measured\n  number in each finding's \"detail\".\n\nCONFIG CHANGES\n- Always call config_diff first and show the operator the diff. Only after they\n  approve the exact diff may you call config_merge or config_replace.\n- config_merge is additive: it adds and modifies lines, it does not remove what\n  you left out. config_replace makes the device match the supplied config in\n  full — anything absent from your text is REMOVED, including the management\n  interface, AAA, and your own access. Never pass a partial config to\n  config_replace.\n- Never generate a full replacement config from scratch. Start from the output\n  of config_backup and edit that — but call it with `include_secrets=True`\n  for that purpose, or the `<redacted>` placeholders become literal\n  passwords on the device. Better still, take the backup with the CLI's\n  `-o <path>` and edit the file.\n- config_rollback reverts the last commit only, and rollback depth is\n  device-dependent — treat it as a single shot, not an undo history.\n- Never change more than one device per confirmed request.\n\nNETBOX VS THE DEVICE\n- NetBox describes intended state; the device reports actual state. When they\n  disagree, that IS the finding. Report both values side by side and label which\n  came from which. Do not silently reconcile them, and never edit a device to\n  match NetBox without the operator explicitly asking for exactly that.\n\nSCOPE\n- Separate observation from interpretation. State what the tools returned, then\n  any interpretation, clearly marked as such.\n- Do not assert a link, routing, or hardware problem unless a tool result\n  supports it.\n- Do not add generic advice that does not follow from the tool output.\n- Do not confuse a target name (the entry in config.yaml) with the device's own\n  hostname, an interface name with a VLAN id, or a BGP neighbor IP with an\n  interface address.\n```\n\n## Recommended setup for a local model\n\n```bash\nnetwork-aiops doctor\n```\n\nAuthorization is not this tool's job — decide it via the account or the agent's\nprompt, not a switch in the skill. The safest posture while you build trust is to\nconnect with a **device account that has read-only privileges** (and a read-only\nNetBox API token): a write then fails at the device itself, the place that\nactually owns the permission, no matter what the model attempts. When you are\nready to allow config changes, connect with an account that can write.\n\n`NETWORK_AUDIT_APPROVED_BY` / `NETWORK_AUDIT_RATIONALE` are optional annotations —\nthey record who asked for a change and why on the audit row, but they never block\na call:\n\n```bash\nexport NETWORK_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport NETWORK_AUDIT_RATIONALE=\"change window CHG-1234, 2026-07-20\"\n```\n\n## Platform notes worth knowing\n\n**Merge vs replace is the single most dangerous distinction here.** NAPALM stages\na *candidate* config and `compare_config()` shows the diff before anything is\napplied. `load_merge_candidate` (behind `config_merge`) is additive. Whereas\n`load_replace_candidate` (behind `config_replace`) makes the running config\n*equal* your text — every line you omitted is removed. On Junos this is a\n`load override`; on IOS-XR a `commit replace`; on EOS/IOS the driver synthesises\nit. A model that treats replace like merge will drop the management VRF and lock\nyou out. `config_replace` is `high` risk — recorded as a `review` tier in the\naudit trail for exactly this reason — and both writes return the pre-change\nrunning config as `backup`.\n\n**The commit / rollback path is device-dependent.** `commit_config()` applies the\ncandidate; `config_rollback` calls NAPALM's `rollback()`, which reverts the last\ncommit. Some platforms keep exactly one rollback point (IOS's archive-based\nimplementation is not a rollback stack the way Junos's `rollback 1..49` is).\nTreat rollback as one shot. The durable recovery path is the recorded undo\ndescriptor — it replays the captured `backup` through `config_replace`, which\nmeans the target must support config replace for the undo to apply.\n\n**Interface names are literal, per-vendor strings.** `GigabitEthernet0/1` (IOS),\n`Ethernet1` (EOS), `ge-0/0/0` (Junos), `TenGigE0/0/0/1` (IOS-XR). NAPALM\nnormalises the *schema*, not the *names*. Every tool returns names exactly as the\ndevice reports them, and every tool that takes one expects the same form back. A\nmodel that \"helpfully\" tidies `GigabitEthernet0/1` into `Gi0/1` will produce a\nconfig line the device rejects, or worse, one that silently creates a different\ninterface.\n\n**NetBox and the device will disagree, and that is signal.** `netbox_device_interfaces`\nreturns the intended inventory; `get_interfaces` returns what is actually\nconfigured and up. Drift is the whole point of asking both. Report both sides\nwith their sources named rather than picking a winner — the correct fix is\nsometimes to update NetBox, not the switch, and that is an operator's call.\nNote that the NetBox listings are paginated: check `truncated` before calling any\ninterface \"missing from source of truth\".\n\n**Not every getter exists on every platform.** `get_vlans`, `get_optics`,\n`get_environment` and `get_network_instances` in particular vary widely. An\nunsupported getter raises a teaching error naming the driver; that is a real\nanswer (\"this platform can't report it\"), not a failure to route around.\n\n## If your model still struggles\n\nSome behaviours are model-capacity limits rather than prompt problems:\n\n- **Multi-tool workflows time out or drift.** Prefer `interface_health_rca` and\n  `bgp_neighbor_rca` — they collect the interfaces, counters and neighbor state\n  and correlate them inside one call, so the model does not have to chain reads\n  and keep interface names straight across turns.\n- **The model ignores later tool results in a long context.** A full\n  `get_interfaces` on a chassis switch is hundreds of rows. Ask narrower\n  questions, and use `--limit` deliberately on the NetBox listings rather than\n  pulling whole inventories.\n- **The model edits config it was only asked to read.** Connect with a read-only\n  device account so writes fail at the device, and lean on `config_backup` +\n  `config_diff` (both reads); hand the diff to a human for the commit.\n- **The model describes calls instead of making them.** This is usually a\n  runtime/tool-calling-format mismatch, not a prompt problem — check that your\n  client advertises the tools in the format your model was trained on.\n\nFeedback on running this with a specific local model is genuinely useful —\nopen an issue at\n[github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops/issues)\nwith the model, runtime, driver, and what went wrong.\n\nFile v0.12.3:references/capabilities.md\n\n# network-aiops Capabilities\n\n33 MCP tools (28 read / 5 write). Every tool is wrapped with `@governed_tool`\n(audit + policy + budget + risk-tier; undo where a clean inverse exists). Returns\nare high-signal summaries — config blobs are sanitized and size-bounded. Secrets\nare never returned (user password hashes and SNMP community strings are redacted).\n\n## Read tools\n\n| Tool | Returns | Risk | Typical response tokens |\n|------|---------|:----:|:-----------------------:|\n| `device_facts` | hostname, vendor, model, os_version, serial, uptime, interface list | low | ~80–300 |\n| `get_interfaces` | per-interface up/enabled/speed/description/mac | low | ~60–800 |\n| `get_interfaces_counters` | per-interface octets/packets/errors/discards | low | ~60–800 |\n| `get_interfaces_ip` | per-interface IPv4/IPv6 + prefix length | low | ~40–400 |\n| `get_bgp_neighbors` | per-VRF peer, remote AS, up, prefix counts | low | ~60–600 |\n| `get_bgp_neighbors_detail` | + state, router id, local AS, advertised prefixes | low | ~80–900 |\n| `get_lldp_neighbors` | local port, remote host, remote port | low | ~40–400 |\n| `get_lldp_neighbors_detail` | + chassis id, system desc, capabilities | low | ~60–700 |\n| `get_arp_table` | interface, IP, MAC, age | low | ~50–700 |\n| `get_mac_address_table` | MAC, interface, VLAN, static/active | low | ~50–900 |\n| `get_vlans` | id, name, member interfaces | low | ~40–500 |\n| `get_route_to` | per-prefix protocol, next hop, outgoing interface | low | ~40–500 |\n| `get_environment` | fans, temperature, power, CPU, memory | low | ~60–500 |\n| `get_optics` | per-interface rx/tx power, laser bias | low | ~40–400 |\n| `get_ntp_servers` | configured NTP servers | low | ~20–120 |\n| `get_ntp_stats` | per-peer stratum, offset, jitter, reachability | low | ~40–300 |\n| `get_users` | username, level, has_password (hash redacted) | low | ~30–200 |\n| `get_snmp_information` | chassis id, contact, location, community_count | low | ~40 |\n| `get_network_instances` | VRFs: name, type, RD, interfaces | low | ~40–400 |\n| `device_health` | facts + interface up/down + environment + issues | low | ~120–400 |\n| `interface_health_rca` | worst-first findings: down / error / discard / flap, each cited | low | ~80–600 |\n| `bgp_neighbor_rca` | worst-first findings: down / shut / reset / route-less, each cited | low | ~60–500 |\n| `config_backup` | running config, credential values masked (`include_secrets=True` for raw) | low | ~500–8000 |\n| `config_diff` | candidate diff, credential values masked (dry-run, never committed) | low | ~30–1500 |\n| `netbox_list_devices` | `{devices, returned, limit, truncated}` — name, role, site, status, primary IP | low | ~40–500 |\n| `netbox_get_device` | + device_type, serial | low | ~80 |\n| `netbox_device_interfaces` | `{interfaces, returned, limit, truncated}` — name, type, enabled, description | low | ~40–600 |\n| `undo_list` | recorded, not-yet-applied reversible writes (undoId, original/inverse tool, note) | low | ~40–400 |\n\n> **Optional fields are `null`, not `\"\"`.** Any value the driver or NetBox did\n> not return (`serial_number`, `model`, an interface `description`, an LLDP\n> `remote_host`, a NetBox `site`) comes back as JSON `null`. An empty string\n> means the field genuinely is empty. Never infer a value from `null`.\n\n> **Truncation is measured.** The two NetBox listings return an envelope with\n> `truncated`; one extra record is fetched to determine it. When `truncated` is\n> true, re-run with a higher `limit` before drawing any conclusion about\n> coverage or drift.\n\n## Write tools\n\n| Tool | Effect | Risk | Undo |\n|------|--------|:----:|------|\n| `config_merge` | merge snippet + commit under a revert timer | medium | `config_replace` back to captured running config |\n| `config_replace` | replace full config + commit under a revert timer | **high** | `config_replace` back to captured running config |\n| `confirm_commit` | confirm a pending commit-confirm, cancelling its revert timer | medium | none (doing nothing lets the device revert) |\n| `config_rollback` | revert last commit | medium | none (already a revert) |\n| `undo_apply` | execute a recorded inverse descriptor — itself governed, single-use, supports `dry_run` | medium | none (is the undo) |\n\n## Per-driver support notes\n\n| Getter / op | ios | nxos / nxos_ssh | iosxr | eos | junos |\n|-------------|:---:|:---------------:|:-----:|:---:|:-----:|\n| `get_facts` / `get_interfaces` / `get_interfaces_ip` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_bgp_neighbors` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_lldp_neighbors` / `get_arp_table` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_interfaces_counters` / `get_mac_address_table` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_bgp_neighbors_detail` | ✓ | varies | ✓ | ✓ | ✓ |\n| `get_environment` / `get_ntp_*` / `get_users` / `get_snmp_information` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_vlans` / `get_network_instances` | varies | ✓ | ✓ | ✓ | ✓ |\n| `get_optics` | varies | varies | ✓ | ✓ | ✓ |\n| `get_route_to` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_config` (backup) | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `load_merge_candidate` + `compare_config` (diff/merge) | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `load_replace_candidate` (replace) | ✓ | varies | ✓ | ✓ | ✓ |\n| `rollback` | ✓ (archive) | varies | ✓ | ✓ | ✓ |\n\nA getter that a given driver does not implement raises `NotImplementedError`,\nwhich the ops layer turns into a teaching `NetworkApiError` (\"not supported by\nthe `<driver>` driver\").\n\n## Token-budget notes\n\n- `config_backup` can be large; prefer `config_diff` to preview a change instead\n  of re-fetching the whole config repeatedly.\n- The runaway guard trips on tight poll loops — wait between repeated reads.\n\n## Design notes / NAPALM assumptions\n\n- NAPALM connections are short-lived: each tool opens a driver, runs its\n  getters/config calls, and closes it. Nothing is cached across calls.\n- Device passwords and the NetBox token come from the encrypted store\n  `~/.network-aiops/secrets.enc` (unlocked by `NETWORK_AIOPS_MASTER_PASSWORD`;\n  legacy plaintext env vars are a deprecated fallback). Enable/secret and\n  transport go in `optional_args` and are passed verbatim to NAPALM. The skill\n  never logs, echoes, or returns the credential.\n- Connection / command / driver errors are translated centrally at the connection\n  layer into a teaching `NetworkApiError`, so agents see actionable messages.\n- Only the five core drivers are validated here; community drivers are untested.\n\n## Commit-confirm (the guard for a change that can lock you out)\n\n`config_merge` / `config_replace` call NAPALM's `commit_config(revert_in=N)`\n(default 300s). The **device** reverts the change on its own unless\n`confirm_commit` arrives first. This matters because the recorded undo is a\n`config_replace` that must open a NEW session to the same device — a commit that\nshuts the management interface, tightens the VTY ACL or breaks AAA kills exactly\nthat path, so an undo token is not a guard against lockout. A device-enforced\ntimer is.\n\nWorkflow: **commit (timer armed) → verify reachability from a NEW session →\n`confirm_commit`**. Doing nothing is the safe branch.\n\nThe result's `commit` block reports what actually happened:\n\n| `commit.safetyNet` | Meaning |\n|---|---|\n| `commit-confirm` | timer armed; the change reverts in `commit.revertInSeconds` unless confirmed |\n| `undo-only` | **no timer** — the driver refused one or `revert_in=0` was passed. The change is permanent on landing; `commit.warning` says so. Arrange out-of-band access before making lockout-capable changes on such a device. |\n\nA write with **neither** a timer nor a usable captured backup is refused\noutright (`UnreversibleCommit`) before anything is committed.\n\n### Backups are digested, not echoed\n\n`config_merge` / `config_replace` return `backup` as `{bytes, sha256,\nretainedForUndo}` — not the config body. A running config carries credential\nhashes, SNMP communities, PSKs and RADIUS keys, and a tool result lands in the\nagent transcript. The byte-exact raw text is kept only in `undo.db` (0600) for\nthe rollback. Use `config_backup` when you deliberately want the text.\n\n### Credential values are masked, and the masking is reported\n\n`config_backup` cannot withhold the config — returning it IS the tool's\ncontract — so it masks credential VALUES instead: password/secret hashes, SNMP\ncommunities, SNMPv3 auth/priv material, IKE pre-shared keys, RADIUS/TACACS and\nkeychain keys become `<redacted>`. Every other line is byte-for-byte what the\ndevice said. The same applies to every `diff`, because a diff that adds\n`snmp-server community X` contains X.\n\nEach result carries a `redaction` block (`applied`, `linesRedacted`, `note`) so\nthe transformation is never silent. `include_secrets=True` returns the verbatim\ntext, and the CLI's `-o <path>` writes raw to a file the operator named.\n\n**Limit**: this is pattern matching over five vendor syntaxes. It REDUCES\nexposure; it does not guarantee the text is credential-free. Line-oriented\nrules cannot see multi-line PKI key blocks. Do not describe redacted output as\n\"safe to share\".\n\n### `dry_run` does not bypass the guard\n\n`config_merge(dry_run=True)` / `config_replace(dry_run=True)` (and the CLI's\n`--dry-run`) stage the candidate, return the diff, discard it, and run the SAME\n`UnreversibleCommit` refusal the real commit would — a green preview is never\nfollowed by a refusal a model would read as transient and retry.\n\nThe CLI's `--dry-run` on `config merge` / `config replace` routes through the\nsame governed twin, so it reaches the same guard **and** records the same audit\nrow. The line's invariant is: **a dry_run MAY read; it must never write.** A\npreview that cannot read cannot answer \"would this be refused?\", so reads are\nexpected; the mutating call is the thing that must never happen.\n\n(`config rollback` and `config confirm` have no `dry_run` parameter — there is no\ngoverned preview to route through, so their `--dry-run` short-circuits\nclient-side and records nothing.)\n\nOne asymmetry is deliberate and safe in the right direction: the preview can only\n*predict* commit-confirm support from the driver's `commit_config` signature,\nwhereas the real write also learns from a `NotImplementedError` raised at commit\ntime. So the preview's refusal condition is a strict **subset** of the write's —\nit never refuses something the write would allow. The preview reports its\nprediction as `commit.wouldArmTimer` / `commit.safetyNet`.\n\nFile v0.12.3:references/cli-reference.md\n\n# network-aiops CLI Reference\n\nAll commands accept `-t/--target <name>` to select a configured device. When\nomitted, the first device in `~/.network-aiops/config.yaml` is used.\n\n## Onboarding & secrets\n\n```bash\nnetwork-aiops init                              # interactive wizard: devices + encrypted passwords (+ NetBox)\nnetwork-aiops secret set <name>                 # store/replace a device password, or 'netbox-token' (hidden prompt)\nnetwork-aiops secret list                       # names only — values are never printed\nnetwork-aiops secret rm <name>                  # delete a stored secret\nnetwork-aiops secret migrate                    # import a legacy plaintext .env into the encrypted store\nnetwork-aiops secret rotate-password            # re-encrypt the store under a new master password\n```\n\nSecrets are stored encrypted in `~/.network-aiops/secrets.enc`. Unlock\nnon-interactively with `NETWORK_AIOPS_MASTER_PASSWORD`.\n\n## Device facts & state (read-only)\n\n```bash\nnetwork-aiops device facts [-t <device>]        # hostname, vendor, model, OS, serial, uptime\nnetwork-aiops device interfaces [-t <device>]   # up/down, enabled, speed, description\nnetwork-aiops device counters [-t <device>]     # per-interface traffic + error counters\nnetwork-aiops device bgp [-t <device>]          # BGP neighbors per VRF\nnetwork-aiops device lldp [-t <device>]         # LLDP neighbors\nnetwork-aiops device arp [-t <device>]          # ARP table\nnetwork-aiops device mac [-t <device>]          # MAC address table\nnetwork-aiops device vlans [-t <device>]        # VLANs (id, name, member count)\nnetwork-aiops device route <prefix> [-t <device>] [--protocol bgp]  # routing-table lookup\nnetwork-aiops device environment [-t <device>]  # fans, temperature, power, CPU, memory\nnetwork-aiops device health [-t <device>]       # aggregated health summary\n```\n\nAdditional read getters are exposed as MCP tools (no dedicated CLI subcommand):\n`get_bgp_neighbors_detail`, `get_lldp_neighbors_detail`, `get_optics`,\n`get_ntp_servers`, `get_ntp_stats`, `get_users`, `get_snmp_information`,\n`get_network_instances`. A getter a driver does not implement returns a teaching\n\"not supported by the `<driver>` driver\" error.\n\n## Configuration\n\n```bash\nnetwork-aiops config backup [-t <device>] [-o <file>]      # running config (save with -o)\nnetwork-aiops config diff <file> [-t <device>] [--replace] # DRY-RUN: show the diff only\nnetwork-aiops config merge <file> [-t <device>] [--dry-run] [--revert-in N]   # commit; double confirm\nnetwork-aiops config replace <file> [-t <device>] [--dry-run] [--revert-in N] # HIGH RISK; double confirm\nnetwork-aiops config confirm [-t <device>] [--dry-run]         # confirm a pending commit\nnetwork-aiops config rollback [-t <device>] [--dry-run]        # revert last commit; double confirm\n```\n\n- `config diff` stages a candidate, runs `compare_config()`, and discards it —\n  nothing is committed. `--replace` diffs as a full-config replacement.\n- `--dry-run` on `merge` / `replace` prints the same diff without committing.\n- `merge` / `replace` capture the pre-change running config for the undo store.\n- `merge` / `replace` commit under a **device-side revert timer**\n  (`--revert-in`, default 300s): the device undoes the change by itself unless\n  `config confirm` follows. Use it for anything that could sever your own\n  management path — it is the only guard that works when you cannot reach the\n  device any more. `--revert-in 0` disables it (undo-only).\n- After committing, re-connect in a **new** session, verify, then\n  `network-aiops config confirm`. If a driver cannot arm a timer the command\n  prints a red `NO COMMIT-CONFIRM SAFETY NET` warning.\n\n## NetBox (optional source-of-truth)\n\n```bash\nnetwork-aiops netbox list [--name <q>] [--limit N]   # name, role, site, status, primary IP\nnetwork-aiops netbox get <name>                      # single device by exact name\nnetwork-aiops netbox interfaces <device> [--limit N] # device interfaces from source-of-truth\n```\n\nRequires a `netbox:` block in config and an encrypted `netbox-token` secret\n(`network-aiops secret set netbox-token`, or via `network-aiops init`).\n\n## Diagnostics & MCP\n\n```bash\nnetwork-aiops doctor [--skip-auth]   # check config + encrypted secret store + per-device password + reachability\nnetwork-aiops mcp                    # start the MCP server over stdio\n```\n\n## Flags summary\n\n| Flag | Meaning |\n|------|---------|\n| `-t, --target` | Device name from `~/.network-aiops/config.yaml` |\n| `-o, --output` | Write `config backup` output to a file |\n| `--replace` | Diff/treat the config file as a full replacement (`config diff`) |\n| `--dry-run` | Preview a destructive config op as a diff without committing |\n| `--protocol` | Filter `device route` by routing protocol (bgp, ospf, …) |\n| `--name` | NetBox name filter (`netbox list`) |\n| `--limit` | NetBox page size (`netbox list` / `netbox interfaces`) |\n| `--skip-auth` | Skip the connectivity check in `doctor` |\n\nFile v0.12.3:references/setup-guide.md\n\n# network-aiops Setup Guide\n\n## Install\n\n```bash\nuv tool install network-aiops\nnetwork-aiops init      # interactive onboarding wizard (recommended)\nnetwork-aiops doctor\n```\n\n`network-aiops` requires Python ≥ 3.11. If `uv` picked an older interpreter:\n\n```bash\nuv python install 3.12\nuv tool install --python 3.12 --force network-aiops\n```\n\n## Configure devices\n\nCreate `~/.network-aiops/config.yaml`:\n\n```yaml\ndevices:\n  - name: core-sw1            # used as -t core-sw1\n    driver: eos               # ios | nxos | nxos_ssh | iosxr | eos | junos\n    host: 10.0.0.1\n    username: admin\n    optional_args:            # passed verbatim to NAPALM (optional)\n      secret: enable-pw       # enable/secret\n      port: 443\n  - name: edge-rtr\n    driver: ios\n    host: 10.0.0.254\n    username: netops\n# Optional source-of-truth:\nnetbox:\n  url: https://netbox.example.com\n```\n\n### Secrets — encrypted store (never in config.yaml)\n\nSecrets are stored **encrypted** in `~/.network-aiops/secrets.enc` (Fernet/AES +\nscrypt-derived key; chmod 600) — never in config.yaml or a plaintext `.env`.\nDevice login passwords are keyed by the device name; the NetBox API token uses\nthe reserved name `netbox-token`. The fastest path is `network-aiops init`, or\nset them individually:\n\n```bash\nnetwork-aiops secret set core-sw1       # hidden prompt for the device password\nnetwork-aiops secret set edge-rtr\nnetwork-aiops secret set netbox-token   # the NetBox API token\nnetwork-aiops secret list               # names only — values are never printed\n```\n\nUnlock the store non-interactively by exporting the master password (used by the\nMCP server, cron, CI):\n\n```bash\nexport NETWORK_AIOPS_MASTER_PASSWORD='your-master-password'\nchmod 700 ~/.network-aiops\n```\n\n**Migrating from a legacy plaintext `.env`** (`NETWORK_<TARGET_UPPER>_PASSWORD`,\n`NETWORK_NETBOX_TOKEN`): run `network-aiops secret migrate` to import them into\nthe encrypted store (the old file is renamed to `.env.migrated`; delete it once\nverified). Those env vars still work as a deprecated fallback with a warning. An\nempty device password is allowed for key-based SSH auth.\n\n### Supported drivers\n\n`ios` (Cisco IOS/IOS-XE), `nxos` / `nxos_ssh` (Cisco Nexus NX-OS), `iosxr`\n(Cisco IOS-XR), `eos` (Arista EOS), `junos` (Juniper Junos). Other platforms\n(Nokia SR OS / SR Linux, Huawei VRP, …) are reachable via NAPALM community\ndrivers but are untested here — request official support via a GitHub issue/PR.\n\n## Security\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox Labs, or any network vendor.** Vendor and product names are trademarks of their respective owners. Source is auditable at [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops) under the MIT license.\n\n1. **Source code** — [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops), MIT.\n2. **Config file contents** — `config.yaml` holds only device names, drivers,\n   hosts, usernames, and NAPALM `optional_args`. No credentials.\n3. **Credentials** — device passwords and the NetBox token live in the encrypted\n   store `~/.network-aiops/secrets.enc` (Fernet/AES, scrypt-derived key, chmod\n   600), unlocked by `NETWORK_AIOPS_MASTER_PASSWORD`; never read back, logged, or\n   echoed. Legacy plaintext env vars remain a deprecated fallback. Keep the dir\n   chmod 700.\n4. **TLS verification** — NAPALM transports (eAPI/NX-API HTTPS, NETCONF/SSH)\n   follow each device's own certificate / SSH host-key configuration; the skill\n   does not weaken it.\n5. **Prompt-injection protection** — all device-returned text (facts, configs,\n   diffs, neighbor data) is run through `sanitize()` (truncation + control-char\n   stripping).\n6. **Least privilege** — use a device account with only the privilege you need:\n   a read-only login for facts/backup, and a config-capable login only for the\n   merge/replace/rollback tools.\n\n## Governance harness\n\nBundled under `network_aiops.governance` — no external dependency. State lives\nunder `~/.network-aiops/` (override with `NETWORK_AIOPS_HOME`):\n\n- `audit.db` — every tool call (skill, tool, params, status, duration, agent).\n- Token/runaway budget guard (`NETWORK_MAX_TOOL_CALLS`, `NETWORK_MAX_TOOL_SECONDS`,\n  `NETWORK_RUNAWAY_MAX`, `NETWORK_RUNAWAY_WINDOW_SEC`).\n- Undo store — inverse descriptors for reversible writes (config merge/replace).\n- Encrypted secret store (`secrets.enc`) — device passwords + NetBox token,\n  unlocked by `NETWORK_AIOPS_MASTER_PASSWORD`.\n- Accountability (optional): set `NETWORK_AUDIT_APPROVED_BY` /\n  `NETWORK_AUDIT_RATIONALE` to annotate the audit row with who asked for a change\n  and why. They are optional and never block a call — the skill does not authorize\n  operations; that is the agent's judgement or the connecting account's privilege.\n\n## MCP client config\n\n```jsonc\n{\n  \"command\": \"network-aiops\",\n  \"args\": [\"mcp\"],\n  \"env\": {\n    \"NETWORK_AIOPS_CONFIG\": \"~/.network-aiops/config.yaml\",\n    \"NETWORK_AIOPS_MASTER_PASSWORD\": \"…\"\n  }\n}\n```\n\nFallback (no `uv tool install`): `uvx --from network-aiops network-aiops-mcp`.\nPrefer the installed entry point — it does not re-resolve PyPI at launch.\n\n## Static analysis\n\n```bash\nuvx bandit -r network_aiops/ mcp_server/\n```\n\nFile v0.12.3:skill-card.md\n\n## Description:\n\nNetwork AIops supports governed multi-vendor network device operations over NAPALM, including device state reads, diagnostics, configuration backup and diff, configuration merge/replace/rollback, and optional NetBox source-of-truth lookups.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nNetwork operators, SREs, and infrastructure engineers use this skill to inspect Cisco, Arista, Juniper, and other NAPALM-supported devices, troubleshoot interface and BGP issues, back up and compare configurations, and perform governed configuration changes. It is also useful for agents that need optional NetBox lookups alongside live device state.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can perform high-impact network configuration operations and handles device and NetBox credentials.\n\nMitigation: Review before production use, prefer read-only device and NetBox credentials unless writes are explicitly required, and require operators to inspect diffs before merge, replace, rollback, or undo operations.\n\nRisk: Raw device configurations and diffs may contain secrets or sensitive operational data.\n\nMitigation: Avoid include_secrets=True in agent or MCP workflows, keep enable secrets out of config.yaml, and prefer local file exports when a raw configuration must be reviewed by a human.\n\nRisk: Package supply-chain changes could affect a tool with access to device credentials.\n\nMitigation: Pin or internally mirror the network-aiops package before granting it production network access.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/network-aiops)\n- [Project homepage](https://github.com/AIops-tools/Network-AIops)\n- [Issue tracker](https://github.com/AIops-tools/Network-AIops/issues)\n- [Agent guardrails](references/agent-guardrails.md)\n- [Capabilities](references/capabilities.md)\n- [CLI reference](references/cli-reference.md)\n- [Setup guide](references/setup-guide.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline shell commands and structured tool-result summaries]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May produce device facts, diagnostics, diffs, backups, NetBox summaries, and operator-facing remediation guidance; large configuration outputs may be size-bounded or redacted.]\n\n## Skill Version(s):\n\n0.12.3 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.12.2: 7 files, 25854 bytes\n\nFiles: references/agent-guardrails.md (11690b), references/capabilities.md (10561b), references/cli-reference.md (4989b), references/setup-guide.md (5363b), skill-card.md (2434b), SKILL.md (24455b), _meta.json (133b)\n\nFile v0.12.2:SKILL.md\n\n---\nname: network-aiops\nslug: network-aiops\ndisplayName: \"Network AIops\"\nsummary: \"Governed network device ops (NAPALM) — 33 MCP tools with audit/undo.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Network-AIops\ntags: [aiops, mcp, governance, network]\ndescription: >\n  Use this skill whenever the user needs to operate a network device — read device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary and detail), ARP/MAC tables, VLANs, routes, hardware environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, and an aggregated device-health summary; run read-only RCA diagnostics on interface health and BGP neighbors; back up a switch/router config, diff a candidate config (dry-run), and merge/replace/rollback config — across Cisco IOS/IOS-XE, Nexus NX-OS, IOS-XR, Arista EOS, and Juniper Junos via NAPALM. An optional NetBox block adds source-of-truth lookups.\n  Always use this skill for \"back up switch config\", \"show bgp neighbors\", \"diff network config\", \"push config to router\", \"show interfaces on the switch\", or tasks mentioning \"cisco\", \"arista\", \"juniper\", \"nexus\", \"ios-xr\", or \"napalm\".\n  Do NOT use when the target is not a NAPALM-supported network device (Kubernetes clusters, hypervisor VMs, and cloud consoles are out of scope — route those elsewhere).\n  Common multi-vendor device operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\ninstaller:\n  kind: uv\n  package: network-aiops\nargument-hint: \"[device name or describe your network task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"network-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"NETWORK_AIOPS_CONFIG\",\"NETWORK_AIOPS_HOME\",\"NETWORK_AIOPS_MASTER_PASSWORD\",\"NETWORK_NETBOX_TOKEN\"]},\"homepage\":\"https://github.com/AIops-tools/Network-AIops\",\"emoji\":\"🛜\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed network device operations over NAPALM. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency.\n  All write operations are audited to a local SQLite DB under ~/.network-aiops/ (relocatable via NETWORK_AIOPS_HOME).\n  Credentials: device login passwords AND the optional NetBox API token live in an ENCRYPTED store at ~/.network-aiops/secrets.enc (Fernet/AES + scrypt-derived key; chmod 600), never in plaintext. Device passwords are keyed by the device name; the NetBox token uses the reserved name \"netbox-token\". Unlock with the NETWORK_AIOPS_MASTER_PASSWORD env var (for the MCP server / non-interactive use) or an interactive prompt. Run `network-aiops init` (wizard) or `network-aiops secret set <name>` to populate it, and `network-aiops secret migrate` to import a legacy plaintext .env (NETWORK_<TARGET_UPPER>_PASSWORD / NETWORK_NETBOX_TOKEN are still honoured as a deprecated fallback). config.yaml holds only device names, drivers, hosts, usernames, and NAPALM optional_args — never secrets. The state dir ~/.network-aiops should be chmod 700.\n  Destructive operations (config merge, config replace, config rollback) require double confirmation at the CLI layer and support --dry-run (which prints the diff without committing). All write tools pass through the @governed_tool decorator (budget guard + audit + risk-tier tagging). config_merge and config_replace capture the pre-change running config and record an inverse config_replace-to-backup undo descriptor; config_rollback records none, and config_replace is risk_level=high.\n  Webhooks: none — no outbound network calls beyond the configured device sessions and the optional NetBox API.\n  TLS: NAPALM driver transports (eAPI/NX-API HTTPS, NETCONF/SSH) follow the device's own certificate/SSH host-key settings; the skill does not weaken them.\n  Transitive dependencies: napalm (device drivers), pynetbox (optional source-of-truth), typer/rich (CLI), pyyaml/python-dotenv (config), and the MCP SDK. No post-install scripts or background services.\n---\n\n# Network AIops\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox Labs, or any network vendor.** Vendor and product names are trademarks of their respective owners. Source code is publicly auditable at [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops) under the MIT license.\n\nGoverned multi-vendor network device operations — **33 MCP tools**, every one wrapped with the bundled `@governed_tool` harness: a local unified audit log under `~/.network-aiops/`, token/runaway budget guard, undo-token recording, and descriptive risk-tier labels. Devices are reached over NAPALM; an optional NetBox block adds source-of-truth lookups. Secrets (device passwords + NetBox token) are kept in an **encrypted store** (`secrets.enc`), unlocked by `NETWORK_AIOPS_MASTER_PASSWORD`.\n\n> **Standalone**: the governance harness is bundled in the package (`network_aiops.governance`) — network-aiops has no external skill-family dependency. Coverage focuses on common operations and is not yet exhaustive.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read or Write |\n|----------|-------|:-----:|:-------------:|\n| **Device facts** | facts, interfaces, interface counters, interface IPs, BGP (+detail), LLDP (+detail), ARP | 9 | 9 read |\n| **Inventory** | MAC table, VLANs, route lookup | 3 | 3 read |\n| **Platform / env** | environment, optics, NTP servers, NTP stats, users, SNMP info, VRFs, device_health | 8 | 8 read |\n| **Diagnostics / RCA** | interface_health_rca, bgp_neighbor_rca | 2 | 2 read |\n| **Config** | backup, diff (dry-run), merge, replace, rollback | 5 | 2 read / 3 write |\n| **NetBox** | list devices, get device, device interfaces | 3 | 3 read |\n| **Undo** | undo_list, undo_apply | 2 | 1 read / 1 write |\n\n## Quick Install\n\n```bash\nuv tool install network-aiops\nnetwork-aiops init            # interactive wizard: device + driver + host + encrypted password (+ optional NetBox)\nnetwork-aiops doctor          # checks config, encrypted secret store, and per-device password presence\n```\n\nOr as an OpenClaw plugin, which installs this skill and its MCP server together:\n\n```bash\nopenclaw plugins install clawhub:@zw008/network-aiops\nopenclaw skills info network-aiops          # expect: Visible to model: yes\n```\n\nNeeds `uvx` on `PATH`: the MCP server is fetched with uv, pinned to this release.\n\n`init` writes `~/.network-aiops/config.yaml` and stores secrets **encrypted** in `~/.network-aiops/secrets.enc`. Export `NETWORK_AIOPS_MASTER_PASSWORD` in your shell profile so the CLI and MCP server can unlock secrets non-interactively.\n\n## Supported Devices\n\n| Platform | NAPALM driver | Transport |\n|----------|---------------|-----------|\n| Cisco IOS / IOS-XE | `ios` | SSH |\n| Cisco Nexus NX-OS | `nxos` (NX-API) / `nxos_ssh` (SSH) | HTTPS / SSH |\n| Cisco IOS-XR | `iosxr` | SSH (XML agent) |\n| Arista EOS | `eos` | eAPI (HTTPS) |\n| Juniper Junos | `junos` | NETCONF (SSH) |\n\nOther platforms (Nokia SR OS / SR Linux, Huawei VRP, etc.) are reachable via NAPALM **community drivers** but are **not officially tested here** — see [Contributing](#contributing--request-a-device-or-feature).\n\n## When to Use This Skill\n\n- Inspect device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary + detail), ARP/MAC tables, VLANs, and route lookups\n- Check hardware health: environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, or a one-shot `device_health` summary\n- Root-cause a problem with read-only RCA: `interface_health_rca` (down/erroring/discarding/flapping ports) and `bgp_neighbor_rca` (down/shut/recently-reset/route-less peers) — each finding cites the measured number that tripped it, worst-first\n- Back up a switch/router running config to a file\n- Dry-run a config change as a diff before committing\n- Merge a config snippet, replace the full config, or roll back the last commit\n- Cross-check intended state in NetBox before pushing a change\n\n**Do NOT use when** the target is not a NAPALM-supported network device (Kubernetes clusters, hypervisor VMs, and cloud-provider consoles are out of scope for this skill).\n\n## Related Skills — Skill Routing\n\n| If the user wants… | Use |\n|--------------------|-----|\n| Network device config / facts (Cisco/Arista/Juniper) | **network-aiops** (this skill) |\n| Kubernetes cluster operations | a cluster ops skill |\n| Hypervisor VM lifecycle (power, snapshot, migrate) | a hypervisor ops skill |\n\n## Supported Actions\n\n| Tool | R/W | Risk | Driver support |\n|------|:---:|:----:|----------------|\n| `device_facts` | R | low | all 5 |\n| `get_interfaces` | R | low | all 5 |\n| `get_interfaces_counters` | R | low | all 5 |\n| `get_interfaces_ip` | R | low | all 5 |\n| `get_bgp_neighbors` | R | low | all 5 (varies by feature) |\n| `get_bgp_neighbors_detail` | R | low | ios/eos/junos/iosxr; nxos varies |\n| `get_lldp_neighbors` | R | low | all 5 |\n| `get_lldp_neighbors_detail` | R | low | all 5 |\n| `get_arp_table` | R | low | all 5 |\n| `get_mac_address_table` | R | low | all 5 (varies by image) |\n| `get_vlans` | R | low | eos/junos/nxos; ios varies |\n| `get_route_to` | R | low | all 5 (varies by feature) |\n| `get_environment` | R | low | all 5 (sensor coverage varies) |\n| `get_optics` | R | low | eos/junos/iosxr; ios/nxos varies |\n| `get_ntp_servers` | R | low | all 5 |\n| `get_ntp_stats` | R | low | all 5 |\n| `get_users` | R | low | all 5 (password hashes redacted) |\n| `get_snmp_information` | R | low | all 5 (community strings redacted) |\n| `get_network_instances` | R | low | eos/junos/iosxr; ios/nxos varies |\n| `device_health` | R | low | all 5 (environment section optional) |\n| `interface_health_rca` | R | low | all 5 (needs get_interfaces + counters) |\n| `bgp_neighbor_rca` | R | low | all 5 (varies by BGP feature) |\n| `config_backup` | R | low | all 5 |\n| `config_diff` (dry-run) | R | low | all 5 |\n| `config_merge` | W | medium | all 5 |\n| `config_replace` | W | **high** | ios/eos/junos/iosxr; nxos varies |\n| `config_rollback` | W | medium | device-dependent rollback depth |\n| `netbox_list_devices` | R | low | NetBox (optional) |\n| `netbox_get_device` | R | low | NetBox (optional) |\n| `netbox_device_interfaces` | R | low | NetBox (optional) |\n\n**Per-driver caveat**: NAPALM does not implement every getter on every platform. Any unsupported getter returns a teaching error (\"not supported by the `<driver>` driver\") instead of crashing — try a different getter or fall back to `config_backup`. `device_health` is resilient: if a driver lacks `get_environment` that section is reported as a note, not a failure.\n\n**Credentials**: `get_users` reduces password hashes to a boolean and `get_snmp_information` reduces community strings to a count — those two never return secrets at all. `config_backup` and every returned `diff` *mask* credential values (password/secret hashes, SNMP communities, pre-shared keys, RADIUS/TACACS and keychain keys) and report how many lines they changed in a `redaction` block; `include_secrets=True` returns the verbatim text. The masking is pattern-based across five vendor syntaxes, so it reduces exposure rather than guaranteeing none remains — notably it cannot see multi-line PKI key blocks. To hand a real config to a human, prefer the CLI's `-o <path>`, which writes raw to a file instead of into this transcript.\n\n## Common Workflows\n\n### Safely change a device config with a dry-run first\n\n1. `network-aiops config backup -t core-sw1 -o core-sw1.cfg` → keep a known-good copy\n2. `network-aiops config diff change.cfg -t core-sw1` → preview the diff (nothing committed)\n3. `network-aiops config merge change.cfg -t core-sw1` (double confirm) → commits **under a 300s device-side revert timer**; the harness also records a `config_replace`-to-backup undo descriptor\n4. `network-aiops device interfaces -t core-sw1` → verify the result **and that you can still reach the device**\n5. `network-aiops config confirm -t core-sw1` → cancels the revert timer, making the change permanent. If you skip this (or get locked out), the device reverts by itself — that is the point\n6. **Failure branch**: if the connection fails (`Could not connect/authenticate`), run `network-aiops doctor` — it shows whether `NETWORK_CORE_SW1_PASSWORD` is set and whether the host/port is reachable; the skill never retries a denied auth.\n\n### Change something that could lock you out (mgmt interface, VTY ACL, AAA)\n\n1. `network-aiops config backup -t core-sw1 -o core-sw1.cfg` → an off-box copy, independent of the tool\n2. `network-aiops config diff risky.cfg -t core-sw1` → confirm the diff touches only what you intend\n3. `network-aiops config merge risky.cfg -t core-sw1 --revert-in 120` → short timer: if the change severs your session, the device restores itself in 2 minutes with nobody logged in\n4. Re-connect and verify. **Do not confirm from a session opened before the commit** — it may survive a change that blocks *new* logins\n5. `network-aiops config confirm -t core-sw1` → only once a NEW session proves the path still works\n6. **Failure branch**: if the result carries `commit.warning` with `safetyNet: \"undo-only\"`, this driver could not arm a timer. The change is permanent on landing and the recorded undo needs a working session — arrange out-of-band access (console/OOB mgmt) before you commit anything of this kind.\n\n### Root-cause a flaky uplink / peering problem (RCA-first)\n\n1. `network-aiops diagnose interface-health -t edge-rtr` → worst-first interface findings; a link that is admin-up/oper-down with climbing `rx_errors+tx_errors` and a recent `last_flapped` is a physical-layer fault (cable/optic), each cited with its measured value\n2. `network-aiops diagnose bgp -t edge-rtr` → worst-first neighbor findings; if the peer riding that link shows `BGP session down` or `recently reset` (low uptime), the L1 fault — not routing — is resetting the session\n3. `network-aiops device counters -t edge-rtr` → confirm the error counters are still climbing before you touch anything\n4. `network-aiops config diff fix.cfg -t edge-rtr` → dry-run the remediation first, then `config merge` (double confirm) through the audited path\n5. **Failure branch**: if `interface_health_rca` / `bgp_neighbor_rca` returns \"not supported by the `<driver>` driver\", the platform's NAPALM driver lacks the underlying getter — fall back to `device facts` / `config_backup` and request the getter via a GitHub issue.\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models | **CLI** | fewer tokens than MCP |\n| Cloud models (Claude, GPT) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | type-safe parameters, audited |\n\n## MCP Tools (33 — 28 read, 5 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Facts | `device_facts`, `get_interfaces`, `get_interfaces_counters`, `get_interfaces_ip`, `get_bgp_neighbors`, `get_bgp_neighbors_detail`, `get_lldp_neighbors`, `get_lldp_neighbors_detail`, `get_arp_table` | Read |\n| Inventory | `get_mac_address_table`, `get_vlans`, `get_route_to` | Read |\n| Platform / env | `get_environment`, `get_optics`, `get_ntp_servers`, `get_ntp_stats`, `get_users`, `get_snmp_information`, `get_network_instances`, `device_health` | Read |\n| Diagnostics / RCA | `interface_health_rca`, `bgp_neighbor_rca` | Read |\n| Config | `config_backup`, `config_diff` | Read |\n| | `config_merge`, `config_replace`, `confirm_commit`, `config_rollback` | Write |\n| NetBox | `netbox_list_devices`, `netbox_get_device`, `netbox_device_interfaces` | Read |\n| Undo | `undo_list` | Read |\n| | `undo_apply` | Write |\n\n**Commit-confirm is the primary safety net.** `config_merge` and `config_replace` commit with a device-side revert timer (`revert_in`, default 300s): the device rolls the change back on its own unless `confirm_commit` follows. This is the only guard that survives the change severing your own management path — a commit that shuts the management interface, tightens the VTY ACL or breaks AAA also kills the session the recorded undo would need, so the *device* has to be the one enforcing the rollback. Workflow: **commit with timer → verify you can still reach the device → `confirm_commit`** (or do nothing and let it revert). Drivers that cannot arm a timer fall back to a plain commit and say so in `commit.warning` / `commit.safetyNet` — check that field, because for those devices the net is absent.\n\n**Harness features that light up**: `config_merge` and `config_replace` capture the pre-change running config and pass an `undo=` lambda so the harness records an inverse descriptor (with `_undo_id`) that restores the captured config via `config_replace` — the device must support config replace for the undo to apply. The raw config is handed to the harness out-of-band and kept only in `undo.db` (0600); the tool result returns a **digest** (size + SHA-256), never the config body, because a running config carries credential hashes, SNMP communities and PSKs that would otherwise land in the agent transcript. `config_rollback` declares no undo; `config_replace` is tagged `risk_level=high`. `config_diff` is a pure dry-run (stage candidate → compare → discard). The two RCA tools (`interface_health_rca`, `bgp_neighbor_rca`) are pure read-only analyses (`risk_level=low`) that collect getter output and rank findings worst-first. All 33 tools are audit-logged under `~/.network-aiops/` and pass through the budget/runaway guard, with a descriptive risk tier tagged on each audit row. Avoid tight poll loops — the runaway breaker backs this up.\n\n## Encrypted secret store\n\nSecrets never touch disk in plaintext. They live in `~/.network-aiops/secrets.enc` (Fernet/AES-128 + HMAC, key derived from a master password via scrypt; file chmod 600). Both kinds of secret share the one store: per-device login passwords keyed by device name, and the single NetBox API token keyed by the reserved name `netbox-token`.\n\n```bash\nnetwork-aiops init                       # wizard: collects devices + passwords (encrypted), optional NetBox\nnetwork-aiops secret set core-sw1        # store/replace a device password (hidden prompt)\nnetwork-aiops secret set netbox-token    # store the NetBox API token\nnetwork-aiops secret list                # names only — values are NEVER printed\nnetwork-aiops secret rm core-sw1\nnetwork-aiops secret migrate             # import a legacy plaintext .env (renamed to .env.migrated)\nnetwork-aiops secret rotate-password     # re-encrypt the whole store under a new master password\n```\n\nUnlock non-interactively by exporting `NETWORK_AIOPS_MASTER_PASSWORD` (used by the MCP server / cron / CI). Legacy plaintext env vars (`NETWORK_<TARGET_UPPER>_PASSWORD`, `NETWORK_NETBOX_TOKEN`) are still honoured as a deprecated fallback with a warning. An empty device password is allowed (valid for key-based SSH auth via `optional_args`).\n\n## CLI Quick Reference\n\n```bash\nnetwork-aiops init                                               # onboarding wizard (encrypted secrets)\nnetwork-aiops device facts [-t <device>]\nnetwork-aiops device interfaces [-t <device>]\nnetwork-aiops device counters [-t <device>]\nnetwork-aiops device bgp [-t <device>]\nnetwork-aiops device lldp [-t <device>]\nnetwork-aiops device arp [-t <device>]\nnetwork-aiops device mac [-t <device>]\nnetwork-aiops device vlans [-t <device>]\nnetwork-aiops device route <prefix> [-t <device>] [--protocol bgp]\nnetwork-aiops device environment [-t <device>]\nnetwork-aiops device health [-t <device>]\nnetwork-aiops diagnose interface-health [-t <device>]           # interface RCA (worst-first)\nnetwork-aiops diagnose bgp [-t <device>]                        # BGP-neighbor RCA (worst-first)\nnetwork-aiops config backup [-t <device>] [-o <file>]\nnetwork-aiops config diff <file> [-t <device>] [--replace]\nnetwork-aiops config merge <file> [-t <device>] [--dry-run]      # double confirm\nnetwork-aiops config replace <file> [-t <device>] [--dry-run]    # HIGH RISK\nnetwork-aiops config rollback [-t <device>] [--dry-run]          # double confirm\nnetwork-aiops netbox list [--name <q>] [--limit N]\nnetwork-aiops netbox get <name>\nnetwork-aiops netbox interfaces <device> [--limit N]\nnetwork-aiops secret set|list|rm|migrate|rotate-password\nnetwork-aiops doctor\nnetwork-aiops mcp                                                # start MCP server (stdio)\n```\n\nSee `references/cli-reference.md` for the full command list.\n\n## Troubleshooting\n\n### \"Could not connect/authenticate to '<device>'\"\nThe host/port, username, or password is wrong, or the device is unreachable. Run `network-aiops doctor` — it reports whether the encrypted secret store is present, whether a password is stored for the device, and whether the device answers. Store/replace the password with `network-aiops secret set <device>` (or re-run `network-aiops init`). For enable/secret, set it in `optional_args.secret`.\n\n### \"Master password not set\" / cannot unlock secrets\nThe encrypted store needs the master password. Export `NETWORK_AIOPS_MASTER_PASSWORD` for non-interactive use (MCP server / cron), or run a CLI command on a TTY to be prompted. If you forgot it, delete `~/.network-aiops/secrets.enc` and re-run `network-aiops init`.\n\n### \"Operation not supported by the '<driver>' NAPALM driver\"\nThat getter or config mode is not implemented for this platform. Try a different getter, or fall back to `config_backup` and inspect the relevant stanza. Request the capability via a GitHub issue/PR.\n\n### \"Driver '<x>' is not in the officially supported set\"\nOnly `ios`, `nxos`, `nxos_ssh`, `iosxr`, `eos`, `junos` are tested here. Community drivers may work but are untested — request official support via a GitHub issue/PR.\n\n### NetBox commands fail with \"NetBox is not configured\"\nAdd a `netbox: {url: ...}` block to `config.yaml` and store the API token encrypted with `network-aiops secret set netbox-token` (or run `network-aiops init`). NetBox tools degrade gracefully when unconfigured.\n\n### `config replace` failed mid-commit\nThe device may not support full config replace (some Nexus images do not). Use `config merge` for additive changes, or restore from your `config backup` file.\n\n## Audit & Safety\n\nThe skill delivers reads and writes and records them; it does **not** decide whether a write is permitted. That is your agent's judgement, or the permission of the account you connect it with (log in with a device account at a read-only privilege level, and give NetBox a read-only API token — writes then fail at the server). There is no read-only switch, policy file, or approval gate.\n\n- **Audit is the guarantee, and it is not bypassable.** Every operation — MCP and CLI alike — is logged to `~/.network-aiops/audit.db` (relocatable via `NETWORK_AIOPS_HOME`): params, result, status, duration, and the risk tier. The CLI writes the same row the MCP path does.\n- `NETWORK_AUDIT_APPROVED_BY` / `NETWORK_AUDIT_RATIONALE` are optional annotations recorded on the audit row (who/why); they are never required and never block.\n- **Runaway guard** — a safety backstop, not authorization: the same call looped in a tight window trips a circuit breaker. Disable with `NETWORK_RUNAWAY_MAX=0`.\n- Undo store records inverse descriptors for reversible writes (config merge/replace → restore captured running config).\n- Writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI.\n\nThe harness is bundled in the package — no external dependency, no manual setup. See `references/setup-guide.md` for security details.\n\nDriving these tools with a smaller / local model? See `references/agent-guardrails.md` — which guardrails the harness now enforces for you, a ready-to-paste system prompt, and the network-specific traps (config merge vs replace, per-vendor interface naming, NetBox intent vs live device state).\n\n## Contributing — request a device or feature\n\nCoverage is intentionally focused. **Need a device (Nokia SR OS, Huawei VRP, …) or an action that isn't here yet?** Open an issue or pull request at [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops/issues) — feature requests, contributions, and comments are all welcome.\n\n## License\n\nMIT — [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)\n\nFile v0.12.2:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"network-aiops\",\n  \"version\": \"0.12.2\",\n  \"publishedAt\": 1789223573043\n}\n\nFile v0.12.2:references/agent-guardrails.md\n\n# Agent guardrails — running network-aiops with a smaller / local model\n\nIf you drive these tools with a local model (Llama, Qwen, Mistral … via Goose,\nOllama, LM Studio, or any OpenAI-compatible runtime), you will get noticeably\nbetter results with a short system prompt. This page gives you one, and — more\nimportantly — tells you which guardrails you **no longer need to write**, because\nthe tool now enforces them itself.\n\nThe distinction matters. A guardrail in a prompt is a request. A guardrail in the\nharness is a guarantee. Anything below that we could move into the harness, we did.\n\nNetwork gear raises the stakes: a bad merge on a core switch takes the management\nplane with it, and the model cannot SSH back in to fix what it broke.\n\n## What the tool now enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Don't invent a value when a field is missing\" | A field the driver did not return comes back as `null`, never as `\"\"`. This is the norm, not the exception, on a multi-vendor fleet: `serial_number`, `model`, an interface `description`, an LLDP neighbour's `hostname` are all optional and driver-dependent. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | The NetBox listings return `{\"devices\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}` (and `{\"interfaces\": ...}` likewise). Truncation is measured — one extra record is fetched — not guessed from a length coincidence. |\n| \"Preserve the ordering / tell me what's most urgent\" | `interface_health_rca` and `bgp_neighbor_rca` findings carry an explicit 1-based `rank`, worst-first, and each cites the measured number that tripped it (`rx_errors+tx_errors = 412 >= 100`). Priority is in the payload, not implied by list position. |\n| \"Show me the diff before you commit anything\" | `config_diff` is a real dry run: it stages a candidate, returns `compare_config()` output, then always discards. Nothing is committed, and the response carries `\"committed\": false`. |\n| \"Confirm before anything destructive\" | The CLI write paths (`config merge`/`replace`/`rollback`) require a double confirmation, and every write supports `--dry-run` / `dry_run=True` to preview first. `config_replace` is `high` risk, carried into the audit row as a `review` tier so it stands out in the trail. |\n| \"Keep a copy of the old config so we can go back\" | `config_merge` and `config_replace` read the running config **before** touching the device and return it as `backup`, and the harness records an undo descriptor that restores it via `config_replace`. The before-state is captured, not reconstructed. |\n| \"Log what you did\" | Every governed call is audited to `~/.network-aiops/audit.db` regardless of what the model says it did. |\n| \"Never show me passwords or SNMP communities\" | `get_users` returns `has_password` (a boolean) instead of the hash; `get_snmp_information` returns `community_count` instead of the community strings. The secrets are not in the payload to leak. |\n| \"Don't crash if this platform doesn't support that command\" | A getter a driver does not implement returns a teaching error naming the driver (\"not supported by the `iosxr` NAPALM driver\"), not a traceback. |\n\n## What still needs a prompt\n\nThese are model-behaviour problems the harness cannot fix from the outside.\nCopy this into your agent's system prompt:\n\n```text\nYou operate multi-vendor network devices (Cisco IOS / NX-OS / IOS-XR, Arista EOS,\nJuniper Junos) and an optional NetBox source of truth through the network-aiops\nMCP tools.\n\nTOOL USE\n- Before answering any question about the current state of the network, you MUST\n  call a tool. Never answer from memory or assumption.\n- Actually invoke the tool. Do not describe the call you would make, and do not\n  emit an example JSON response in place of calling it.\n- If a tool call fails, report the real error verbatim. Never fill the gap with\n  a plausible-sounding answer. \"Not supported by the <driver> driver\" means the\n  platform lacks that getter — say so; do not substitute a different getter and\n  present its output as the answer to the original question.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result contains a \"truncated\"\n  field that is true, say so and re-run with a higher limit instead of treating\n  the partial result as complete.\n- A null field means the driver did not return that value. Report it as \"not\n  available\" — never infer it.\n- Report identifiers EXACTLY as returned. Interface naming is vendor-specific:\n  GigabitEthernet0/1, Ethernet1, ge-0/0/0 and Te0/0/0/1 are literal device\n  strings, not styles to normalise. Never abbreviate Gi0/1 to 0/1, never expand\n  Et1 to Ethernet1, never convert between vendors' forms.\n- Do not normalise, translate, or prettify VRF names, BGP connection states,\n  route protocols, or VLAN names either.\n- When an RCA result has findings, work in \"rank\" order and cite the measured\n  number in each finding's \"detail\".\n\nCONFIG CHANGES\n- Always call config_diff first and show the operator the diff. Only after they\n  approve the exact diff may you call config_merge or config_replace.\n- config_merge is additive: it adds and modifies lines, it does not remove what\n  you left out. config_replace makes the device match the supplied config in\n  full — anything absent from your text is REMOVED, including the management\n  interface, AAA, and your own access. Never pass a partial config to\n  config_replace.\n- Never generate a full replacement config from scratch. Start from the output\n  of config_backup and edit that — but call it with `include_secrets=True`\n  for that purpose, or the `<redacted>` placeholders become literal\n  passwords on the device. Better still, take the backup with the CLI's\n  `-o <path>` and edit the file.\n- config_rollback reverts the last commit only, and rollback depth is\n  device-dependent — treat it as a single shot, not an undo history.\n- Never change more than one device per confirmed request.\n\nNETBOX VS THE DEVICE\n- NetBox describes intended state; the device reports actual state. When they\n  disagree, that IS the finding. Report both values side by side and label which\n  came from which. Do not silently reconcile them, and never edit a device to\n  match NetBox without the operator explicitly asking for exactly that.\n\nSCOPE\n- Separate observation from interpretation. State what the tools returned, then\n  any interpretation, clearly marked as such.\n- Do not assert a link, routing, or hardware problem unless a tool result\n  supports it.\n- Do not add generic advice that does not follow from the tool output.\n- Do not confuse a target name (the entry in config.yaml) with the device's own\n  hostname, an interface name with a VLAN id, or a BGP neighbor IP with an\n  interface address.\n```\n\n## Recommended setup for a local model\n\n```bash\nnetwork-aiops doctor\n```\n\nAuthorization is not this tool's job — decide it via the account or the agent's\nprompt, not a switch in the skill. The safest posture while you build trust is to\nconnect with a **device account that has read-only privileges** (and a read-only\nNetBox API token): a write then fails at the device itself, the place that\nactually owns the permission, no matter what the model attempts. When you are\nready to allow config changes, connect with an account that can write.\n\n`NETWORK_AUDIT_APPROVED_BY` / `NETWORK_AUDIT_RATIONALE` are optional annotations —\nthey record who asked for a change and why on the audit row, but they never block\na call:\n\n```bash\nexport NETWORK_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport NETWORK_AUDIT_RATIONALE=\"change window CHG-1234, 2026-07-20\"\n```\n\n## Platform notes worth knowing\n\n**Merge vs replace is the single most dangerous distinction here.** NAPALM stages\na *candidate* config and `compare_config()` shows the diff before anything is\napplied. `load_merge_candidate` (behind `config_merge`) is additive. Whereas\n`load_replace_candidate` (behind `config_replace`) makes the running config\n*equal* your text — every line you omitted is removed. On Junos this is a\n`load override`; on IOS-XR a `commit replace`; on EOS/IOS the driver synthesises\nit. A model that treats replace like merge will drop the management VRF and lock\nyou out. `config_replace` is `high` risk — recorded as a `review` tier in the\naudit trail for exactly this reason — and both writes return the pre-change\nrunning config as `backup`.\n\n**The commit / rollback path is device-dependent.** `commit_config()` applies the\ncandidate; `config_rollback` calls NAPALM's `rollback()`, which reverts the last\ncommit. Some platforms keep exactly one rollback point (IOS's archive-based\nimplementation is not a rollback stack the way Junos's `rollback 1..49` is).\nTreat rollback as one shot. The durable recovery path is the recorded undo\ndescriptor — it replays the captured `backup` through `config_replace`, which\nmeans the target must support config replace for the undo to apply.\n\n**Interface names are literal, per-vendor strings.** `GigabitEthernet0/1` (IOS),\n`Ethernet1` (EOS), `ge-0/0/0` (Junos), `TenGigE0/0/0/1` (IOS-XR). NAPALM\nnormalises the *schema*, not the *names*. Every tool returns names exactly as the\ndevice reports them, and every tool that takes one expects the same form back. A\nmodel that \"helpfully\" tidies `GigabitEthernet0/1` into `Gi0/1` will produce a\nconfig line the device rejects, or worse, one that silently creates a different\ninterface.\n\n**NetBox and the device will disagree, and that is signal.** `netbox_device_interfaces`\nreturns the intended inventory; `get_interfaces` returns what is actually\nconfigured and up. Drift is the whole point of asking both. Report both sides\nwith their sources named rather than picking a winner — the correct fix is\nsometimes to update NetBox, not the switch, and that is an operator's call.\nNote that the NetBox listings are paginated: check `truncated` before calling any\ninterface \"missing from source of truth\".\n\n**Not every getter exists on every platform.** `get_vlans`, `get_optics`,\n`get_environment` and `get_network_instances` in particular vary widely. An\nunsupported getter raises a teaching error naming the driver; that is a real\nanswer (\"this platform can't report it\"), not a failure to route around.\n\n## If your model still struggles\n\nSome behaviours are model-capacity limits rather than prompt problems:\n\n- **Multi-tool workflows time out or drift.** Prefer `interface_health_rca` and\n  `bgp_neighbor_rca` — they collect the interfaces, counters and neighbor state\n  and correlate them inside one call, so the model does not have to chain reads\n  and keep interface names straight across turns.\n- **The model ignores later tool results in a long context.** A full\n  `get_interfaces` on a chassis switch is hundreds of rows. Ask narrower\n  questions, and use `--limit` deliberately on the NetBox listings rather than\n  pulling whole inventories.\n- **The model edits config it was only asked to read.** Connect with a read-only\n  device account so writes fail at the device, and lean on `config_backup` +\n  `config_diff` (both reads); hand the diff to a human for the commit.\n- **The model describes calls instead of making them.** This is usually a\n  runtime/tool-calling-format mismatch, not a prompt problem — check that your\n  client advertises the tools in the format your model was trained on.\n\nFeedback on running this with a specific local model is genuinely useful —\nopen an issue at\n[github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops/issues)\nwith the model, runtime, driver, and what went wrong.\n\nFile v0.12.2:references/capabilities.md\n\n# network-aiops Capabilities\n\n33 MCP tools (28 read / 5 write). Every tool is wrapped with `@governed_tool`\n(audit + policy + budget + risk-tier; undo where a clean inverse exists). Returns\nare high-signal summaries — config blobs are sanitized and size-bounded. Secrets\nare never returned (user password hashes and SNMP community strings are redacted).\n\n## Read tools\n\n| Tool | Returns | Risk | Typical response tokens |\n|------|---------|:----:|:-----------------------:|\n| `device_facts` | hostname, vendor, model, os_version, serial, uptime, interface list | low | ~80–300 |\n| `get_interfaces` | per-interface up/enabled/speed/description/mac | low | ~60–800 |\n| `get_interfaces_counters` | per-interface octets/packets/errors/discards | low | ~60–800 |\n| `get_interfaces_ip` | per-interface IPv4/IPv6 + prefix length | low | ~40–400 |\n| `get_bgp_neighbors` | per-VRF peer, remote AS, up, prefix counts | low | ~60–600 |\n| `get_bgp_neighbors_detail` | + state, router id, local AS, advertised prefixes | low | ~80–900 |\n| `get_lldp_neighbors` | local port, remote host, remote port | low | ~40–400 |\n| `get_lldp_neighbors_detail` | + chassis id, system desc, capabilities | low | ~60–700 |\n| `get_arp_table` | interface, IP, MAC, age | low | ~50–700 |\n| `get_mac_address_table` | MAC, interface, VLAN, static/active | low | ~50–900 |\n| `get_vlans` | id, name, member interfaces | low | ~40–500 |\n| `get_route_to` | per-prefix protocol, next hop, outgoing interface | low | ~40–500 |\n| `get_environment` | fans, temperature, power, CPU, memory | low | ~60–500 |\n| `get_optics` | per-interface rx/tx power, laser bias | low | ~40–400 |\n| `get_ntp_servers` | configured NTP servers | low | ~20–120 |\n| `get_ntp_stats` | per-peer stratum, offset, jitter, reachability | low | ~40–300 |\n| `get_users` | username, level, has_password (hash redacted) | low | ~30–200 |\n| `get_snmp_information` | chassis id, contact, location, community_count | low | ~40 |\n| `get_network_instances` | VRFs: name, type, RD, interfaces | low | ~40–400 |\n| `device_health` | facts + interface up/down + environment + issues | low | ~120–400 |\n| `interface_health_rca` | worst-first findings: down / error / discard / flap, each cited | low | ~80–600 |\n| `bgp_neighbor_rca` | worst-first findings: down / shut / reset / route-less, each cited | low | ~60–500 |\n| `config_backup` | running config, credential values masked (`include_secrets=True` for raw) | low | ~500–8000 |\n| `config_diff` | candidate diff, credential values masked (dry-run, never committed) | low | ~30–1500 |\n| `netbox_list_devices` | `{devices, returned, limit, truncated}` — name, role, site, status, primary IP | low | ~40–500 |\n| `netbox_get_device` | + device_type, serial | low | ~80 |\n| `netbox_device_interfaces` | `{interfaces, returned, limit, truncated}` — name, type, enabled, description | low | ~40–600 |\n| `undo_list` | recorded, not-yet-applied reversible writes (undoId, original/inverse tool, note) | low | ~40–400 |\n\n> **Optional fields are `null`, not `\"\"`.** Any value the driver or NetBox did\n> not return (`serial_number`, `model`, an interface `description`, an LLDP\n> `remote_host`, a NetBox `site`) comes back as JSON `null`. An empty string\n> means the field genuinely is empty. Never infer a value from `null`.\n\n> **Truncation is measured.** The two NetBox listings return an envelope with\n> `truncated`; one extra record is fetched to determine it. When `truncated` is\n> true, re-run with a higher `limit` before drawing any conclusion about\n> coverage or drift.\n\n## Write tools\n\n| Tool | Effect | Risk | Undo |\n|------|--------|:----:|------|\n| `config_merge` | merge snippet + commit under a revert timer | medium | `config_replace` back to captured running config |\n| `config_replace` | replace full config + commit under a revert timer | **high** | `config_replace` back to captured running config |\n| `confirm_commit` | confirm a pending commit-confirm, cancelling its revert timer | medium | none (doing nothing lets the device revert) |\n| `config_rollback` | revert last commit | medium | none (already a revert) |\n| `undo_apply` | execute a recorded inverse descriptor — itself governed, single-use, supports `dry_run` | medium | none (is the undo) |\n\n## Per-driver support notes\n\n| Getter / op | ios | nxos / nxos_ssh | iosxr | eos | junos |\n|-------------|:---:|:---------------:|:-----:|:---:|:-----:|\n| `get_facts` / `get_interfaces` / `get_interfaces_ip` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_bgp_neighbors` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_lldp_neighbors` / `get_arp_table` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_interfaces_counters` / `get_mac_address_table` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_bgp_neighbors_detail` | ✓ | varies | ✓ | ✓ | ✓ |\n| `get_environment` / `get_ntp_*` / `get_users` / `get_snmp_information` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_vlans` / `get_network_instances` | varies | ✓ | ✓ | ✓ | ✓ |\n| `get_optics` | varies | varies | ✓ | ✓ | ✓ |\n| `get_route_to` | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `get_config` (backup) | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `load_merge_candidate` + `compare_config` (diff/merge) | ✓ | ✓ | ✓ | ✓ | ✓ |\n| `load_replace_candidate` (replace) | ✓ | varies | ✓ | ✓ | ✓ |\n| `rollback` | ✓ (archive) | varies | ✓ | ✓ | ✓ |\n\nA getter that a given driver does not implement raises `NotImplementedError`,\nwhich the ops layer turns into a teaching `NetworkApiError` (\"not supported by\nthe `<driver>` driver\").\n\n## Token-budget notes\n\n- `config_backup` can be large; prefer `config_diff` to preview a change instead\n  of re-fetching the whole config repeatedly.\n- The runaway guard trips on tight poll loops — wait between repeated reads.\n\n## Design notes / NAPALM assumptions\n\n- NAPALM connections are short-lived: each tool opens a driver, runs its\n  getters/config calls, and closes it. Nothing is cached across calls.\n- Device passwords and the NetBox token come from the encrypted store\n  `~/.network-aiops/secrets.enc` (unlocked by `NETWORK_AIOPS_MASTER_PASSWORD`;\n  legacy plaintext env vars are a deprecated fallback). Enable/secret and\n  transport go in `optional_args` and are passed verbatim to NAPALM. The skill\n  never logs, echoes, or returns the credential.\n- Connection / command / driver errors are translated centrally at the connection\n  layer into a teaching `NetworkApiError`, so agents see actionable messages.\n- Only the five core drivers are validated here; community drivers are untested.\n\n## Commit-confirm (the guard for a change that can lock you out)\n\n`config_merge` / `config_replace` call NAPALM's `commit_config(revert_in=N)`\n(default 300s). The **device** reverts the change on its own unless\n`confirm_commit` arrives first. This matters because the recorded undo is a\n`config_replace` that must open a NEW session to the same device — a commit that\nshuts the management interface, tightens the VTY ACL or breaks AAA kills exactly\nthat path, so an undo token is not a guard against lockout. A device-enforced\ntimer is.\n\nWorkflow: **commit (timer armed) → verify reachability from a NEW session →\n`confirm_commit`**. Doing nothing is the safe branch.\n\nThe result's `commit` block reports what actually happened:\n\n| `commit.safetyNet` | Meaning |\n|---|---|\n| `commit-confirm` | timer armed; the change reverts in `commit.revertInSeconds` unless confirmed |\n| `undo-only` | **no timer** — the driver refused one or `revert_in=0` was passed. The change is permanent on landing; `commit.warning` says so. Arrange out-of-band access before making lockout-capable changes on such a device. |\n\nA write with **neither** a timer nor a usable captured backup is refused\noutright (`UnreversibleCommit`) before anything is committed.\n\n### Backups are digested, not echoed\n\n`config_merge` / `config_replace` return `backup` as `{bytes, sha256,\nretainedForUndo}` — not the config body. A running config carries credential\nhashes, SNMP communities, PSKs and RADIUS keys, and a tool result lands in the\nagent transcript. The byte-exact raw text is kept only in `undo.db` (0600) for\nthe rollback. Use `config_backup` when you deliberately want the text.\n\n### Credential values are masked, and the masking is reported\n\n`config_backup` cannot withhold the config — returning it IS the tool's\ncontract — so it masks credential VALUES instead: password/secret hashes, SNMP\ncommunities, SNMPv3 auth/priv material, IKE pre-shared keys, RADIUS/TACACS and\nkeychain keys become `<redacted>`. Every other line is byte-for-byte what the\ndevice said. The same applies to every `diff`, because a diff that adds\n`snmp-server community X` contains X.\n\nEach result carries a `redaction` block (`applied`, `linesRedacted`, `note`) so\nthe transformation is never silent. `include_secrets=True` returns the verbatim\ntext, and the CLI's `-o <path>` writes raw to a file the operator named.\n\n**Limit**: this is pattern matching over five vendor syntaxes. It REDUCES\nexposure; it does not guarantee the text is credential-free. Line-oriented\nrules cannot see multi-line PKI key blocks. Do not describe redacted output as\n\"safe to share\".\n\n### `dry_run` does not bypass the guard\n\n`config_merge(dry_run=True)` / `config_replace(dry_run=True)` (and the CLI's\n`--dry-run`) stage the candidate, return the diff, discard it, and run the SAME\n`UnreversibleCommit` refusal the real commit would — a green preview is never\nfollowed by a refusal a model would read as transient and retry.\n\nThe CLI's `--dry-run` on `config merge` / `config replace` routes through the\nsame governed twin, so it reaches the same guard **and** records the same audit\nrow. The line's invariant is: **a dry_run MAY read; it must never write.** A\npreview that cannot read cannot answer \"would this be refused?\", so reads are\nexpected; the mutating call is the thing that must never happen.\n\n(`config rollback` and `config confirm` have no `dry_run` parameter — there is no\ngoverned preview to route through, so their `--dry-run` short-circuits\nclient-side and records nothing.)\n\nOne asymmetry is deliberate and safe in the right direction: the preview can only\n*predict* commit-confirm support from the driver's `commit_config` signature,\nwhereas the real write also learns from a `NotImplementedError` raised at commit\ntime. So the preview's refusal condition is a strict **subset** of the write's —\nit never refuses something the write would allow. The preview reports its\nprediction as `commit.wouldArmTimer` / `commit.safetyNet`.\n\nFile v0.12.2:references/cli-reference.md\n\n# network-aiops CLI Reference\n\nAll commands accept `-t/--target <name>` to select a configured device. When\nomitted, the first device in `~/.network-aiops/config.yaml` is used.\n\n## Onboarding & secrets\n\n```bash\nnetwork-aiops init                              # interactive wizard: devices + encrypted passwords (+ NetBox)\nnetwork-aiops secret set <name>                 # store/replace a device password, or 'netbox-token' (hidden prompt)\nnetwork-aiops secret list                       # names only — values are never printed\nnetwork-aiops secret rm <name>                  # delete a stored secret\nnetwork-aiops secret migrate                    # import a legacy plaintext .env into the encrypted store\nnetwork-aiops secret rotate-password            # re-encrypt the store under a new master password\n```\n\nSecrets are stored encrypted in `~/.network-aiops/secrets.enc`. Unlock\nnon-interactively with `NETWORK_AIOPS_MASTER_PASSWORD`.\n\n## Device facts & state (read-only)\n\n```bash\nnetwork-aiops device facts [-t <device>]        # hostname, vendor, model, OS, serial, uptime\nnetwork-aiops device interfaces [-t <device>]   # up/down, enabled, speed, description\nnetwork-aiops device counters [-t <device>]     # per-interface traffic + error counters\nnetwork-aiops device bgp [-t <device>]          # BGP neighbors per VRF\nnetwork-aiops device lldp [-t <device>]         # LLDP neighbors\nnetwork-aiops device arp [-t <device>]          # ARP table\nnetwork-aiops device mac [-t <device>]          # MAC address table\nnetwork-aiops device vlans [-t <device>]        # VLANs (id, name, member count)\nnetwork-aiops device route <prefix> [-t <device>] [--protocol bgp]  # routing-table lookup\nnetwork-aiops device environment [-t <device>]  # fans, temperature, power, CPU, memory\nnetwork-aiops device health [-t <device>]       # aggregated health summary\n```\n\nAdditional read getters are exposed as MCP tools (no dedicated CLI subcommand):\n`get_bgp_neighbors_detail`, `get_lldp_neighbors_detail`, `get_optics`,\n`get_ntp_servers`, `get_ntp_stats`, `get_users`, `get_snmp_information`,\n`get_network_instances`. A getter a driver does not implement returns a teaching\n\"not supported by the `<driver>` driver\" error.\n\n## Configuration\n\n```bash\nnetwork-aiops config backup [-t <device>] [-o <file>]      # running config (save with -o)\nnetwork-aiops config diff <file> [-t <device>] [--replace] # DRY-RUN: show the diff only\nnetwork-aiops config merge <file> [-t <device>] [--dry-run] [--revert-in N]   # commit; double confirm\nnetwork-aiops config replace <file> [-t <device>] [--dry-run] [--revert-in N] # HIGH RISK; double confirm\nnetwork-aiops config confirm [-t <device>] [--dry-run]         # confirm a pending commit\nnetwork-aiops config rollback [-t <device>] [--dry-run]        # revert last commit; double confirm\n```\n\n- `config diff` stages a candidate, runs `compare_config()`, and discards it —\n  nothing is committed. `--replace` diffs as a full-config replacement.\n- `--dry-run` on `merge` / `replace` prints the same diff without committing.\n- `merge` / `replace` capture the pre-change running config for the undo store.\n- `merge` / `replace` commit under a **device-side revert timer**\n  (`--revert-in`, default 300s): the device undoes the change by itself unless\n  `config confirm` follows. Use it for anything that could sever your own\n  management path — it is the only guard that works when you cannot reach the\n  device any more. `--revert-in 0` disables it (undo-only).\n- After committing, re-connect in a **new** session, verify, then\n  `network-aiops config confirm`. If a driver cannot arm a timer the command\n  prints a red `NO COMMIT-CONFIRM SAFETY NET` warning.\n\n## NetBox (optional source-of-truth)\n\n```bash\nnetwork-aiops netbox list [--name <q>] [--limit N]   # name, role, site, status, primary IP\nnetwork-aiops netbox get <name>                      # single device by exact name\nnetwork-aiops netbox interfaces <device> [--limit N] # device interfaces from source-of-truth\n```\n\nRequires a `netbox:` block in config and an encrypted `netbox-token` secret\n(`network-aiops secret set netbox-token`, or via `network-aiops init`).\n\n## Diagnostics & MCP\n\n```bash\nnetwork-aiops doctor [--skip-auth]   # check config + encrypted secret store + per-device password + reachability\nnetwork-aiops mcp                    # start the MCP server over stdio\n```\n\n## Flags summary\n\n| Flag | Meaning |\n|------|---------|\n| `-t, --target` | Device name from `~/.network-aiops/config.yaml` |\n| `-o, --output` | Write `config backup` output to a file |\n| `--replace` | Diff/treat the config file as a full replacement (`config diff`) |\n| `--dry-run` | Preview a destructive config op as a diff without committing |\n| `--protocol` | Filter `device route` by routing protocol (bgp, ospf, …) |\n| `--name` | NetBox name filter (`netbox list`) |\n| `--limit` | NetBox page size (`netbox list` / `netbox interfaces`) |\n| `--skip-auth` | Skip the connectivity check in `doctor` |\n\nFile v0.12.2:references/setup-guide.md\n\n# network-aiops Setup Guide\n\n## Install\n\n```bash\nuv tool install network-aiops\nnetwork-aiops init      # interactive onboarding wizard (recommended)\nnetwork-aiops doctor\n```\n\n`network-aiops` requires Python ≥ 3.11. If `uv` picked an older interpreter:\n\n```bash\nuv python install 3.12\nuv tool install --python 3.12 --force network-aiops\n```\n\n## Configure devices\n\nCreate `~/.network-aiops/config.yaml`:\n\n```yaml\ndevices:\n  - name: core-sw1            # used as -t core-sw1\n    driver: eos               # ios | nxos | nxos_ssh | iosxr | eos | junos\n    host: 10.0.0.1\n    username: admin\n    optional_args:            # passed verbatim to NAPALM (optional)\n      secret: enable-pw       # enable/secret\n      port: 443\n  - name: edge-rtr\n    driver: ios\n    host: 10.0.0.254\n    username: netops\n# Optional source-of-truth:\nnetbox:\n  url: https://netbox.example.com\n```\n\n### Secrets — encrypted store (never in config.yaml)\n\nSecrets are stored **encrypted** in `~/.network-aiops/secrets.enc` (Fernet/AES +\nscrypt-derived key; chmod 600) — never in config.yaml or a plaintext `.env`.\nDevice login passwords are keyed by the device name; the NetBox API token uses\nthe reserved name `netbox-token`. The fastest path is `network-aiops init`, or\nset them individually:\n\n```bash\nnetwork-aiops secret set core-sw1       # hidden prompt for the device password\nnetwork-aiops secret set edge-rtr\nnetwork-aiops secret set netbox-token   # the NetBox API token\nnetwork-aiops secret list               # names only — values are never printed\n```\n\nUnlock the store non-interactively by exporting the master password (used by the\nMCP server, cron, CI):\n\n```bash\nexport NETWORK_AIOPS_MASTER_PASSWORD='your-master-password'\nchmod 700 ~/.network-aiops\n```\n\n**Migrating from a legacy plaintext `.env`** (`NETWORK_<TARGET_UPPER>_PASSWORD`,\n`NETWORK_NETBOX_TOKEN`): run `network-aiops secret migrate` to import them into\nthe encrypted store (the old file is renamed to `.env.migrated`; delete it once\nverified). Those env vars still work as a deprecated fallback with a warning. An\nempty device password is allowed for key-based SSH auth.\n\n### Supported drivers\n\n`ios` (Cisco IOS/IOS-XE), `nxos` / `nxos_ssh` (Cisco Nexus NX-OS), `iosxr`\n(Cisco IOS-XR), `eos` (Arista EOS), `junos` (Juniper Junos). Other platforms\n(Nokia SR OS / SR Linux, Huawei VRP, …) are reachable via NAPALM community\ndrivers but are untested here — request official support via a GitHub issue/PR.\n\n## Security\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox Labs, or any network vendor.** Vendor and product names are trademarks of their respective owners. Source is auditable at [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops) under the MIT license.\n\n1. **Source code** — [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops), MIT.\n2. **Config file contents** — `config.yaml` holds only device names, drivers,\n   hosts, usernames, and NAPALM `optional_args`. No credentials.\n3. **Credentials** — device passwords and the NetBox token live in the encrypted\n   store `~/.network-aiops/secrets.enc` (Fernet/AES, scrypt-derived key, chmod\n   600), unlocked by `NETWORK_AIOPS_MASTER_PASSWORD`; never read back, logged, or\n   echoed. Legacy plaintext env vars remain a deprecated fallback. Keep the dir\n   chmod 700.\n4. **TLS verification** — NAPALM transports (eAPI/NX-API HTTPS, NETCONF/SSH)\n   follow each device's own certificate / SSH host-key configuration; the skill\n   does not weaken it.\n5. **Prompt-injection protection** — all device-returned text (facts, configs,\n   diffs, neighbor data) is run through `sanitize()` (truncation + control-char\n   stripping).\n6. **Least privilege** — use a device account with only the privilege you need:\n   a read-only login for facts/backup, and a config-capable login only for the\n   merge/replace/rollback tools.\n\n## Governance harness\n\nBundled under `network_aiops.governance` — no external dependency. State lives\nunder `~/.network-aiops/` (override with `NETWORK_AIOPS_HOME`):\n\n- `audit.db` — every tool call (skill, tool, params, status, duration, agent).\n- Token/runaway budget guard (`NETWORK_MAX_TOOL_CALLS`, `NETWORK_MAX_TOOL_SECONDS`,\n  `NETWORK_RUNAWAY_MAX`, `NETWORK_RUNAWAY_WINDOW_SEC`).\n- Undo store — inverse descriptors for reversible writes (config merge/replace).\n- Encrypted secret store (`secrets.enc`) — device passwords + NetBox token,\n  unlocked by `NETWORK_AIOPS_MASTER_PASSWORD`.\n- Accountability (optional): set `NETWORK_AUDIT_APPROVED_BY` /\n  `NETWORK_AUDIT_RATIONALE` to annotate the audit row with who asked for a change\n  and why. They are optional and never block a call — the skill does not authorize\n  operations; that is the agent's judgement or the connecting account's privilege.\n\n## MCP client config\n\n```jsonc\n{\n  \"command\": \"network-aiops\",\n  \"args\": [\"mcp\"],\n  \"env\": {\n    \"NETWORK_AIOPS_CONFIG\": \"~/.network-aiops/config.yaml\",\n    \"NETWORK_AIOPS_MASTER_PASSWORD\": \"…\"\n  }\n}\n```\n\nFallback (no `uv tool install`): `uvx --from network-aiops network-aiops-mcp`.\nPrefer the installed entry point — it does not re-resolve PyPI at launch.\n\n## Static analysis\n\n```bash\nuvx bandit -r network_aiops/ mcp_server/\n```\n\nFile v0.12.2:skill-card.md\n\n## Description:\n\nNetwork AIops helps agents inspect, diagnose, back up, diff, merge, replace, and roll back configurations on NAPALM-supported network devices, with optional NetBox lookups and governed audit/undo controls.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[zw008](https://clawhub.ai/user/zw008)\n\n### License/Terms of Use:\n\nMIT\n\n## Use Case:\n\nDevelopers and network engineers use this skill to query multi-vendor device state, run read-only RCA, compare intended changes, and perform governed configuration changes on Cisco IOS/IOS-XE, Nexus NX-OS, IOS-XR, Arista EOS, and Juniper Junos devices.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill grants high-impact access to network devices and can affect production infrastructure.\n\nMitigation: Install only in a controlled network-operations environment, pin the package version, and use read-only device and NetBox accounts by default.\n\nRisk: Credential and approval handling can be under-scoped when the master password or raw secret output is exposed to model-visible tools.\n\nMitigation: Avoid putting the master password in shell profiles or MCP config, do not use include_secrets=True through model-visible tools, and keep enable secrets out of config.yaml.\n\n## Reference(s):\n\n- [Network AIops source repository](https://github.com/AIops-tools/Network-AIops)\n- [Network AIops ClawHub page](https://clawhub.ai/zw008/skills/network-aiops)\n- [Capabilities](references/capabilities.md)\n- [Agent Guardrails](references/agent-guardrails.md)\n- [CLI Reference](references/cli-reference.md)\n- [Setup Guide](references/setup-guide.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown with inline commands, configuration snippets, diffs, and structured tool-result guidance]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Agent output may include network state summaries, RCA findings, dry-run diffs, backup guidance, and explicit operator approval steps for writes.]\n\n## Skill Version(s):\n\n0.12.2 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.12.1: 7 files, 25880 bytes\n\nFiles: references/agent-guardrails.md (11690b), references/capabilities.md (10561b), references/cli-reference.md (4989b), references/setup-guide.md (5363b), skill-card.md (2556b), SKILL.md (24461b), _meta.json (133b)\n\nFile v0.12.1:SKILL.md\n\n---\nname: network-aiops\nslug: network-aiops\ndisplayName: \"Network AIops\"\nsummary: \"Governed network device ops (NAPALM) — 33 MCP tools with audit/undo.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Network-AIops\ntags: [aiops, mcp, governance, network]\ndescription: >\n  Use this skill whenever the user needs to operate a network device — read device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary and detail), ARP/MAC tables, VLANs, routes, hardware environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, and an aggregated device-health summary; run read-only RCA diagnostics on interface health and BGP neighbors; back up a switch/router config, diff a candidate config (dry-run), and merge/replace/rollback config — across Cisco IOS/IOS-XE, Nexus NX-OS, IOS-XR, Arista EOS, and Juniper Junos via NAPALM. An optional NetBox block adds source-of-truth lookups.\n  Always use this skill for \"back up switch config\", \"show bgp neighbors\", \"diff network config\", \"push config to router\", \"show interfaces on the switch\", or tasks mentioning \"cisco\", \"arista\", \"juniper\", \"nexus\", \"ios-xr\", or \"napalm\".\n  Do NOT use when the target is not a NAPALM-supported network device (Kubernetes clusters, hypervisor VMs, and cloud consoles are out of scope — route those elsewhere).\n  Common multi-vendor device operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\ninstaller:\n  kind: uv\n  package: network-aiops\nargument-hint: \"[device name or describe your network task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"network-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"NETWORK_AIOPS_CONFIG\",\"NETWORK_AIOPS_HOME\",\"NETWORK_AIOPS_MASTER_PASSWORD\",\"NETWORK_NETBOX_TOKEN\"]},\"homepage\":\"https://github.com/AIops-tools/Network-AIops\",\"emoji\":\"🛜\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed network device operations over NAPALM. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency.\n  All write operations are audited to a local SQLite DB under ~/.network-aiops/ (relocatable via NETWORK_AIOPS_HOME).\n  Credentials: device login passwords AND the optional NetBox API token live in an ENCRYPTED store at ~/.network-aiops/secrets.enc (Fernet/AES + scrypt-derived key; chmod 600), never in plaintext. Device passwords are keyed by the device name; the NetBox token uses the reserved name \"netbox-token\". Unlock with the NETWORK_AIOPS_MASTER_PASSWORD env var (for the MCP server / non-interactive use) or an interactive prompt. Run `network-aiops init` (wizard) or `network-aiops secret set <name>` to populate it, and `network-aiops secret migrate` to import a legacy plaintext .env (NETWORK_<TARGET_UPPER>_PASSWORD / NETWORK_NETBOX_TOKEN are still honoured as a deprecated fallback). config.yaml holds only device names, drivers, hosts, usernames, and NAPALM optional_args — never secrets. The state dir ~/.network-aiops should be chmod 700.\n  Destructive operations (config merge, config replace, config rollback) require double confirmation at the CLI layer and support --dry-run (which prints the diff without committing). All write tools pass through the @governed_tool decorator (budget guard + audit + risk-tier tagging). config_merge and config_replace capture the pre-change running config and record an inverse config_replace-to-backup undo descriptor; config_rollback records none, and config_replace is risk_level=high.\n  Webhooks: none — no outbound network calls beyond the configured device sessions and the optional NetBox API.\n  TLS: NAPALM driver transports (eAPI/NX-API HTTPS, NETCONF/SSH) follow the device's own certificate/SSH host-key settings; the skill does not weaken them.\n  Transitive dependencies: napalm (device drivers), pynetbox (optional source-of-truth), typer/rich (CLI), pyyaml/python-dotenv (config), and the MCP SDK. No post-install scripts or background services.\n---\n\n# Network AIops\n\n> **Disclaimer**: This is a community-maintained open-source project and is **not affiliated with, endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox Labs, or any network vendor.** Vendor and product names are trademarks of their respective owners. Source code is publicly auditable at [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops) under the MIT license.\n\nGoverned multi-vendor network device operations — **33 MCP tools**, every one wrapped with the bundled `@governed_tool` harness: a local unified audit log under `~/.network-aiops/`, token/runaway budget guard, undo-token recording, and descriptive risk-tier labels. Devices are reached over NAPALM; an optional NetBox block adds source-of-truth lookups. Secrets (device passwords + NetBox token) are kept in an **encrypted store** (`secrets.enc`), unlocked by `NETWORK_AIOPS_MASTER_PASSWORD`.\n\n> **Standalone**: the governance harness is bundled in the package (`network_aiops.governance`) — network-aiops has no external skill-family dependency. Coverage focuses on common operations and is not yet exhaustive.\n\n## What This Skill Does\n\n| Category | Tools | Count | Read or Write |\n|----------|-------|:-----:|:-------------:|\n| **Device facts** | facts, interfaces, interface counters, interface IPs, BGP (+detail), LLDP (+detail), ARP | 9 | 9 read |\n| **Inventory** | MAC table, VLANs, route lookup | 3 | 3 read |\n| **Platform / env** | environment, optics, NTP servers, NTP stats, users, SNMP info, VRFs, device_health | 8 | 8 read |\n| **Diagnostics / RCA** | interface_health_rca, bgp_neighbor_rca | 2 | 2 read |\n| **Config** | backup, diff (dry-run), merge, replace, rollback | 5 | 2 read / 3 write |\n| **NetBox** | list devices, get device, device interfaces | 3 | 3 read |\n| **Undo** | undo_list, undo_apply | 2 | 1 read / 1 write |\n\n## Quick Install\n\n```bash\nuv tool install network-aiops\nnetwork-aiops init            # interactive wizard: device + driver + host + encrypted password (+ optional NetBox)\nnetwork-aiops doctor          # checks config, encrypted secret store, and per-device password presence\n```\n\nOr as an OpenClaw plugin, which installs this skill and its MCP server together:\n\n```bash\nopenclaw plugins install clawhub:@aiops-tools/network-aiops\nopenclaw skills info network-aiops          # expect: Visible to model: yes\n```\n\nNeeds `uvx` on `PATH`: the MCP server is fetched with uv, pinned to this release.\n\n`init` writes `~/.network-aiops/config.yaml` and stores secrets **encrypted** in `~/.network-aiops/secrets.enc`. Export `NETWORK_AIOPS_MASTER_PASSWORD` in your shell profile so the CLI and MCP server can unlock secrets non-interactively.\n\n## Supported Devices\n\n| Platform | NAPALM driver | Transport |\n|----------|---------------|-----------|\n| Cisco IOS / IOS-XE | `ios` | SSH |\n| Cisco Nexus NX-OS | `nxos` (NX-API) / `nxos_ssh` (SSH) | HTTPS / SSH |\n| Cisco IOS-XR | `iosxr` | SSH (XML agent) |\n| Arista EOS | `eos` | eAPI (HTTPS) |\n| Juniper Junos | `junos` | NETCONF (SSH) |\n\nOther platforms (Nokia SR OS / SR Linux, Huawei VRP, etc.) are reachable via NAPALM **community drivers** but are **not officially tested here** — see [Contributing](#contributing--request-a-device-or-feature).\n\n## When to Use This Skill\n\n- Inspect device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary + detail), ARP/MAC tables, VLANs, and route lookups\n- Check hardware health: environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, or a one-shot `device_health` summary\n- Root-cause a problem with read-only RCA: `interface_health_rca` (down/erroring/discarding/flapping ports) and `bgp_neighbor_rca` (down/shut/recently-reset/route-less peers) — each finding cites the measured number that tripped it, worst-first\n- Back up a switch/router running config to a file\n- Dry-run a config change as a diff before committing\n- Merge a config snippet, replace the full config, or roll back the last commit\n- Cross-check intended state in NetBox before pushing a change\n\n**Do NOT use when** the target is not a NAPALM-supported network device (Kubernetes clusters, hypervisor VMs, and cloud-provider consoles are out of scope for this skill).\n\n## Related Skills — Skill Routing\n\n| If the user wants… | Use |\n|--------------------|-----|\n| Network device config / facts (Cisco/Arista/Juniper) | **network-aiops** (this skill) |\n| Kubernetes cluster operations | a cluster ops skill |\n| Hypervisor VM lifecycle (power, snapshot, migrate) | a hypervisor ops skill |\n\n## Supported Actions\n\n| Tool | R/W | Risk | Driver support |\n|------|:---:|:----:|----------------|\n| `device_facts` | R | low | all 5 |\n| `get_interfaces` | R | low | all 5 |\n| `get_interfaces_counters` | R | low | all 5 |\n| `get_interfaces_ip` | R | low | all 5 |\n| `get_bgp_neighbors` | R | low | all 5 (varies by feature) |\n| `get_bgp_neighbors_detail` | R | low | ios/eos/junos/iosxr; nxos varies |\n| `get_lldp_neighbors` | R | low | all 5 |\n| `get_lldp_neighbors_detail` | R | low | all 5 |\n| `get_arp_table` | R | low | all 5 |\n| `get_mac_address_table` | R | low | all 5 (varies by image) |\n| `get_vlans` | R | low | eos/junos/nxos; ios varies |\n| `get_route_to` | R | low | all 5 (varies by feature) |\n| `get_environment` | R | low | all 5 (sensor coverage varies) |\n| `get_optics` | R | low | eos/junos/iosxr; ios/nxos varies |\n| `get_ntp_servers` | R | low | all 5 |\n| `get_ntp_stats` | R | low | all 5 |\n| `get_users` | R | low | all 5 (password hashes redacted) |\n| `get_snmp_information` | R | low | all 5 (community strings redacted) |\n| `get_network_instances` | R | low | eos/junos/iosxr; ios/nxos varies |\n| `device_health` | R | low | all 5 (environment section optional) |\n| `interface_health_rca` | R | low | all 5 (needs get_interfaces + counters) |\n| `bgp_neighbor_rca` | R | low | all 5 (varies by BGP feature) |\n| `config_backup` | R | low | all 5 |\n| `config_diff` (dry-run) | R | low | all 5 |\n| `config_merge` | W | medium | all 5 |\n| `config_replace` | W | **high** | ios/eos/junos/iosxr; nxos varies |\n| `config_rollback` | W | medium | device-dependent rollback depth |\n| `netbox_list_devices` | R | low | NetBox (optional) |\n| `netbox_get_device` | R | low | NetBox (optional) |\n| `netbox_device_interfaces` | R | low | NetBox (optional) |\n\n**Per-driver caveat**: NAPALM does not implement every getter on every platform. Any unsupported getter returns a teaching error (\"not supported by the `<driver>` driver\") instead of crashing — try a different getter or fall back to `config_backup`. `device_health` is resilient: if a driver lacks `get_environment` that section is reported as a note, not a failure.\n\n**Credentials**: `get_users` reduces password hashes to a boolean and `get_snmp_information` reduces community strings to a count — those two never return secrets at all. `config_backup` and every returned `diff` *mask* credential values (password/secret hashes, SNMP communities, pre-shared keys, RADIUS/TACACS and keychain keys) and report how many lines they changed in a `redaction` block; `include_secrets=True` returns the verbatim text. The masking is pattern-based across five vendor syntaxes, so it reduces exposure rather than guaranteeing none remains — notably it cannot see multi-line PKI key blocks. To hand a real config to a human, prefer the CLI's `-o <path>`, which writes raw to a file instead of into this transcript.\n\n## Common Workflows\n\n### Safely change a device config with a dry-run first\n\n1. `network-aiops config backup -t core-sw1 -o core-sw1.cfg` → keep a known-good copy\n2. `network-aiops config diff change.cfg -t core-sw1` → preview the diff (nothing committed)\n3. `network-aiops config merge change.cfg -t core-sw1` (double confirm) → commits **under a 300s device-side revert timer**; the harness also records a `config_replace`-to-backup undo descriptor\n4. `network-aiops device interfaces -t core-sw1` → verify the result **and that you can still reach the device**\n5. `network-aiops config confirm -t core-sw1` → cancels the revert timer, making the change permanent. If you skip this (or get locked out), the device reverts by itself — that is the point\n6. **Failure branch**: if the connection fails (`Could not connect/authenticate`), run `network-aiops doctor` — it shows whether `NETWORK_CORE_SW1_PASSWORD` is set and whether the host/port is reachable; the skill never retries a denied auth.\n\n### Change something that could lock you out (mgmt interface, VTY ACL, AAA)\n\n1. `network-aiops config backup -t core-sw1 -o core-sw1.cfg` → an off-box copy, independent of the tool\n2. `network-aiops config diff risky.cfg -t core-sw1` → confirm the diff touches only what you intend\n3. `network-aiops config merge risky.cfg -t core-sw1 --revert-in 120` → short timer: if the change severs your session, the device restores itself in 2 minutes with nobody logged in\n4. Re-connect and verify. **Do not confirm from a session opened before the commit** — it may survive a change that blocks *new* logins\n5. `network-aiops config confirm -t core-sw1` → only once a NEW session proves the path still works\n6. **Failure branch**: if the result carries `commit.warning` with `safetyNet: \"undo-only\"`, this driver could not arm a timer. The change is permanent on landing and the recorded undo needs a working session — arrange out-of-band access (console/OOB mgmt) before you commit anything of this kind.\n\n### Root-cause a flaky uplink / peering problem (RCA-first)\n\n1. `network-aiops diagnose interface-health -t edge-rtr` → worst-first interface findings; a link that is admin-up/oper-down with climbing `rx_errors+tx_errors` and a recent `last_flapped` is a physical-layer fault (cable/optic), each cited with its measured value\n2. `network-aiops diagnose bgp -t edge-rtr` → worst-first neighbor findings; if the peer riding that link shows `BGP session down` or `recently reset` (low uptime), the L1 fault — not routing — is resetting the session\n3. `network-aiops device counters -t edge-rtr` → confirm the error counters are still climbing before you touch anything\n4. `network-aiops config diff fix.cfg -t edge-rtr` → dry-run the remediation first, then `config merge` (double confirm) through the audited path\n5. **Failure branch**: if `interface_health_rca` / `bgp_neighbor_rca` returns \"not supported by the `<driver>` driver\", the platform's NAPALM driver lacks the underlying getter — fall back to `device facts` / `config_backup` and request the getter via a GitHub issue.\n\n## Usage Mode\n\n| Scenario | Recommended | Why |\n|----------|:-----------:|-----|\n| Local/small models | **CLI** | fewer tokens than MCP |\n| Cloud models (Claude, GPT) | Either | MCP gives structured JSON I/O |\n| Automated pipelines | **MCP** | type-safe parameters, audited |\n\n## MCP Tools (33 — 28 read, 5 write)\n\n| Category | Tools | R/W |\n|----------|-------|:---:|\n| Facts | `device_facts`, `get_interfaces`, `get_interfaces_counters`, `get_interfaces_ip`, `get_bgp_neighbors`, `get_bgp_neighbors_detail`, `get_lldp_neighbors`, `get_lldp_neighbors_detail`, `get_arp_table` | Read |\n| Inventory | `get_mac_address_table`, `get_vlans`, `get_route_to` | Read |\n| Platform / env | `get_environment`, `get_optics`, `get_ntp_servers`, `get_ntp_stats`, `get_users`, `get_snmp_information`, `get_network_instances`, `device_health` | Read |\n| Diagnostics / RCA | `interface_health_rca`, `bgp_neighbor_rca` | Read |\n| Config | `config_backup`, `config_diff` | Read |\n| | `config_merge`, `config_replace`, `confirm_commit`, `config_rollback` | Write |\n| NetBox | `netbox_list_devices`, `netbox_get_device`, `netbox_device_interfaces` | Read |\n| Undo | `undo_list` | Read |\n| | `undo_apply` | Write |\n\n**Commit-confirm is the primary safety net.** `config_merge` and `config_replace` commit with a device-side revert timer (`revert_in`, default 300s): the device rolls the change back on its own unless `confirm_commit` follows. This is the only guard that survives the change severing your own management path — a commit that shuts the management interface, tightens the VTY ACL or breaks AAA also kills the session the recorded undo would need, so the *device* has to be the one enforcing the rollback. Workflow: **commit with timer → verify you can still reach the device → `confirm_commit`** (or do nothing and let it revert). Drivers that cannot arm a timer fall back to a plain commit and say so in `commit.warning` / `commit.safetyNet` — check that field, because for those devices the net is absent.\n\n**Harness features that light up**: `config_merge` and `config_replace` capture the pre-change running config and pass an `undo=` lambda so the harness records an inverse descriptor (with `_undo_id`) that restores the captured config via `config_replace` — the device must support config replace for the undo to apply. The raw config is handed to the harness out-of-band and kept only in `undo.db` (0600); the tool result returns a **digest** (size + SHA-256), never the config body, because a running config carries credential hashes, SNMP communities and PSKs that would otherwise land in the agent transcript. `config_rollback` declares no undo; `config_replace` is tagged `risk_level=high`. `config_diff` is a pure dry-run (stage candidate → compare → discard). The two RCA tools (`interface_health_rca`, `bgp_neighbor_rca`) are pure read-only analyses (`risk_level=low`) that collect getter output and rank findings worst-first. All 33 tools are audit-logged under `~/.network-aiops/` and pass through the budget/runaway guard, with a descriptive risk tier tagged on each audit row. Avoid tight poll loops — the runaway breaker backs this up.\n\n## Encrypted secret store\n\nSecrets never touch disk in plaintext. They live in `~/.network-aiops/secrets.enc` (Fernet/AES-128 + HMAC, key derived from a master password via scrypt; file chmod 600). Both kinds of secret share the one store: per-device login passwords keyed by device name, and the single NetBox API token keyed by the reserved name `netbox-token`.\n\n```bash\nnetwork-aiops init                       # wizard: collects devices + passwords (encrypted), optional NetBox\nnetwork-aiops secret set core-sw1        # store/replace a device password (hidden prompt)\nnetwork-aiops secret set netbox-token    # store the NetBox API token\nnetwork-aiops secret list                # names only — values are NEVER printed\nnetwork-aiops secret rm core-sw1\nnetwork-aiops secret migrate             # import a legacy plaintext .env (renamed to .env.migrated)\nnetwork-aiops secret rotate-password     # re-encrypt the whole store under a new master password\n```\n\nUnlock non-interactively by exporting `NETWORK_AIOPS_MASTER_PASSWORD` (used by the MCP server / cron / CI). Legacy plaintext env vars (`NETWORK_<TARGET_UPPER>_PASSWORD`, `NETWORK_NETBOX_TOKEN`) are still honoured as a deprecated fallback with a warning. An empty device password is allowed (valid for key-based SSH auth via `optional_args`).\n\n## CLI Quick Reference\n\n```bash\nnetwork-aiops init                                               # onboarding wizard (encrypted secrets)\nnetwork-aiops device facts [-t <device>]\nnetwork-aiops device interfaces [-t <device>]\nnetwork-aiops device counters [-t <device>]\nnetwork-aiops device bgp [-t <device>]\nnetwork-aiops device lldp [-t <device>]\nnetwork-aiops device arp [-t <device>]\nnetwork-aiops device mac [-t <device>]\nnetwork-aiops device vlans [-t <device>]\nnetwork-aiops device route <prefix> [-t <device>] [--protocol bgp]\nnetwork-aiops device environment [-t <device>]\nnetwork-aiops device health [-t <device>]\nnetwork-aiops diagnose interface-health [-t <device>]           # interface RCA (worst-first)\nnetwork-aiops diagnose bgp [-t <device>]                        # BGP-neighbor RCA (worst-first)\nnetwork-aiops config backup [-t <device>] [-o <file>]\nnetwork-aiops config diff <file> [-t <device>] [--replace]\nnetwork-aiops config merge <file> [-t <device>] [--dry-run]      # double confirm\nnetwork-aiops config replace <file> [-t <device>] [--dry-run]    # HIGH RISK\nnetwork-aiops config rollback [-t <device>] [--dry-run]          # double confirm\nnetwork-aiops netbox list [--name <q>] [--limit N]\nnetwork-aiops netbox get <name>\nnetwork-aiops netbox interfaces <device> [--limit N]\nnetwork-aiops secret set|list|rm|migrate|rotate-password\nnetwork-aiops doctor\nnetwork-aiops mcp                                                # start MCP server (stdio)\n```\n\nSee `references/cli-reference.md` for the full command list.\n\n## Troubleshooting\n\n### \"Could not connect/authenticate to '<device>'\"\nThe host/port, username, or password is wrong, or the device is unreachable. Run `network-aiops doctor` — it reports whether the encrypted secret store is present, whether a password is stored for the device, and whether the device answers. Store/replace the password with `network-aiops secret set <device>` (or re-run `network-aiops init`). For enable/secret, set it in `optional_args.secret`.\n\n### \"Master password not set\" / cannot unlock secrets\nThe encrypted store needs the master password. Export `NETWORK_AIOPS_MASTER_PASSWORD` for non-interactive use (MCP server / cron), or \n\nArchive v0.12.0: 7 files, 25890 bytes\n\nFiles: references/agent-guardrails.md (11690b), references/capabilities.md (10561b), references/cli-reference.md (4989b), references/setup-guide.md (5363b), skill-card.md (2915b), SKILL.md (24147b), _meta.json (133b)\n\nArchive v0.11.0: 7 files, 25732 bytes\n\nFiles: references/agent-guardrails.md (11690b), references/capabilities.md (10561b), references/cli-reference.md (4989b), references/setup-guide.md (5363b), skill-card.md (2459b), SKILL.md (24224b), _meta.json (133b)\n\nArchive v0.10.0: 7 files, 25868 bytes\n\nFiles: references/agent-guardrails.md (11690b), references/capabilities.md (10561b), references/cli-reference.md (4989b), references/setup-guide.md (5363b), skill-card.md (2965b), SKILL.md (24224b), _meta.json (133b)\n\nArchive v0.9.0: 7 files, 25845 bytes\n\nFiles: references/agent-guardrails.md (11690b), references/capabilities.md (10561b), references/cli-reference.md (4989b), references/setup-guide.md (5363b), skill-card.md (2859b), SKILL.md (24224b), _meta.json (132b)\n\nArchive v0.8.0: 7 files, 25876 bytes\n\nFiles: references/agent-guardrails.md (11690b), references/capabilities.md (10561b), references/cli-reference.md (4989b), references/setup-guide.md (5363b), skill-card.md (2938b), SKILL.md (24224b), _meta.json (132b)\n\nArchive v0.7.0: 7 files, 25842 bytes\n\nFiles: references/agent-guardrails.md (11690b), references/capabilities.md (10561b), references/cli-reference.md (4989b), references/setup-guide.md (5363b), skill-card.md (2859b), SKILL.md (24224b), _meta.json (132b)\n\nArchive v0.6.0: 7 files, 24996 bytes\n\nFiles: references/agent-guardrails.md (11395b), references/capabilities.md (9536b), references/cli-reference.md (4989b), references/setup-guide.md (5257b), skill-card.md (3079b), SKILL.md (23672b), _meta.json (132b)","readmeExcerpt":"Skill: network-aiops Owner: zw008 Summary: Use this skill whenever the user needs to operate a network device — read device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary and detail), ARP/MAC tables, VLANs, routes, hardware environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, and an aggregated device-health summary; run read-only RCA diagnostics on interface health and BGP neigh","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"uv tool install network-aiops\nnetwork-aiops init            # interactive wizard: device + driver + host + encrypted password (+ optional NetBox)\nnetwork-aiops doctor          # checks config, encrypted secret store, and per-device password presence"},{"language":"bash","snippet":"openclaw plugins install clawhub:@zw008/network-aiops\nopenclaw skills info network-aiops          # expect: Visible to model: yes"},{"language":"bash","snippet":"network-aiops init                       # wizard: collects devices + passwords (encrypted), optional NetBox\nnetwork-aiops secret set core-sw1        # store/replace a device password (hidden prompt)\nnetwork-aiops secret set netbox-token    # store the NetBox API token\nnetwork-aiops secret list                # names only — values are NEVER printed\nnetwork-aiops secret rm core-sw1\nnetwork-aiops secret migrate             # import a legacy plaintext .env (renamed to .env.migrated)\nnetwork-aiops secret rotate-password     # re-encrypt the whole store under a new master password"},{"language":"bash","snippet":"network-aiops init                                               # onboarding wizard (encrypted secrets)\nnetwork-aiops device facts [-t <device>]\nnetwork-aiops device interfaces [-t <device>]\nnetwork-aiops device counters [-t <device>]\nnetwork-aiops device bgp [-t <device>]\nnetwork-aiops device lldp [-t <device>]\nnetwork-aiops device arp [-t <device>]\nnetwork-aiops device mac [-t <device>]\nnetwork-aiops device vlans [-t <device>]\nnetwork-aiops device route <prefix> [-t <device>] [--protocol bgp]\nnetwork-aiops device environment [-t <device>]\nnetwork-aiops device health [-t <device>]\nnetwork-aiops diagnose interface-health [-t <device>]           # interface RCA (worst-first)\nnetwork-aiops diagnose bgp [-t <device>]                        # BGP-neighbor RCA (worst-first)\nnetwork-aiops config backup [-t <device>] [-o <file>]\nnetwork-aiops config diff <file> [-t <device>] [--replace]\nnetwork-aiops config merge <file> [-t <device>] [--dry-run]      # double confirm\nnetwork-aiops config replace <file> [-t <device>] [--dry-run]    # HIGH RISK\nnetwork-aiops config rollback [-t <device>] [--dry-run]          # double confirm\nnetwork-aiops netbox list [--name <q>] [--limit N]\nnetwork-aiops netbox get <name>\nnetwork-aiops netbox interfaces <device> [--limit N]\nnetwork-aiops secret set|list|rm|migrate|rotate-password\nnetwork-aiops doctor\nnetwork-aiops mcp                                                # start MCP server (stdio)"},{"language":"text","snippet":"You operate multi-vendor network devices (Cisco IOS / NX-OS / IOS-XR, Arista EOS,\nJuniper Junos) and an optional NetBox source of truth through the network-aiops\nMCP tools.\n\nTOOL USE\n- Before answering any question about the current state of the network, you MUST\n  call a tool. Never answer from memory or assumption.\n- Actually invoke the tool. Do not describe the call you would make, and do not\n  emit an example JSON response in place of calling it.\n- If a tool call fails, report the real error verbatim. Never fill the gap with\n  a plausible-sounding answer. \"Not supported by the <driver> driver\" means the\n  platform lacks that getter — say so; do not substitute a different getter and\n  present its output as the answer to the original question.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result contains a \"truncated\"\n  field that is true, say so and re-run with a higher limit instead of treating\n  the partial result as complete.\n- A null field means the driver did not return that value. Report it as \"not\n  available\" — never infer it.\n- Report identifiers EXACTLY as returned. Interface naming is vendor-specific:\n  GigabitEthernet0/1, Ethernet1, ge-0/0/0 and Te0/0/0/1 are literal device\n  strings, not styles to normalise. Never abbreviate Gi0/1 to 0/1, never expand\n  Et1 to Ethernet1, never convert between vendors' forms.\n- Do not normalise, translate, or prettify VRF names, BGP connection states,\n  route protocols, or VLAN names either.\n- When an RCA result has findings, work in \"rank\" order and cite the measured\n  number in each finding's \"detail\".\n\nCONFIG CHANGES\n- Always call config_diff first and show the operator the diff. Only after they\n  approve the exact diff may you call config_merge or config_replace.\n- config_merge is additive: it adds and modifies lines, it does not remove what\n  you left out. config_replace makes the device match the supplied config in\n  full — anything absent from your text is REMOVED, including the management\n  "},{"language":"bash","snippet":"network-aiops doctor"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: network-aiops\nslug: network-aiops\ndisplayName: \"Network AIops\"\nsummary: \"Governed network device ops (NAPALM) — 33 MCP tools with audit/undo.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Network-AIops\ntags: [aiops, mcp, governance, network]\ndescription: >\n  Use this skill whenever the user needs to operate a network device — read device facts, interfaces (+ counters/IP), BGP/LLDP neighbors (summary and detail), ARP/MAC tables, VLANs, routes, hardware environment (fans/temp/power/CPU/mem), optics, NTP, users, SNMP info, VRFs, and an aggregated device-health summary; run read-only RCA diagnostics on interface health and BGP neighbors; back up a switch/router config, diff a candidate config (dry-run), and merge/replace/rollback config — across Cisco IOS/IOS-XE, Nexus NX-OS, IOS-XR, Arista EOS, and Juniper Junos via NAPALM. An optional NetBox block adds source-of-truth lookups.\n  Always use this skill for \"back up switch config\", \"show bgp neighbors\", \"diff network config\", \"push config to router\", \"show interfaces on the switch\", or tasks mentioning \"cisco\", \"arista\", \"juniper\", \"nexus\", \"ios-xr\", or \"napalm\".\n  Do NOT use when the target is not a NAPALM-supported network device (Kubernetes clusters, hypervisor VMs, and cloud consoles are out of scope — route those elsewhere).\n  Common multi-vendor device operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers).\ninstaller:\n  kind: uv\n  package: network-aiops\nargument-hint: \"[device name or describe your network task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"network-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"NETWORK_AIOPS_CONFIG\",\"NETWORK_AIOPS_HOME\",\"NETWORK_AIOPS_MASTER_PASSWORD\",\"NETWORK_NETBOX_TOKEN\"]},\"homepage\":\"https://github.com/AIops-tools/Network-AIops\",\"emoji\":\"🛜\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed network device operations over NAPALM. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency.\n  All write operations are audited to a local SQLite DB under ~/.network-aiops/ (relocatable via NETWORK_AIOPS_HOME).\n  Credentials: device login passwords AND the optional NetBox API token live in an ENCRYPTED store at ~/.network-aiops/secrets.enc (Fernet/AES + scrypt-derived key; chmod 600), never in plaintext. Device passwords are keyed by the device name; the NetBox token uses the reserved name \"netbox-token\". Unlock with the NETWORK_AIOPS_MASTER_PASSWORD env var (for the MCP server / non-interactive use) or an interactive prompt. Run `network-aiops init` (wizard) or `network-aiops secret set <name>` to populate it, and `network-aiops secret migrate` to import a legacy plaintext .env (NETWORK_<TARGET_UPPER>_PASSWORD / NETWORK_NETBOX_TOKEN are still honoured as a deprecated fallback). config.yaml holds only device names, drivers, hosts, usernames, and NAPALM optional_args — never secrets. The state "},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"network-aiops\",\n  \"version\": \"0.12.3\",\n  \"publishedAt\": 1789452559228\n}"},{"path":"references/agent-guardrails.md","content":"# Agent guardrails — running network-aiops with a smaller / local model\n\nIf you drive these tools with a local model (Llama, Qwen, Mistral … via Goose,\nOllama, LM Studio, or any OpenAI-compatible runtime), you will get noticeably\nbetter results with a short system prompt. This page gives you one, and — more\nimportantly — tells you which guardrails you **no longer need to write**, because\nthe tool now enforces them itself.\n\nThe distinction matters. A guardrail in a prompt is a request. A guardrail in the\nharness is a guarantee. Anything below that we could move into the harness, we did.\n\nNetwork gear raises the stakes: a bad merge on a core switch takes the management\nplane with it, and the model cannot SSH back in to fix what it broke.\n\n## What the tool now enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Don't invent a value when a field is missing\" | A field the driver did not return comes back as `null`, never as `\"\"`. This is the norm, not the exception, on a multi-vendor fleet: `serial_number`, `model`, an interface `description`, an LLDP neighbour's `hostname` are all optional and driver-dependent. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | The NetBox listings return `{\"devices\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}` (and `{\"interfaces\": ...}` likewise). Truncation is measured — one extra record is fetched — not guessed from a length coincidence. |\n| \"Preserve the ordering / tell me what's most urgent\" | `interface_health_rca` and `bgp_neighbor_rca` findings carry an explicit 1-based `rank`, worst-first, and each cites the measured number that tripped it (`rx_errors+tx_errors = 412 >= 100`). Priority is in the payload, not implied by list position. |\n| \"Show me the diff before you commit anything\" | `config_diff` is a real dry run: it stages a candidate, returns `compare_config()` output, then always discards. Nothing is committed, and the response carries `\"committed\": false`. |\n| \"Confirm before anything destructive\" | The CLI write paths (`config merge`/`replace`/`rollback`) require a double confirmation, and every write supports `--dry-run` / `dry_run=True` to preview first. `config_replace` is `high` risk, carried into the audit row as a `review` tier so it stands out in the trail. |\n| \"Keep a copy of the old config so we can go back\" | `config_merge` and `config_replace` read the running config **before** touching the device and return it as `backup`, and the harness records an undo descriptor that restores it via `config_replace`. The before-state is captured, not reconstructed. |\n| \"Log what you did\" | Every governed call is audited to `~/.network-aiops/audit.db` regardless of what the model says it did. |\n| \"Never show me passwords or SNMP communities\" | `get_users` returns `has_password` (a boolean) instead of the hash; `get_snmp_information` returns `community_count` instead of the commu"},{"path":"references/capabilities.md","content":"# network-aiops Capabilities\n\n33 MCP tools (28 read / 5 write). Every tool is wrapped with `@governed_tool`\n(audit + policy + budget + risk-tier; undo where a clean inverse exists). Returns\nare high-signal summaries — config blobs are sanitized and size-bounded. Secrets\nare never returned (user password hashes and SNMP community strings are redacted).\n\n## Read tools\n\n| Tool | Returns | Risk | Typical response tokens |\n|------|---------|:----:|:-----------------------:|\n| `device_facts` | hostname, vendor, model, os_version, serial, uptime, interface list | low | ~80–300 |\n| `get_interfaces` | per-interface up/enabled/speed/description/mac | low | ~60–800 |\n| `get_interfaces_counters` | per-interface octets/packets/errors/discards | low | ~60–800 |\n| `get_interfaces_ip` | per-interface IPv4/IPv6 + prefix length | low | ~40–400 |\n| `get_bgp_neighbors` | per-VRF peer, remote AS, up, prefix counts | low | ~60–600 |\n| `get_bgp_neighbors_detail` | + state, router id, local AS, advertised prefixes | low | ~80–900 |\n| `get_lldp_neighbors` | local port, remote host, remote port | low | ~40–400 |\n| `get_lldp_neighbors_detail` | + chassis id, system desc, capabilities | low | ~60–700 |\n| `get_arp_table` | interface, IP, MAC, age | low | ~50–700 |\n| `get_mac_address_table` | MAC, interface, VLAN, static/active | low | ~50–900 |\n| `get_vlans` | id, name, member interfaces | low | ~40–500 |\n| `get_route_to` | per-prefix protocol, next hop, outgoing interface | low | ~40–500 |\n| `get_environment` | fans, temperature, power, CPU, memory | low | ~60–500 |\n| `get_optics` | per-interface rx/tx power, laser bias | low | ~40–400 |\n| `get_ntp_servers` | configured NTP servers | low | ~20–120 |\n| `get_ntp_stats` | per-peer stratum, offset, jitter, reachability | low | ~40–300 |\n| `get_users` | username, level, has_password (hash redacted) | low | ~30–200 |\n| `get_snmp_information` | chassis id, contact, location, community_count | low | ~40 |\n| `get_network_instances` | VRFs: name, type, RD, interfaces | low | ~40–400 |\n| `device_health` | facts + interface up/down + environment + issues | low | ~120–400 |\n| `interface_health_rca` | worst-first findings: down / error / discard / flap, each cited | low | ~80–600 |\n| `bgp_neighbor_rca` | worst-first findings: down / shut / reset / route-less, each cited | low | ~60–500 |\n| `config_backup` | running config, credential values masked (`include_secrets=True` for raw) | low | ~500–8000 |\n| `config_diff` | candidate diff, credential values masked (dry-run, never committed) | low | ~30–1500 |\n| `netbox_list_devices` | `{devices, returned, limit, truncated}` — name, role, site, status, primary IP | low | ~40–500 |\n| `netbox_get_device` | + device_type, serial | low | ~80 |\n| `netbox_device_interfaces` | `{interfaces, returned, limit, truncated}` — name, type, enabled, description | low | ~40–600 |\n| `undo_list` | recorded, not-yet-applied reversible writes (undoId, original/inverse tool, note) | low | ~40–400 |\n\n> **Optional fie"},{"path":"references/cli-reference.md","content":"# network-aiops CLI Reference\n\nAll commands accept `-t/--target <name>` to select a configured device. When\nomitted, the first device in `~/.network-aiops/config.yaml` is used.\n\n## Onboarding & secrets\n\n```bash\nnetwork-aiops init                              # interactive wizard: devices + encrypted passwords (+ NetBox)\nnetwork-aiops secret set <name>                 # store/replace a device password, or 'netbox-token' (hidden prompt)\nnetwork-aiops secret list                       # names only — values are never printed\nnetwork-aiops secret rm <name>                  # delete a stored secret\nnetwork-aiops secret migrate                    # import a legacy plaintext .env into the encrypted store\nnetwork-aiops secret rotate-password            # re-encrypt the store under a new master password\n```\n\nSecrets are stored encrypted in `~/.network-aiops/secrets.enc`. Unlock\nnon-interactively with `NETWORK_AIOPS_MASTER_PASSWORD`.\n\n## Device facts & state (read-only)\n\n```bash\nnetwork-aiops device facts [-t <device>]        # hostname, vendor, model, OS, serial, uptime\nnetwork-aiops device interfaces [-t <device>]   # up/down, enabled, speed, description\nnetwork-aiops device counters [-t <device>]     # per-interface traffic + error counters\nnetwork-aiops device bgp [-t <device>]          # BGP neighbors per VRF\nnetwork-aiops device lldp [-t <device>]         # LLDP neighbors\nnetwork-aiops device arp [-t <device>]          # ARP table\nnetwork-aiops device mac [-t <device>]          # MAC address table\nnetwork-aiops device vlans [-t <device>]        # VLANs (id, name, member count)\nnetwork-aiops device route <prefix> [-t <device>] [--protocol bgp]  # routing-table lookup\nnetwork-aiops device environment [-t <device>]  # fans, temperature, power, CPU, memory\nnetwork-aiops device health [-t <device>]       # aggregated health summary\n```\n\nAdditional read getters are exposed as MCP tools (no dedicated CLI subcommand):\n`get_bgp_neighbors_detail`, `get_lldp_neighbors_detail`, `get_optics`,\n`get_ntp_servers`, `get_ntp_stats`, `get_users`, `get_snmp_information`,\n`get_network_instances`. A getter a driver does not implement returns a teaching\n\"not supported by the `<driver>` driver\" error.\n\n## Configuration\n\n```bash\nnetwork-aiops config backup [-t <device>] [-o <file>]      # running config (save with -o)\nnetwork-aiops config diff <file> [-t <device>] [--replace] # DRY-RUN: show the diff only\nnetwork-aiops config merge <file> [-t <device>] [--dry-run] [--revert-in N]   # commit; double confirm\nnetwork-aiops config replace <file> [-t <device>] [--dry-run] [--revert-in N] # HIGH RISK; double confirm\nnetwork-aiops config confirm [-t <device>] [--dry-run]         # confirm a pending commit\nnetwork-aiops config rollback [-t <device>] [--dry-run]        # revert last commit; double confirm\n```\n\n- `config diff` stages a candidate, runs `compare_config()`, and discards it —\n  nothing is committed. `--replace` diffs as a full-config replacement.\n- `--dry-run` on `merge` /"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2210,"uniquenessScore":40,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T23:33:08.442Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T23:33:08.442Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:39:49.631Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}