{"id":"592ad318-93ca-4bdb-bbfd-e5fad833164e","entityType":"agent","slug":"clawhub-zw008-fabric-aiops","name":"fabric-aiops","canonicalUrl":"https://www.xpersona.co/agent/clawhub-zw008-fabric-aiops","canonicalPath":"/agent/clawhub-zw008-fabric-aiops","generatedAt":"2026-10-10T10:45:00.761Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T07:53:49.677Z","emptyReason":null},"description":"Use this skill whenever the user needs to operate a network fabric through a controller API — Cisco Meraki Dashboard (full read+write), Cisco Catalyst Center / DNA Center (read subset), Arista CloudVision Portal / CVP (read subset), or UniFi Network (self-hosted controller / UniFi OS console; read subset + device restart) — a one-shot fabric health overview; organization/site/container reads (list/get, licensing, admins, org-wide device statuses, API usage); network reads (list/get, VLANs, health alerts, traffic); device reads (inventory by model MX/MS/MR/MV/MG, status, uplinks, switch ports / interface stats, wireless SSIDs); client reads (list, detail, usage, connectivity); three flagship analyses — uplink loss & latency RCA (rank worst MX WAN uplinks + cause/action), network health score (composite per-network), and config template drift (settings drifted from a bound template); and eight guarded writes (reboot, blink LEDs, update device, update VLAN, claim/remove devices, bind/unbind a config template — Meraki-only except device restart, which unifi also maps; other unmapped writes return a teaching \"not supported yet\" error). Always use this skill for \"Meraki org overview\", \"which uplinks are worst\", \"uplink loss and latency\", \"WAN degradation RCA\", \"network health score\", \"config template drift\", \"list Meraki networks/devices/clients\", \"reboot a Meraki device\", \"blink device LEDs\", \"claim a device into a network\", \"bind a network to a template\", \"Catalyst Center site health / device health / issues\", \"DNA Center inventory\", \"CloudVision inventory / compliance / events\", \"UniFi site health / alarms / clients\", \"restart a UniFi AP or switch\" when the context is a controller-managed network fabric. Do NOT use when the target is OT / industrial equipment (Modbus, OPC-UA, PLCs — use industrial-aiops), a hypervisor, a storage appliance, a backup product, a container/cluster orchestrator, or device-level CLI/SSH network automation (negative routing hints only). Covers common controller fabric operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers). The test suite is mock-based; no platform has yet been exercised against a live controller (see docs/VERIFICATION.md).","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.6K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:fabric-aiops","sourceUrl":"https://clawhub.ai/zw008/fabric-aiops","homepage":"https://clawhub.ai/zw008/skills/fabric-aiops","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/zw008/fabric-aiops","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/zw008/skills/fabric-aiops","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":64,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"fabric-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-10T07:53:49.677Z","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-10T07:53:49.677Z","emptyReason":null},"stars":null,"forks":null,"downloads":1578,"packageName":null,"latestVersion":"0.12.0","tractionLabel":"1.6K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T07:53:49.644Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T07:53:49.677Z","lastCrawledAt":"2026-10-10T07:53:49.644Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T07:53:49.644Z","lastVerifiedAt":null,"highlights":[{"version":"0.12.0","createdAt":"2026-09-21T03:56:26.404Z","changelog":"- Added Cisco ACI APIC platform support: read-only endpoint path trace, EPG segment, and fault queries. - Expanded from 34 to 37 MCP tools, now spanning five controller platforms. - Documentation updated to reflect ACI capabilities and tested coverage. - Removed obsolete skill-card.md file. - General improvements and clarifications in CLI reference and setup documentation.","fileCount":7,"zipByteSize":24775},{"version":"0.11.5","createdAt":"2026-09-16T23:25:27.380Z","changelog":"- Updated references/agent-guardrails.md documentation. - Removed the skill-card.md file.","fileCount":7,"zipByteSize":21116},{"version":"0.11.4","createdAt":"2026-09-16T05:13:33.987Z","changelog":"## fabric-aiops 0.11.4 - Removed the redundant or outdated skill-card.md file from the project. - No user-facing functional changes; all features and documentation remain unchanged.","fileCount":7,"zipByteSize":21315},{"version":"0.11.3","createdAt":"2026-09-15T05:56:31.978Z","changelog":"- Removed the file skill-card.md from the project. - No other user-facing functionality or documentation changes.","fileCount":7,"zipByteSize":21261},{"version":"0.11.2","createdAt":"2026-09-12T14:11:28.256Z","changelog":"## fabric-aiops 0.11.2 Changelog - Documentation updated: SKILL.md received revisions and improvements. - Obsolete or redundant documentation file skill-card.md was removed. - No code or feature changes; this is a documentation-only update.","fileCount":7,"zipByteSize":21195},{"version":"0.11.1","createdAt":"2026-09-12T10:04:11.270Z","changelog":"## fabric-aiops v0.11.1 changelog - Documentation was updated: SKILL.md revised with no functional or API changes. - The skill-card.md file was removed, simplifying the documentation set.","fileCount":7,"zipByteSize":21082},{"version":"0.11.0","createdAt":"2026-09-12T00:52:37.812Z","changelog":"- Updated SKILL.md metadata to use anyBins for binary requirements (now supports either 'fabric-aiops' or 'uvx'). - Expanded optional environment variables list in metadata to include both FABRIC_AIOPS_CONFIG and FABRIC_AIOPS_MASTER_PASSWORD. - Removed the metadata field for the skill-card file (skill-card.md), streamlining documentation. - No user-facing functional changes.","fileCount":7,"zipByteSize":21047},{"version":"0.10.0","createdAt":"2026-08-10T06:50:41.604Z","changelog":"- Removed the documentation file skill-card.md. - No functional or code changes; this version only deletes skill-card.md from the project.","fileCount":7,"zipByteSize":21137}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:fabric-aiops","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s171xgnmqse0nqvgqvqnaq5f9183kyre:fabric-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/fabric-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-fabric-aiops/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-fabric-aiops/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-fabric-aiops/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-fabric-aiops/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-fabric-aiops/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-zw008-fabric-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-10T10:45:00.757Z"}},"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-fabric-aiops/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-fabric-aiops/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-fabric-aiops/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-zw008-fabric-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-10T07:53:49.677Z","emptyReason":null},"readme":"Skill: fabric-aiops\n\nOwner: zw008\n\nSummary: Use this skill whenever the user needs to operate a network fabric through a controller API — Cisco Meraki Dashboard (full read+write), Cisco Catalyst Center / DNA Center (read subset), Arista CloudVision Portal / CVP (read subset), or UniFi Network (self-hosted controller / UniFi OS console; read subset + device restart) — a one-shot fabric health overview; organization/site/container reads (list/get, licensing, admins, org-wide device statuses, API usage); network reads (list/get, VLANs, health alerts, traffic); device reads (inventory by model MX/MS/MR/MV/MG, status, uplinks, switch ports / interface stats, wireless SSIDs); client reads (list, detail, usage, connectivity); three flagship analyses — uplink loss & latency RCA (rank worst MX WAN uplinks + cause/action), network health score (composite per-network), and config template drift (settings drifted from a bound template); and eight guarded writes (reboot, blink LEDs, update device, update VLAN, claim/remove devices, bind/unbind a config template — Meraki-only except device restart, which unifi also maps; other unmapped writes return a teaching \"not supported yet\" error). Always use this skill for \"Meraki org overview\", \"which uplinks are worst\", \"uplink loss and latency\", \"WAN degradation RCA\", \"network health score\", \"config template drift\", \"list Meraki networks/devices/clients\", \"reboot a Meraki device\", \"blink device LEDs\", \"claim a device into a network\", \"bind a network to a template\", \"Catalyst Center site health / device health / issues\", \"DNA Center inventory\", \"CloudVision inventory / compliance / events\", \"UniFi site health / alarms / clients\", \"restart a UniFi AP or switch\" when the context is a controller-managed network fabric. Do NOT use when the target is OT / industrial equipment (Modbus, OPC-UA, PLCs — use industrial-aiops), a hypervisor, a storage appliance, a backup product, a container/cluster orchestrator, or device-level CLI/SSH network automation (negative routing hints only). Covers common controller fabric operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers). The test suite is mock-based; no platform has yet been exercised against a live controller (see docs/VERIFICATION.md).\n\nTags: latest:0.12.0\n\nVersion history:\n\nv0.12.0 | 2026-09-21T03:56:26.404Z | auto\n\n- Added Cisco ACI APIC platform support: read-only endpoint path trace, EPG segment, and fault queries.\n- Expanded from 34 to 37 MCP tools, now spanning five controller platforms.\n- Documentation updated to reflect ACI capabilities and tested coverage.\n- Removed obsolete skill-card.md file.\n- General improvements and clarifications in CLI reference and setup documentation.\n\nv0.11.5 | 2026-09-16T23:25:27.380Z | auto\n\n- Updated references/agent-guardrails.md documentation.\n- Removed the skill-card.md file.\n\nv0.11.4 | 2026-09-16T05:13:33.987Z | auto\n\n## fabric-aiops 0.11.4\n\n- Removed the redundant or outdated skill-card.md file from the project.\n- No user-facing functional changes; all features and documentation remain unchanged.\n\nv0.11.3 | 2026-09-15T05:56:31.978Z | auto\n\n- Removed the file skill-card.md from the project.\n- No other user-facing functionality or documentation changes.\n\nv0.11.2 | 2026-09-12T14:11:28.256Z | auto\n\n## fabric-aiops 0.11.2 Changelog\n\n- Documentation updated: SKILL.md received revisions and improvements.\n- Obsolete or redundant documentation file skill-card.md was removed.\n- No code or feature changes; this is a documentation-only update.\n\nv0.11.1 | 2026-09-12T10:04:11.270Z | auto\n\n## fabric-aiops v0.11.1 changelog\n\n- Documentation was updated: SKILL.md revised with no functional or API changes.\n- The skill-card.md file was removed, simplifying the documentation set.\n\nv0.11.0 | 2026-09-12T00:52:37.812Z | auto\n\n- Updated SKILL.md metadata to use anyBins for binary requirements (now supports either 'fabric-aiops' or 'uvx').\n- Expanded optional environment variables list in metadata to include both FABRIC_AIOPS_CONFIG and FABRIC_AIOPS_MASTER_PASSWORD.\n- Removed the metadata field for the skill-card file (skill-card.md), streamlining documentation.\n- No user-facing functional changes.\n\nv0.10.0 | 2026-08-10T06:50:41.604Z | auto\n\n- Removed the documentation file skill-card.md.\n- No functional or code changes; this version only deletes skill-card.md from the project.\n\nv0.9.0 | 2026-08-03T05:52:33.129Z | auto\n\n- Removed the skill-card.md file from the package.\n- No impact to user-facing functionality; all governance and controller operations remain unchanged.\n- This is primarily a cleanup/housekeeping release.\n\nv0.8.0 | 2026-08-02T09:38:55.923Z | auto\n\n- Removed the file skill-card.md.\n- No changes to skill functionality or user interface.\n- Documentation cleanup only; feature set and compatibility remain unchanged.\n\nv0.7.0 | 2026-07-21T09:40:49.888Z | auto\n\nfabric-aiops 0.7.0\n\n- Updated documentation: SKILL.md, setup-guide, and agent guardrail references revised for clarity and accuracy.\n- Removed obsolete skill-card.md file.\n- Small clarifications to risk tier and audit/undo descriptions.\n- No changes to toolset or platform coverage.\n\nv0.6.0 | 2026-07-20T11:15:00.926Z | auto\n\n## fabric-aiops 0.6.0\n\n- Removed the skill-card.md file.\n- No changes to functionality or APIs; documentation file update only.\n\nv0.5.0 | 2026-07-19T03:51:05.639Z | auto\n\n## fabric-aiops v0.5.0\n\n- Added new guardrails reference documentation (`references/agent-guardrails.md`).\n- Updated CLI reference, capabilities, and setup guide documentation.\n- Improved and clarified SKILL.md metadata, including new summary, tags, and verification status notes.\n- Increased tool count to 34 governed fabric operations.\n- Removed deprecated or redundant documentation (`skill-card.md`).\n\nv0.4.0 | 2026-07-17T05:54:46.083Z | auto\n\n**UniFi Network support added.**\n\n- UniFi Network (self-hosted/UniFi OS) is now a supported platform: inventory, health, alarms, clients, and device restart (write) are mapped.\n- Updated documentation and references to include UniFi controller—details in SKILL.md, capabilities, CLI reference, and setup guide.\n- Device restart write operation is now available for UniFi devices (in addition to Meraki).\n- Other controller operations remain mock-validated and have improved matrix coverage notes.\n- Removed skill-card.md; documentation is now consolidated.\n\nv0.3.0 | 2026-07-16T15:08:06.767Z | auto\n\n**v0.3.0: Multi-controller platform support (Meraki, Catalyst, CVP), read/write unification**\n\n- Added support for Cisco Catalyst Center and Arista CloudVision Portal as read-only platforms alongside full Meraki API read/write.\n- Unified organization, network, device, and client read operations across all supported controllers.\n- Write operations remain Meraki-only; on Catalyst/CVP, write attempts return a clear \"not supported yet\" message.\n- Secrets and credential storage expanded to handle API keys, bearer tokens, and username/password flows for all platforms.\n- Documentation and guidance updated throughout; legacy Meraki-only hints expanded to controller-neutral language.\n- File cleanup: removed obsolete skill-card.md.\n\nv0.2.0 | 2026-07-13T13:09:47.577Z | auto\n\nVersion 0.2.0\n\n- Removed redundant skill-card.md file for improved maintainability.\n- SKILL.md updated with no changes to functionality or core documentation.\n- No changes to capabilities or system requirements.\n\nv0.1.0 | 2026-07-13T04:49:00.246Z | auto\n\nInitial release: Cisco Meraki network fabric operations with built-in governance and audit.\n\n- Provides 32 Meraki Dashboard API tools for organization, network, device, and client management.\n- All critical write operations are protected by policy, audit, and undo/risk-tier gates.\n- Credentials are securely encrypted and never stored in plaintext on disk.\n- Supports dry-run mode, double-confirmation for state-changing writes, and local audit logging.\n- Preview-only: tools are mock-validated and not yet live-tested against real Meraki environments.\n\nArchive index:\n\nArchive v0.12.0: 7 files, 24775 bytes\n\nFiles: references/agent-guardrails.md (9290b), references/capabilities.md (11225b), references/cli-reference.md (4236b), references/setup-guide.md (7264b), skill-card.md (2874b), SKILL.md (20557b), _meta.json (132b)\n\nFile v0.12.0:SKILL.md\n\n---\nname: fabric-aiops\nslug: fabric-aiops\ndisplayName: \"Fabric AIops\"\nsummary: \"Governed Cisco Meraki + ACI fabric ops: uplink RCA, ACI endpoint trace; 37 tools with audit/undo.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Fabric-AIops\ntags: [aiops, mcp, governance, fabric]\ndescription: >\n  Use this skill whenever the user needs to operate a network fabric through a controller API — Cisco Meraki Dashboard (full read+write), Cisco Catalyst Center / DNA Center (read subset), Arista CloudVision Portal / CVP (read subset), or UniFi Network (self-hosted controller / UniFi OS console; read subset + device restart) — a one-shot fabric health overview; organization/site/container reads (list/get, licensing, admins, org-wide device statuses, API usage); network reads (list/get, VLANs, health alerts, traffic); device reads (inventory by model MX/MS/MR/MV/MG, status, uplinks, switch ports / interface stats, wireless SSIDs); client reads (list, detail, usage, connectivity); three flagship analyses — uplink loss & latency RCA (rank worst MX WAN uplinks + cause/action), network health score (composite per-network), and config template drift (settings drifted from a bound template); and eight guarded writes (reboot, blink LEDs, update device, update VLAN, claim/remove devices, bind/unbind a config template — Meraki-only except device restart, which unifi also maps; other unmapped writes return a teaching \"not supported yet\" error).\n  Always use this skill for \"Meraki org overview\", \"which uplinks are worst\", \"uplink loss and latency\", \"WAN degradation RCA\", \"network health score\", \"config template drift\", \"list Meraki networks/devices/clients\", \"reboot a Meraki device\", \"blink device LEDs\", \"claim a device into a network\", \"bind a network to a template\", \"Catalyst Center site health / device health / issues\", \"DNA Center inventory\", \"CloudVision inventory / compliance / events\", \"UniFi site health / alarms / clients\", \"restart a UniFi AP or switch\" when the context is a controller-managed network fabric.\n  Do NOT use when the target is OT / industrial equipment (Modbus, OPC-UA, PLCs — use industrial-aiops), a hypervisor, a storage appliance, a backup product, a container/cluster orchestrator, or device-level CLI/SSH network automation (negative routing hints only).\n  Covers common controller fabric operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers). The test suite is mock-based; no platform has yet been exercised against a live controller (see docs/VERIFICATION.md).\ninstaller:\n  kind: uv\n  package: fabric-aiops\nargument-hint: \"[org/network/device id or describe your fabric task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"fabric-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"FABRIC_AIOPS_CONFIG\",\"FABRIC_AIOPS_MASTER_PASSWORD\"]},\"homepage\":\"https://github.com/AIops-tools/Fabric-AIops\",\"emoji\":\"🛰️\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed network-fabric controller operations. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency. Multi-platform by construction (a platform registry): meraki (Cisco Meraki Dashboard, reference platform, full read+write), catalyst (Cisco Catalyst Center, read subset — sites stand in for organizations/networks), cvp (Arista CloudVision Portal, read subset — containers stand in for organizations/networks), and unifi (UniFi Network controller / UniFi OS console, read subset — sites stand in for organizations/networks — plus the device-restart write via a cmd/devmgr command envelope). Unmapped ops raise a teaching \"not supported on <platform> yet\" error; all writes are Meraki-only except UniFi device restart.\n  All write operations are audited to a local SQLite DB under ~/.fabric-aiops/ (relocatable via FABRIC_AIOPS_HOME).\n  Credentials: the controller secret (Meraki API key / Catalyst Center username:password / CVP service-account token / UniFi API key) is stored ENCRYPTED in ~/.fabric-aiops/secrets.enc (Fernet/AES-128 + scrypt-derived key) — never plaintext on disk. Run 'fabric-aiops init' to onboard, or 'fabric-aiops secret set <target>' to add one. The store is unlocked by a master password from FABRIC_AIOPS_MASTER_PASSWORD (non-interactive/MCP/CI) or an interactive prompt (CLI on a TTY). A legacy plaintext env var FABRIC_<TARGET_NAME_UPPER>_APIKEY is still honoured as a fallback with a deprecation warning (migrate with 'fabric-aiops secret migrate'). Meraki/CVP/UniFi secrets ride the platform auth header (Authorization: Bearer, X-Cisco-Meraki-API-Key, or UniFi's X-API-KEY) at request time; the Catalyst Center secret is exchanged via POST /dna/system/api/v1/auth/token for a short-lived X-Auth-Token (auto-refreshed once on 401). UniFi legacy cookie login (POST /api/login) is not implemented — use an API key (UniFi OS console or self-hosted Network Server 9.0+; a UniFi OS console's base_url carries the /proxy/network prefix). Secrets are held only in memory and never logged or echoed.\n  State-changing operations require double confirmation at the CLI layer and support --dry-run. All write tools pass through the @governed_tool decorator (pre-check + budget guard + audit + risk-tier label) and take a dry_run preview. Mutating/reversible writes fetch the real before-state first and record a faithful inverse undo descriptor; irreversible ops (reboot, blink) record only the before-state.\n  Webhooks: none — no outbound network calls beyond the configured controller REST API base URL.\n  SSL: verify_ssl defaults to true; disable only for a self-signed on-prem controller proxy.\n  Transitive dependencies: httpx (HTTP client) and the MCP SDK. No post-install scripts or background services.\n  Verification status: the test suite is mock-based; the Dashboard API paths are modelled from the public API shape and have not yet been exercised live — docs/VERIFICATION.md defines the checklist. Community-maintained; not affiliated with or endorsed by Cisco/Meraki — trademarks belong to their owners.\n---\n\n# Fabric AIops\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or sponsored by Cisco, Meraki, Arista, Ubiquiti, or any network-controller vendor.** Product and trademark names belong to their owners. Source at [github.com/AIops-tools/Fabric-AIops](https://github.com/AIops-tools/Fabric-AIops) under the MIT license.\n\nGoverned network-fabric controller operations — **37 MCP tools** over **five platforms** (Cisco Meraki Dashboard: full read+write; Cisco Catalyst Center and Arista CloudVision Portal: read subsets; UniFi Network: read subset + device restart; Cisco ACI APIC: read-only endpoint path trace, EPG segment and faults), every one wrapped with the bundled `@governed_tool` harness: a local unified audit log under `~/.fabric-aiops/`, token/runaway budget guard, undo-token recording, and descriptive risk tiers. The controller secret is stored **encrypted** (`~/.fabric-aiops/secrets.enc`, Fernet + scrypt) — never plaintext on disk.\n\n> **Standalone**: the governance harness is bundled in the package (`fabric_aiops.governance`) — fabric-aiops has no external skill-family dependency. No platform has yet been exercised by this tool against a live controller; the ACI reads are tested against real, anonymized APIC responses from a production fabric (see `docs/VERIFICATION.md`).\n\n## Platform support\n\n| Platform | `platform:` | Coverage | Auth |\n|----------|-------------|----------|------|\n| Cisco Meraki Dashboard | `meraki` | full (all reads + all 8 writes) | API key (Bearer / X-Cisco-Meraki-API-Key) |\n| Cisco Catalyst Center | `catalyst` | read subset: sites (as orgs/networks), device+site+client health, issues→alerts, inventory, interface stats | `username:password` → short-lived X-Auth-Token (auto-refresh on 401) |\n| Arista CloudVision Portal | `cvp` | read subset: containers (as orgs/networks), inventory (+ complianceCode drift signal), events→alerts, users→admins | service-account token (Bearer) |\n| Cisco ACI (APIC) | `aci` | **no canonical op** — three ACI-native reads instead: endpoint path trace (MAC/IP → leaf/interface → EPG → BD → VRF → contracts → filter entries, plus DN-matched fault candidates), EPG segment, fabric faults | `username:password` → `aaaLogin` session cookie (refreshed; one re-login on 401/403) |\n| UniFi Network | `unifi` | read subset: sites (as orgs/networks), stat/device inventory+statuses, stat/health, alarms→alerts, stat/sta clients, device port_table→switch ports; **plus the device-restart write** (cmd/devmgr) | API key (`X-API-KEY`, stateless); base_url = classic `https://<host>:8443` or UniFi OS console `https://<console>/proxy/network` |\n\nOps a platform does not map — and **every write on catalyst/cvp (on unifi, every write except reboot)** — return a teaching \"not supported on `<platform>` yet — open an issue or PR\" error, never a silent no-op. Full matrix in the repo README.\n\n## What This Skill Does\n\n| Domain | Tools | Count | Read or Write |\n|--------|-------|:-----:|:-------------:|\n| **Overview** | fabric fleet overview | 1 | 1 read |\n| **Organizations** | list/get, licensing, admins, device statuses, API usage | 6 | 6 read |\n| **Networks** | list/get, VLANs, health alerts, traffic | 5 | 5 read |\n| **Devices** | inventory (by model), status, uplinks, switch ports, SSIDs | 5 | 5 read |\n| **Clients** | list, detail, usage, connectivity | 4 | 4 read |\n| **Health (flagship)** | uplink loss/latency RCA, network health score, config template drift | 3 | 3 read |\n| **Cisco ACI** (APIC targets) | endpoint path trace, EPG segment, fabric faults | 3 | 3 read |\n| **Remediation** | reboot, claim, remove, bind, unbind | 5 | 5 write (high) |\n| | update device, update VLAN | 2 | 2 write (medium) |\n| | blink LEDs | 1 | 1 write (low) |\n| **Undo** | list recorded reversible writes | 1 | 1 read |\n| | apply a recorded inverse (governed, single-use, `dry_run`) | 1 | 1 write (medium) |\n\n`network_health_score` and `config_template_drift` are injected-only (they score data you already hold); `uplink_loss_and_latency_rca` accepts injected `records` for offline analysis, or pulls live from a configured target. Meraki device models carry a product-type prefix: **MX** appliance, **MS** switch, **MR** wireless AP, **MV** camera, **MG** cellular gateway.\n\n## Quick Install\n\n```bash\nuv tool install fabric-aiops\nfabric-aiops init       # interactive wizard: platform choice (meraki/catalyst/cvp/unifi) + encrypted secret\nfabric-aiops doctor\n```\n\nOr as an OpenClaw plugin, which installs this skill and its MCP server together:\n\n```bash\nopenclaw plugins install clawhub:@zw008/fabric-aiops\nopenclaw skills info fabric-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## When to Use This Skill\n\n- Triage an organization (`overview`): network count + device status/product rollup\n- Find the worst WAN uplinks (`health uplink-rca` / `uplink_loss_and_latency_rca`): ranked by loss + latency with a likely cause and action\n- Score fleet health per network (`health score` / `network_health_score`): a composite 0-100, worst first, every component shown\n- List/inspect organizations, networks, devices (by model), and clients\n- Reboot/blink a device, update device or VLAN attributes (reversible), claim/remove devices, or bind/unbind a config template — all with dry-run + double-confirm\n- On a Cisco ACI fabric: find where an endpoint (MAC/IP) attaches and which EPG / BD / VRF / contracts carry it (`aci trace` / `aci_endpoint_trace`), inspect an EPG's segment (`aci segment`), or list faults worst-first (`aci faults`)\n\n**Do NOT use when** the target is OT/industrial equipment (use industrial-aiops), a hypervisor, a storage appliance, a backup product, a container cluster, or device-level CLI/SSH network automation.\n\n## Related Skills — Skill Routing\n\n| If the user wants… | Use |\n|--------------------|-----|\n| Cisco Meraki fabric: uplinks, health, config templates, device lifecycle | **fabric-aiops** (this skill) |\n| Cisco Catalyst Center (DNA Center): site/device/client health, issues, inventory | **fabric-aiops** (this skill, `platform: catalyst`) |\n| Arista CloudVision Portal: inventory, compliance drift signal, events | **fabric-aiops** (this skill, `platform: cvp`) |\n| UniFi Network (self-hosted controller / UniFi OS console): site health, alarms, clients, device restart | **fabric-aiops** (this skill, `platform: unifi`) |\n| Cisco ACI (APIC): endpoint location, EPG/BD/VRF/contract chain, fabric faults | **fabric-aiops** (this skill, `platform: aci`) |\n| OT / industrial edge (Modbus, OPC-UA, PLC, PROFINET) | the **industrial-aiops** line |\n| Hypervisor VM lifecycle (power, snapshot, migrate) | a hypervisor ops skill |\n| Container/cluster lifecycle | a cluster ops skill |\n\n## Common Workflows\n\n### \"The branch VPN keeps dropping\" — diagnose degraded WAN uplinks\n\n1. `fabric-aiops health uplink-rca` → worst MX WAN uplinks ranked by avg loss + latency, each citing the measured numbers plus a likely cause and action\n2. `fabric-aiops health uplink-rca --loss-pct 2 --latency-ms 100` → tighten the thresholds if nothing crosses the defaults but users still complain\n3. `fabric-aiops device uplinks` → the raw per-appliance uplink statuses across the org (WAN1/WAN2, active vs failover) behind the ranking — confirm the flagged appliance rather than trusting the summary\n4. `fabric-aiops network alerts <networkId>` → check whether the controller already raised a matching alert (independent corroboration before you touch anything)\n5. **Failure branch**: if the RCA returns no uplink records at all, the org has no appliances reporting uplink telemetry, or the API key lacks org-wide read — run `fabric-aiops doctor` and re-check the org id with `fabric-aiops org list` rather than assuming the WAN is healthy.\n\n### Rank the fleet and fix the worst network's device attributes (reversible)\n\n1. `fabric-aiops overview` → org-level rollup: network count and device status/product mix\n2. `fabric-aiops health score` → composite 0-100 per network, worst first, with every scoring component shown\n3. `fabric-aiops org device-statuses` → find the offline/alerting devices dragging the worst network's score\n4. `fabric-aiops device status <serial>` → confirm the device before changing it\n5. `fabric-aiops remediate update-device <serial> '{\"name\":\"branch-ap-01\"}' --dry-run` → preview the exact `PUT /devices/<serial>` call; then run without `--dry-run` (double confirmation). The real before-state is fetched first and recorded as a faithful inverse\n6. **Failure branch**: wrong attribute or wrong device — `fabric-aiops undo list`, then `fabric-aiops undo apply <id>` restores the captured prior attributes. Re-run `fabric-aiops device status <serial>` to confirm the restore landed rather than trusting the undo's success message.\n\n### Bring a drifted network back to its config template (reversible)\n\n1. `fabric-aiops network list` → the networks in scope and their ids\n2. Pass the template plus its bound networks to `config_template_drift(template=..., networks=[...])` → the settings that deviate, per network\n3. `fabric-aiops network vlans <networkId>` → confirm the drifted VLAN's current values before changing anything\n4. Fix the specific setting — `fabric-aiops remediate update-vlan <networkId> <vlanId> '{\"name\":\"data\"}' --dry-run`, then for real — or re-establish the binding itself: `fabric-aiops remediate bind <networkId> <templateId> --dry-run`, then without `--dry-run` (double confirmation). Both capture the real before-state and record an inverse descriptor (for `bind`, the inverse is unbind or a rebind to the prior template)\n5. **Failure branch**: if the rebind makes things worse, `fabric-aiops undo apply <id>` returns the network to its captured prior binding; `fabric-aiops remediate unbind <networkId>` is the manual escape hatch. Re-run `config_template_drift` to confirm the drift actually cleared instead of trusting the write's success message.\n\n### Stage a replacement device into a branch network\n\n1. `fabric-aiops device inventory` → confirm the replacement serial is in the org inventory and unassigned\n2. `fabric-aiops network get <networkId>` → confirm the target network\n3. `fabric-aiops remediate claim <networkId> <serial> --dry-run` → preview `POST /networks/<networkId>/devices/claim`; then run for real (double confirmation) — the inverse (remove from network) is recorded\n4. `fabric-aiops remediate blink-leds <serial> --duration 30` → low-risk physical confirmation that you are at the right box in the rack\n5. `fabric-aiops health score` → confirm the network's score recovers once the device reports in\n6. **Failure branch**: wrong network — `fabric-aiops undo apply <id>` or `fabric-aiops remediate remove <networkId> <serial>`. Note `fabric-aiops remediate reboot <serial>` is `no undo` by construction (a reboot has no safe inverse); it records only the before-state, so use it last, not as a first response.\n\n### \"This VM can't reach its database\" — reconstruct the ACI path (read-only)\n\n1. `fabric-aiops aci trace --ip <vm-ip>` → the endpoint's attachment (pod / leaf / interface or vPC), its EPG → bridge domain → VRF, the contracts the EPG provides/consumes down to filter entries, and faults whose DN names the EPG or the interface\n2. Read `findings` first (worst-first, each with its signal): an unformed attachment or an unresolved BD/VRF/contract relation is where the configured chain breaks\n3. `fabric-aiops aci trace --ip <db-ip>` → the peer's chain; compare VRFs and whether one EPG provides a contract the other consumes\n4. `fabric-aiops aci faults` → fabric-wide faults worst-first, when the chain itself is clean\n5. **Failure branch**: `notFound` means the fabric has not learned the address now (silent hosts age out) — not that the host is down. A section that is `null` with an entry in `errors` was not read; do not report it as absent. `staticPathResolved: true` is configuration, not proof traffic flows — this is not a reachability test, and vzAny / taboo / preferred-group rules are listed in `notChecked`, not evaluated.\n\n### Offline analysis (no live controller)\n\n1. Export the org's uplink, device-status, and template data to JSON\n2. Feed it straight to the analysis tools — `uplink_loss_and_latency_rca(records=[...])`, `network_health_score(device_statuses=[...])`, `config_template_drift(template=..., networks=[...])` — no connection or credentials required\n3. **Failure branch**: a tool that rejects the injected records means the export is missing fields the analysis needs (loss/latency samples, device status, template settings) — re-export rather than hand-editing, so the findings stay traceable to the controller.\n\n## Governance & Safety\n\nThe skill delivers reads and writes and records them; it does **not** decide\nwhether a write is permitted. That is your agent's judgement, or the permission\nof the account you connect it with (a Meraki API key whose admin has read-only\norganization access — writes then fail at the controller). There is no read-only\nswitch, 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 `~/.fabric-aiops/audit.db` (relocatable via `FABRIC_AIOPS_HOME`): params, result, status, duration, and the risk tier. The CLI writes the same row the MCP path does.\n- `FABRIC_AUDIT_APPROVED_BY` / `FABRIC_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 `FABRIC_RUNAWAY_MAX=0`.\n- Destructive writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI.\n- Mutating/reversible writes fetch the real before-state and record an inverse descriptor (`update_device`/`update_network_vlan`→restore prior values, `claim`↔`remove`, `bind`↔`unbind`/rebind); irreversible ops (`reboot_device`, `blink_device_leds`) record only the before-state.\n\n## References\n\n- `references/capabilities.md` — full tool + field reference\n- `references/cli-reference.md` — CLI command reference\n- `references/setup-guide.md` — onboarding, credentials, and connectivity\n\nFile v0.12.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"fabric-aiops\",\n  \"version\": \"0.12.0\",\n  \"publishedAt\": 1789962986404\n}\n\nFile v0.12.0:references/agent-guardrails.md\n\n# Agent guardrails — running fabric-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\n## Authorization is not this tool's job — decide it where it belongs\n\nWhether a write should happen is your decision, or the account's. The tool does\nnot gate it — there is no read-only switch and no approval prompt to configure.\nThe two right places to control read vs write:\n\n- **The account you connect with.** Give it a Meraki API key whose admin has\n  read-only organization access (or the read-only equivalent on your\n  controller). A write then fails at the controller, which is the only place the\n  permission actually lives — no skill-side flag can be argued around by a model,\n  but a revoked permission cannot be.\n- **Your agent's system prompt.** If you want an observe-only session, tell the\n  model not to call the write tools (they are clearly tagged `[WRITE]`).\n\nWhat the tool *does* guarantee is that you can always see what happened:\n\n## What the tool enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Log everything you do, over both MCP and the CLI\" | Every call is audited to `~/.fabric-aiops/audit.db` regardless of what the model says it did — and the CLI writes the same row the MCP path does, so there is no unaudited entry point. Reversible writes also record an undo token capturing the *prior* state. |\n| \"Don't invent a value when a field is missing\" | A field the controller did not return comes back as `null`, never as `\"\"`. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | Anything with a `limit` returns `{\"<items>\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}`, where `<items>` names what was listed — `devices`, `alerts`, `topApplications`, `worst`, `driftedNetworks` or `undos`; on ACI, `endpoints`, `faults`, `contracts` or `entries`. Read the key the tool documents rather than assuming `devices`. Truncation is measured against the full result, not guessed from a length coincidence. |\n| \"Preserve the ordering / tell me what's most urgent\" | The ranked analyses return worst-first and carry the numbers that produced each ranking (`avgLossPct`, `score`, `alertPenalty`), so priority is in the payload rather than implied by list position. The ACI reads carry an explicit `rank` on findings and on `aci_faults_list` rows; related-fault candidates are sorted active-first but unranked. |\n| \"Confirm before anything destructive\" | Destructive operations require a `--dry-run`-able preview + double confirmation at the CLI. |\n| \"Don't get stuck retrying\" | The runaway guard trips a circuit breaker if the same call is hammered in a tight loop — a stuck agent is stopped rather than left to burn calls and time. |\n| \"Don't guess at an unsupported platform\" | An operation a platform does not map raises a teaching `PlatformUnsupported` error naming the platform — never a silent no-op the model can mistake for success. |\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 a network fabric through its CONTROLLER API using the fabric-aiops\nMCP tools (Cisco Meraki Dashboard, Cisco Catalyst Center, Arista CloudVision\nPortal, UniFi Network, or Cisco ACI, depending on the configured target).\n\nTOOL USE\n- Before answering any question about the current fabric, you MUST call a tool.\n  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.\n- If a tool returns \"not supported on <platform> yet\", say so. Do not substitute\n  a different tool and present its output as the answer to the original question.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result has \"truncated\": true,\n  say so and re-run with a higher limit instead of treating the partial result\n  as complete.\n- A null field means the controller did not return that value. Report it as\n  \"not available\" — never infer it.\n- Report values exactly as returned. Do not normalise, translate, or prettify\n  status strings, severities, model names, or identifiers.\n- In the ranked analyses, work worst-first and cite the measured number\n  (avgLossPct, avgLatencyMs, score, alertPenalty) behind each ranking.\n\nIDENTIFIERS — keep these straight, they are not interchangeable\n- An ORGANIZATION id scopes the whole account (on Catalyst Center, CVP, and\n  UniFi a site/container stands in for it).\n- A NETWORK id names one site/branch inside an organization.\n- A DEVICE SERIAL names one physical device. It is not a device name, not a MAC,\n  and not a network id.\n- An UPLINK names a WAN interface on one appliance (e.g. wan1/wan2), scoped to\n  that device's serial — an uplink is never addressed on its own.\n- Never pass an organization id where a network id is expected, or a device name\n  where a serial is expected. If you do not have the right id, call the list\n  tool that returns it (org_list, network_list, device_inventory) first.\n\nCISCO ACI (aci_* tools)\n- aci_endpoint_trace is NOT a reachability test. \"staticPathResolved\": true\n  means the fabric is configured to carry the endpoint — never say traffic flows.\n- relatedFaultCandidates are matched by DN only. Never present one as the cause\n  of a problem; call them candidates. If its \"faults\" is null, no scan\n  succeeded: say related faults are unknown, never \"no faults\".\n- tagRelations in state \"missing-target\" are policy-tag lookups. They are not a\n  path or attachment failure — do not report them as one.\n- A section that is null with an entry in \"errors\" was NOT read. Say it could\n  not be read; never describe it as empty or absent.\n- A cleared fault keeps the description it had when raised. Judge it by\n  severity and lifecycle, not by its text.\n- Fault rows are records, not incidents: a \"delegated\": true row mirrors a\n  fault on another object. Do not count the pair as two problems.\n- \"notFound\" means the fabric has not learned the address now, or it sits in a\n  tenant this account cannot see — not that the host is down.\n- Anything listed in \"notChecked\" (vzAny, taboo, imported contracts, preferred\n  groups, service graphs) was not evaluated; do not claim it allows or blocks\n  traffic.\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 connectivity, capacity, or availability problem unless a tool\n  result supports it.\n- Do not add generic advice that does not follow from the tool output.\n```\n\n## Recommended setup for a local model\n\nStart with a connection that *cannot* write, verify, and widen the account's\npermission only when you trust the setup — the fleet-affecting operations here\n(`reboot_device`, `remove_device_from_network`, `bind_network_to_template`) hit\nproduction hardware and live networks:\n\n```bash\n# e.g. use a Meraki API key whose admin has read-only organization access. Then:\nfabric-aiops doctor\n```\n\nOptionally annotate the audit trail with who is operating and why — recorded on\nevery row, never required:\n\n```bash\nexport FABRIC_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport FABRIC_AUDIT_RATIONALE=\"scheduled maintenance window 2026-07-20\"\n```\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 `overview` and the three\n  flagship analyses (`uplink_loss_and_latency_rca`, `network_health_score`,\n  `config_template_drift`) — they do the multi-step correlation inside one call,\n  so the model does not have to chain reads and keep org/network/serial ids\n  straight across turns.\n- **The model ignores later tool results in a long context.** Ask narrower\n  questions and use `--limit` deliberately rather than pulling a whole org\n  inventory in one go.\n- **The model confuses sites with networks on Catalyst Center / CVP / UniFi.**\n  On those platforms a site or container stands in for both the organization and\n  the network level. Tell the model which one your target is scoped to.\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/Fabric-AIops](https://github.com/AIops-tools/Fabric-AIops/issues)\nwith the model, runtime, and what went wrong.\n\nFile v0.12.0:references/capabilities.md\n\n# fabric-aiops capabilities\n\n> 37 MCP tools (28 read, 9 write) over five platforms —\n> Cisco Meraki Dashboard (reference, full read+write), Cisco Catalyst Center\n> (read subset), Arista CloudVision Portal (read subset), UniFi Network (read\n> subset + device restart), Cisco ACI APIC (three ACI-native reads). The first\n> four platforms' API paths are modelled from the public API shapes and need live\n> verification; the ACI reads are built against real, anonymized APIC responses.\n> Community-maintained; not affiliated with Cisco/Meraki/Arista/Ubiquiti.\n\nMeraki hierarchy: **organizations → networks → devices**. Device models carry a\nproduct-type prefix: **MX** appliance, **MS** switch, **MR** wireless AP, **MV**\ncamera, **MG** cellular gateway.\n\n**Multi-platform**: the tables below show the reference (Meraki) API per tool.\nOn `catalyst`, canonical organizations/networks are **sites**\n(`/dna/intent/api/v1/site`, `site-health`), device statuses come from\n`device-health`, alerts from `issues` (P1→critical, P2→warning), inventory from\n`network-device`, switch ports from per-device `interface` stats (pass the\ndevice uuid), and clients from `client-health` (aggregate) / `client-detail`\n(by MAC). On `cvp`, organizations/networks are **containers**\n(`/cvpservice/inventory/containers`), devices come from\n`/cvpservice/inventory/devices` (rows carry the `complianceCode` config-drift\nsignal), alerts from `getAllEvents.do`, and admins from `getUsers.do`.\nOn `unifi`, organizations/networks are **sites** (`/api/self/sites`; the\ncanonical id is the site's short name — the `/api/s/{site}/` path segment),\ndevice inventory/statuses come from `stat/device` (state 1 → online; uptime,\nfirmware), switch ports from the device detail's `port_table` (pass the device\n**MAC** where Meraki takes a serial), clients from `stat/sta` / `stat/user`,\nalerts from `stat/alarm` (`*_Lost_Contact` → critical), `network_get` from\n`stat/health` (per-subsystem rollup), and `reboot_device` maps to\n`POST /api/s/{site}/cmd/devmgr {\"cmd\": \"restart-device\", \"mac\": ...}` — the\nonly non-Meraki write. Device-scoped calls fill the site from the target's\ndefault `org_id`. Auth is a UniFi API key (`X-API-KEY`); a UniFi OS console's\n`base_url` carries the `/proxy/network` prefix.\nAny tool a platform does not map — and **every write on catalyst/cvp (on\nunifi, every write except reboot)** — returns a teaching \"not supported on\n<platform> yet — open an issue or PR\" error instead of a silent no-op. The\nfull per-op matrix is in the repo README.\n\n## Read tools (28)\n\n### Overview + organizations\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `overview` | `/organizations/{id}/networks` + `/devices/statuses` | organizationId, networks, devicesTotal, devicesByStatus, devicesByProductType |\n| `org_list` | `GET /organizations` | id, name, url, apiEnabled |\n| `org_get` | `GET /organizations/{id}` | one org detail |\n| `org_licensing` | `GET /organizations/{id}/licenses/overview` | status, expiration, per-device-type counts |\n| `org_admins` | `GET /organizations/{id}/admins` | name, email, access level |\n| `org_device_statuses` | `GET /organizations/{id}/devices/statuses` | total, byStatus, byProductType, devices[] |\n| `org_api_requests` | `GET /organizations/{id}/apiRequests/overview` | totalRequests, rateLimited429, responseCodeCounts |\n\n### Networks\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `network_list` | `GET /organizations/{id}/networks` | id, name, productTypes, tags |\n| `network_get` | `GET /networks/{id}` | one network detail |\n| `network_vlans` | `GET /networks/{id}/appliance/vlans` | id, subnet, applianceIp |\n| `network_alerts` | `GET /networks/{id}/health/alerts` | total, bySeverity, alerts[] |\n| `network_traffic` | `GET /networks/{id}/traffic` | applicationCount, topApplications[] (by bytes) |\n\n### Devices\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `device_inventory` | `GET /organizations/{id}/devices` | total, byModelFamily, matched, devices[] (filterable by model) |\n| `device_status` | `GET /organizations/{id}/devices/statuses` | one device's status row |\n| `device_uplinks` | `GET /organizations/{id}/uplinks/statuses` | appliance/gateway WAN uplink statuses |\n| `switch_ports` | `GET /devices/{serial}/switch/ports` | MS port configuration |\n| `wireless_ssids` | `GET /networks/{id}/wireless/ssids` | MR SSIDs (number, name, enabled) |\n\n### Clients\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `client_list` | `GET /networks/{id}/clients` | clients seen in the window |\n| `client_get` | `GET /networks/{id}/clients/{clientId}` | description, MAC, IP, VLAN, manufacturer |\n| `client_usage` | `GET .../clients/{clientId}/usageHistory` | samples, totalSentKb, totalReceivedKb, totalKb |\n| `client_connectivity` | `GET .../clients/{clientId}/connectionStats` | assoc, auth, dhcp, dns, success |\n\n### Health (flagship)\n| Tool | Source | Returns |\n|------|--------|---------|\n| `uplink_loss_and_latency_rca` | `GET /organizations/{id}/devices/uplinksLossAndLatency` or injected `records` | uplinksEvaluated, degradedCount, thresholds, worst[]{serial, uplink, avgLossPct, avgLatencyMs, degraded, cause, action}, note |\n| `network_health_score` | injected only | networksEvaluated, fleetScore, summary, weights, worst[]{networkId, score, band, onlinePct, uplinkHealthPct, alertPenalty}, note |\n| `config_template_drift` | injected only | templateId, boundNetworks, driftedCount, compliantCount, settingsChecked, driftedNetworks[]{networkId, deviations[]}, note |\n\n`uplink_loss_and_latency_rca` accepts `records=` for offline analysis or pulls\nlive from a `target`/`org_id`. `network_health_score` and `config_template_drift`\nare injected-only (they score data you already hold, e.g. from\n`org_device_statuses` / `device_uplinks`).\n\n### Cisco ACI (APIC targets only)\n\nACI maps **no canonical operation** — the tools above answer an `aci` target\nwith a teaching error. These three take ACI references instead:\n\n| Tool | APIC queries (all GET) | Returns |\n|------|------------------------|---------|\n| `aci_endpoint_trace` | `class/fvCEp` by `eq(fvCEp.mac,…)` + `rsp-subtree=full` (or `class/fvIp` by `eq(fvIp.addr,…)`, then the owning `fvCEp`); the EPG / BD / VRF / contract / filter reads of `aci_epg_segment`; `faultInst` under the EPG and under each attachment leaf | `endpoints[]` (`returned/limit/truncated`), each with `attachment` (pod, nodes, interface or vPC, `state`, `tCl` as sent), `tagRelations` (listed apart — never a path verdict), `epg`/`bd`/`vrf`/`contracts`, `relatedFaultCandidates` (DN-matched, active first), `staticPathResolved`, ranked `findings`, `errors`, `notChecked`; `notFound` when the address is not learned |\n| `aci_epg_segment` | `mo/<epg>` `rsp-subtree=children&rsp-subtree-class=fvRsBd,fvRsProv,fvRsCons,fvRsConsIf,fvRsProtBy`; `mo/<bd>` (`fvRsCtx,fvSubnet`); `mo/<vrf>`; `mo/<contract>` `query-target=subtree&target-subtree-class=vzBrCP,vzSubj,vzRsSubjFiltAtt,vzInTerm,vzOutTerm,vzRsFiltAtt`; `mo/<filter>` `target-subtree-class=vzEntry` | `epg`, `bd` (subnets), `vrf` (`policyEnforcement`), `contracts` (subjects → filters with action/direction → entries), `segmentResolved`, ranked `findings`, `errors`, `notChecked` |\n| `aci_faults_list` | `class/faultInst` by `eq(faultInst.severity,…)`, one query per level in severity order, `page-size` = what is still needed + 1 | `faults[]` (`rank`, `active` from severity, `delegated`, `scope`/`pod`/`node`/`aboutDn`), `returned/limit/truncated`, `bySeverity.serverReported`, `delegatedRecords` |\n\nEvery link is the relation APIC resolved (`tDn`), so cross-tenant links into\n`common` are followed. A failed EPG / BD / VRF read leaves its section `null`\nwith an entry in `errors` and `segmentResolved`/`staticPathResolved` `null` —\nnever an empty section. A failed contract read stays in the list as\n`{\"dn\": …, \"read\": false}` with `contracts.complete: false`; if no fault scan\nsucceeds, `relatedFaultCandidates.faults` is `null`, not `[]`. A 2xx that is not\nan APIC response (no `imdata` — e.g. a proxy login page) is an error, never an\nempty result. An empty APIC answer is reported as \"does not exist, or not\nvisible to this account's security domain\" — APIC answers both the same way. Not evaluated: vzAny, taboo contracts, imported contract interfaces,\npreferred-group peers, service graphs / L3Out. Leaf/spine inventory and\ninterface state are not implemented yet.\n\n### Undo\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `undo_list` | _(local `undo.db`, no API call)_ | recorded, not-yet-applied reversible writes: undoId, original tool, inverse tool, note |\n\n## Write tools (9) — all support `dry_run`; CLI adds double-confirm\n\n| Tool | Risk | Meraki API path | Undo / safety |\n|------|------|----------------------|---------------|\n| `reboot_device` | **high** | `POST /devices/{serial}/reboot` (unifi: `POST /api/s/{site}/cmd/devmgr` `{\"cmd\": \"restart-device\", \"mac\": ...}`) | captures prior status; no safe inverse, no undo |\n| `claim_devices_into_network` | **high** | `POST /networks/{id}/devices/claim` | inverse = remove the claimed serials |\n| `remove_device_from_network` | **high** | `POST /networks/{id}/devices/remove` | inverse = claim it back into the network |\n| `bind_network_to_template` | **high** | `POST /networks/{id}/bind` | captures the prior binding; inverse = rebind prior / unbind |\n| `unbind_network_from_template` | **high** | `POST /networks/{id}/unbind` | captures the prior template; inverse = rebind to it |\n| `update_device` | medium | `PUT /devices/{serial}` | fetches + captures the changed keys' prior values; inverse = restore them |\n| `update_network_vlan` | medium | `PUT /networks/{id}/appliance/vlans/{vlanId}` | fetches + captures prior values; inverse = restore them |\n| `blink_device_leds` | low | `POST /devices/{serial}/blinkLeds` | locator aid; no config change, no undo |\n| `undo_apply` | medium | _(local `undo.db`, then dispatches the recorded inverse tool)_ | executes a recorded inverse — itself governed and audited, single-use |\n\n## Out of scope (by design)\n\n- Full org/network **provisioning** workflows (create org, create network)\n- Firmware upgrade orchestration\n- SSID/switch-port config CRUD beyond the writes above\n- OT / industrial equipment (use the `industrial-aiops` line) and device-level\n  CLI/SSH network automation\n\n- On **catalyst/cvp/unifi**: the unmapped reads in the matrix (licensing,\n  VLANs, traffic, uplink telemetry, ...), the unmapped writes (all on\n  catalyst/cvp; all but reboot on unifi), CVP configlet-content retrieval,\n  Catalyst Center per-client listing, UniFi legacy cookie login\n  (`POST /api/login` — use an API key) and blink-LED (`set-locate` has no\n  bounded duration), and deep pagination\n\nWant one of these — a missing Meraki call, a ❌ filled in on Catalyst Center,\nCloudVision Portal, or UniFi Network (writes included), or another controller\nplatform entirely? Open an issue or PR — feedback and contributions welcome (a\nplatform is one descriptor module: path templates + response adapters).\n\nFile v0.12.0:references/cli-reference.md\n\n# fabric-aiops CLI reference\n\n> Controller API paths (Meraki / Catalyst Center / CVP / UniFi Network) are\n> modelled from the public API shapes and have not yet been exercised live\n> (see docs/VERIFICATION.md). Not affiliated with Cisco/Meraki/Arista/Ubiquiti.\n\n## Setup & diagnostics\n\n```bash\nfabric-aiops init                      # interactive onboarding wizard (platform: meraki/catalyst/cvp/unifi)\nfabric-aiops doctor [--skip-auth]      # config + secret store + connectivity (canonical org/site/container probe)\nfabric-aiops mcp                       # start the MCP server (stdio transport)\n```\n\n## Secrets (encrypted store ~/.fabric-aiops/secrets.enc)\n\n```bash\nfabric-aiops secret set <target> [--value <key>]   # store API key (hidden prompt if no --value)\nfabric-aiops secret list                            # names only — values never shown\nfabric-aiops secret rm <target>\nfabric-aiops secret migrate                         # import legacy plaintext .env (FABRIC_<T>_APIKEY)\nfabric-aiops secret rotate-password                 # re-encrypt under a new master password\n```\n\n## Read commands\n\n```bash\nfabric-aiops overview [--org-id <id>] [--target <t>]   # networks + device status/product rollup\n\nfabric-aiops org list                                  # organizations visible to the key\nfabric-aiops org get [--org-id <id>]\nfabric-aiops org licensing [--org-id <id>]\nfabric-aiops org admins [--org-id <id>]\nfabric-aiops org device-statuses [--org-id <id>]       # online/offline/alerting rollup\nfabric-aiops org api-usage [--org-id <id>]             # response-code counts, 429 rate-limits\n\nfabric-aiops network list [--org-id <id>]\nfabric-aiops network get <networkId>\nfabric-aiops network vlans <networkId>\nfabric-aiops network alerts <networkId>                # health alerts by severity\nfabric-aiops network traffic <networkId> [--timespan 86400]\n\nfabric-aiops device inventory [--model MS] [--org-id <id>]   # MX/MS/MR/MV/MG\nfabric-aiops device status <serial> [--org-id <id>]\nfabric-aiops device uplinks [--org-id <id>]\nfabric-aiops device switch-ports <serial>              # MS ports\nfabric-aiops device ssids <networkId>                  # MR SSIDs\n\nfabric-aiops client list <networkId> [--timespan 86400]\nfabric-aiops client get <networkId> <clientId>\nfabric-aiops client usage <networkId> <clientId>\nfabric-aiops client connectivity <networkId> <clientId>\n\nfabric-aiops health uplink-rca [--loss-pct 5] [--latency-ms 150] [--org-id <id>]   # flagship RCA\nfabric-aiops health score [--org-id <id>]              # composite per-network health from live data\n\n# Cisco ACI targets (platform: aci) — read-only, ACI-native references\nfabric-aiops aci trace --mac <mac> | --ip <ip> [--limit 5]   # endpoint → leaf/interface → EPG → BD → VRF → contracts\nfabric-aiops aci segment <tenant> <app> <epg>                # an EPG's BD, VRF and contracts\nfabric-aiops aci faults [--severity critical] [--include-cleared] [--limit 50]   # worst-first\n```\n\n## Write commands (governed; risk tier in parentheses)\n\n```bash\nfabric-aiops remediate reboot <serial> [--dry-run]                       # (high) no undo; double confirm\nfabric-aiops remediate blink-leds <serial> [--duration 20]               # (low)  locator aid\nfabric-aiops remediate update-device <serial> '{\"name\":\"ap1\"}' [--dry-run]   # (medium) captures before\nfabric-aiops remediate update-vlan <networkId> <vlanId> '{\"name\":\"data\"}' [--dry-run]  # (medium)\nfabric-aiops remediate claim <networkId> <serial...> [--dry-run]         # (high) inverse = remove\nfabric-aiops remediate remove <networkId> <serial> [--dry-run]           # (high) inverse = claim back\nfabric-aiops remediate bind <networkId> <templateId> [--auto-bind] [--dry-run]   # (high) captures prior binding\nfabric-aiops remediate unbind <networkId> [--dry-run]                    # (high) captures prior template\n```\n\n## Common options\n\n- `--target, -t <name>` — target name from `config.yaml` (omit to use the default/first target)\n- `--org-id, -o <id>` — Meraki organization id (omit to use the target's default `org_id`)\n- `--dry-run` — print the API call that would be made, change nothing\n- State-changing commands require two confirmations (except `blink-leds`, low risk)\n\nFile v0.12.0:references/setup-guide.md\n\n# fabric-aiops setup & security guide\n\n> Not yet exercised against a live controller of any platform (Meraki\n> organization, Catalyst Center appliance, CloudVision Portal instance, or\n> UniFi controller) — see docs/VERIFICATION.md. Community-maintained; not affiliated\n> with or endorsed by Cisco/Meraki/Arista/Ubiquiti.\n\n## 1. Install\n\n```bash\nuv tool install fabric-aiops\n```\n\n## 2. Create the platform credential\n\n**Cisco Meraki Dashboard (`platform: meraki`)** — in the Dashboard:\n**Organization → Settings → API access → Generate API key**. Copy the key.\nfabric-aiops sends it as `Authorization: Bearer <key>` (or, with\n`auth_style: meraki-key`, `X-Cisco-Meraki-API-Key`) against the Dashboard API\nbase `https://api.meraki.com/api/v1`.\n\n**Cisco Catalyst Center (`platform: catalyst`)** — use a Catalyst Center\naccount (a read-only role suffices for the current read subset) and store the\nsecret as a single `username:password` string. fabric-aiops exchanges it via\n`POST /dna/system/api/v1/auth/token` (HTTP Basic) for a short-lived (~1 h)\n`X-Auth-Token`, attached per request and auto-refreshed once on a 401. A\n`base_url` is required (`https://<catalyst-center-host>`).\n\n**Arista CloudVision Portal (`platform: cvp`)** — create a service-account\ntoken in CloudVision: **Settings → Access Control → Service Accounts**.\nfabric-aiops sends it as `Authorization: Bearer <token>`. A `base_url` is\nrequired (`https://<cvp-host>`).\n\n**UniFi Network (`platform: unifi`)** — create an **API key** in the UniFi\nconsole (UniFi OS: **Settings → Control Plane → Integrations**; self-hosted\nNetwork Server 9.0+: the admin's API-key page). fabric-aiops sends it as\n`X-API-KEY` on every request (stateless). The legacy cookie login\n(`POST /api/login`) is **not** supported — use an API key. A `base_url` is\nrequired and encodes the controller layout:\n- classic self-hosted controller: `https://<host>:8443`\n- UniFi OS console (UDM / UDM-Pro / Cloud Key Gen2):\n  `https://<console>/proxy/network` — keep the `/proxy/network` suffix; every\n  API path is issued relative to it.\n\nSet the target's `org_id` to the site's short name (e.g. `default`) —\ndevice-scoped calls (device get, switch ports, restart) use it as the\n`/api/s/{site}/` scope.\n\n**Cisco ACI (`platform: aci`)** — use an APIC local or remote user whose role is\n**read-only** (every ACI read is a GET; only the login is a POST) and whose\nsecurity domains cover the tenants you want to trace. An object outside them\nmay come back as an empty answer — reported as \"does not exist, or not visible\nto this account\" because APIC answers both the same way — or as a 403, reported\nas a privilege problem, not an expired session. After a refused login the tool\nwaits 60 s before sending the password again, so a changed password cannot turn\ninto one login attempt per read. Store\nthe secret as a single `username:password` string. fabric-aiops logs in via\n`POST /api/aaaLogin.json`, carries the session cookie APIC returns, extends the\nsession via `/api/aaaRefresh.json` at half its `refreshTimeoutSeconds`, and logs\nin again once if APIC answers 401/403. A `base_url` is required\n(`https://<apic-host>`); `org_id` is not used. ACI answers the Meraki-shaped\ntools with a teaching error — use `fabric-aiops aci trace | segment | faults`.\n\n## 3. Onboard\n\n```bash\nfabric-aiops init\n```\n\nThe wizard asks for the platform (`meraki` / `catalyst` / `cvp` / `unifi`), collects\n(non-secret) connection details into `~/.fabric-aiops/config.yaml`, and stores\nthe secret **encrypted** into `~/.fabric-aiops/secrets.enc`. Example config:\n\n```yaml\ntargets:\n  - name: org1\n    platform: meraki\n    org_id: \"123456\"            # default organization id (optional)\n    verify_ssl: true\n    # base_url: https://api.meraki.eu/api/v1   # override only for a region/proxy\n    # auth_style: meraki-key                    # use X-Cisco-Meraki-API-Key instead of Bearer\n  - name: campus\n    platform: catalyst\n    base_url: https://catalyst.example.com     # required (per-install)\n    org_id: \"site-uuid\"          # default site id (optional)\n    # verify_ssl: false          # only for self-signed lab controllers\n  - name: dc-fabric\n    platform: cvp\n    base_url: https://cvp.example.com          # required (per-install)\n    org_id: \"root\"               # default container key (optional)\n  - name: home-lab\n    platform: unifi\n    base_url: https://unifi.example.com:8443   # classic controller\n    # base_url: https://console.example.com/proxy/network   # UniFi OS console\n    org_id: \"default\"            # site short name (fills /api/s/{site}/ scopes)\n```\n\n## 4. Non-interactive use (MCP server / CI / cron)\n\nExport the master password so the encrypted store can be unlocked without a\nprompt:\n\n```bash\nexport FABRIC_AIOPS_MASTER_PASSWORD='your-master-password'\n```\n\n## Credential security\n\n- The controller secret (Meraki API key / Catalyst Center `username:password`\n  / CVP service-account token / UniFi API key) is **never** written to disk in plaintext. It lives only in\n  `~/.fabric-aiops/secrets.enc`, encrypted with Fernet (AES-128-CBC + HMAC),\n  the key derived from your master password via scrypt. Only a per-store random\n  salt and the ciphertext are on disk (chmod 600); the master password itself is\n  never stored.\n- A legacy plaintext env var `FABRIC_<TARGET_NAME_UPPER>_APIKEY` is still honoured\n  as a fallback with a deprecation warning — migrate with `fabric-aiops secret\n  migrate` (it imports then renames the old `.env`).\n- The key is held only in memory during a session and is never logged or echoed;\n  exception text and tracebacks are scrubbed of secret-shaped strings before\n  being written to the audit log.\n\n## Audit-annotation env vars (optional)\n\nThe skill does not decide whether a write is permitted — that is the agent's\njudgement or the connecting controller account's role. If you want the audit\ntrail to record *who* ran a destructive op and *why*, set these; they are\nrecorded on the row, never required, and gate nothing:\n\n```bash\nexport FABRIC_AUDIT_APPROVED_BY='you@example.com'\nexport FABRIC_AUDIT_RATIONALE='why this destructive op is justified'\n```\n\n## Governance harness state\n\nState lives under `~/.fabric-aiops/` (relocate with `FABRIC_AIOPS_HOME`):\n\n- `audit.db` — every tool call (SQLite), with risk tier and any approver/rationale\n- `undo.db` — inverse descriptors for reversible writes (e.g. `update_device`,\n  `bind_network_to_template`)\n- budget / runaway guard — caps cumulative tool calls and wall-time; trips on\n  tight poll/retry loops (also your first line of defense against Dashboard API\n  rate limits)\n\n## Verify\n\n```bash\nfabric-aiops doctor\n```\n\n`doctor` checks the config file, the encrypted store and its permissions, that a\nsecret (and, for on-prem platforms, a `base_url`) is present per target, and\n(unless `--skip-auth`) connectivity via the canonical top-of-hierarchy read —\nMeraki organizations, Catalyst Center sites, CVP containers, or UniFi sites —\nwhich also exercises the platform's full auth flow (including the Catalyst\nCenter session-token exchange and, on unifi, the `X-API-KEY` header against\nthe configured base URL — the fastest way to confirm a UniFi OS console's\n`/proxy/network` prefix is right).\n\nFile v0.12.0:skill-card.md\n\n## Description:\n\nfabric-aiops helps agents operate and analyze controller-managed network fabrics across Cisco Meraki, Catalyst Center, Arista CloudVision, UniFi Network, and Cisco ACI, including health triage, read-only inventory, ACI tracing, and governed write workflows where supported.\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 engineers and operations teams use this skill to inspect controller-managed network fabrics, rank fabric health issues, trace Cisco ACI endpoint paths, and run governed remediation commands when their controller account permits writes. It is intended for controller API workflows, not OT equipment, device-level CLI automation, hypervisors, storage appliances, or cluster orchestrators.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can perform high-impact network changes and does not provide a built-in read-only mode or approval gate for agent-driven MCP use.\n\nMitigation: Prefer a read-only controller account first and treat MCP access as write-capable unless controller permissions block writes.\n\nRisk: Controller credentials grant access to production network APIs.\n\nMitigation: Avoid broad admin API keys, keep FABRIC_AIOPS_MASTER_PASSWORD out of shell history and logs, and rotate or scope credentials according to the controller's own access controls.\n\nRisk: Write operations can affect live network devices and configuration.\n\nMitigation: Use dry-run previews and CLI confirmation for writes, verify target identifiers before execution, and rely on controller permissions for final authorization.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/fabric-aiops)\n- [Fabric AIops repository](https://github.com/AIops-tools/Fabric-AIops)\n- [Capabilities reference](references/capabilities.md)\n- [CLI reference](references/cli-reference.md)\n- [Setup and security guide](references/setup-guide.md)\n- [Agent guardrails](references/agent-guardrails.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Text or Markdown with shell commands, configuration snippets, and structured controller results]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include live or injected controller analysis results, risk-tiered remediation previews, audit guidance, and undo-related instructions.]\n\n## Skill Version(s):\n\n0.12.0 (source: server release metadata, released 2026-09-21T03:56:26Z)\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.11.5: 7 files, 21116 bytes\n\nFiles: references/agent-guardrails.md (7839b), references/capabilities.md (8457b), references/cli-reference.md (3845b), references/setup-guide.md (6207b), skill-card.md (2717b), SKILL.md (18452b), _meta.json (132b)\n\nFile v0.11.5:SKILL.md\n\n---\nname: fabric-aiops\nslug: fabric-aiops\ndisplayName: \"Fabric AIops\"\nsummary: \"Governed Cisco Meraki fabric ops: uplink RCA, health score, drift; 34 tools with audit/undo.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Fabric-AIops\ntags: [aiops, mcp, governance, fabric]\ndescription: >\n  Use this skill whenever the user needs to operate a network fabric through a controller API — Cisco Meraki Dashboard (full read+write), Cisco Catalyst Center / DNA Center (read subset), Arista CloudVision Portal / CVP (read subset), or UniFi Network (self-hosted controller / UniFi OS console; read subset + device restart) — a one-shot fabric health overview; organization/site/container reads (list/get, licensing, admins, org-wide device statuses, API usage); network reads (list/get, VLANs, health alerts, traffic); device reads (inventory by model MX/MS/MR/MV/MG, status, uplinks, switch ports / interface stats, wireless SSIDs); client reads (list, detail, usage, connectivity); three flagship analyses — uplink loss & latency RCA (rank worst MX WAN uplinks + cause/action), network health score (composite per-network), and config template drift (settings drifted from a bound template); and eight guarded writes (reboot, blink LEDs, update device, update VLAN, claim/remove devices, bind/unbind a config template — Meraki-only except device restart, which unifi also maps; other unmapped writes return a teaching \"not supported yet\" error).\n  Always use this skill for \"Meraki org overview\", \"which uplinks are worst\", \"uplink loss and latency\", \"WAN degradation RCA\", \"network health score\", \"config template drift\", \"list Meraki networks/devices/clients\", \"reboot a Meraki device\", \"blink device LEDs\", \"claim a device into a network\", \"bind a network to a template\", \"Catalyst Center site health / device health / issues\", \"DNA Center inventory\", \"CloudVision inventory / compliance / events\", \"UniFi site health / alarms / clients\", \"restart a UniFi AP or switch\" when the context is a controller-managed network fabric.\n  Do NOT use when the target is OT / industrial equipment (Modbus, OPC-UA, PLCs — use industrial-aiops), a hypervisor, a storage appliance, a backup product, a container/cluster orchestrator, or device-level CLI/SSH network automation (negative routing hints only).\n  Covers common controller fabric operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers). The test suite is mock-based; no platform has yet been exercised against a live controller (see docs/VERIFICATION.md).\ninstaller:\n  kind: uv\n  package: fabric-aiops\nargument-hint: \"[org/network/device id or describe your fabric task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"fabric-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"FABRIC_AIOPS_CONFIG\",\"FABRIC_AIOPS_MASTER_PASSWORD\"]},\"homepage\":\"https://github.com/AIops-tools/Fabric-AIops\",\"emoji\":\"🛰️\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed network-fabric controller operations. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency. Multi-platform by construction (a platform registry): meraki (Cisco Meraki Dashboard, reference platform, full read+write), catalyst (Cisco Catalyst Center, read subset — sites stand in for organizations/networks), cvp (Arista CloudVision Portal, read subset — containers stand in for organizations/networks), and unifi (UniFi Network controller / UniFi OS console, read subset — sites stand in for organizations/networks — plus the device-restart write via a cmd/devmgr command envelope). Unmapped ops raise a teaching \"not supported on <platform> yet\" error; all writes are Meraki-only except UniFi device restart.\n  All write operations are audited to a local SQLite DB under ~/.fabric-aiops/ (relocatable via FABRIC_AIOPS_HOME).\n  Credentials: the controller secret (Meraki API key / Catalyst Center username:password / CVP service-account token / UniFi API key) is stored ENCRYPTED in ~/.fabric-aiops/secrets.enc (Fernet/AES-128 + scrypt-derived key) — never plaintext on disk. Run 'fabric-aiops init' to onboard, or 'fabric-aiops secret set <target>' to add one. The store is unlocked by a master password from FABRIC_AIOPS_MASTER_PASSWORD (non-interactive/MCP/CI) or an interactive prompt (CLI on a TTY). A legacy plaintext env var FABRIC_<TARGET_NAME_UPPER>_APIKEY is still honoured as a fallback with a deprecation warning (migrate with 'fabric-aiops secret migrate'). Meraki/CVP/UniFi secrets ride the platform auth header (Authorization: Bearer, X-Cisco-Meraki-API-Key, or UniFi's X-API-KEY) at request time; the Catalyst Center secret is exchanged via POST /dna/system/api/v1/auth/token for a short-lived X-Auth-Token (auto-refreshed once on 401). UniFi legacy cookie login (POST /api/login) is not implemented — use an API key (UniFi OS console or self-hosted Network Server 9.0+; a UniFi OS console's base_url carries the /proxy/network prefix). Secrets are held only in memory and never logged or echoed.\n  State-changing operations require double confirmation at the CLI layer and support --dry-run. All write tools pass through the @governed_tool decorator (pre-check + budget guard + audit + risk-tier label) and take a dry_run preview. Mutating/reversible writes fetch the real before-state first and record a faithful inverse undo descriptor; irreversible ops (reboot, blink) record only the before-state.\n  Webhooks: none — no outbound network calls beyond the configured controller REST API base URL.\n  SSL: verify_ssl defaults to true; disable only for a self-signed on-prem controller proxy.\n  Transitive dependencies: httpx (HTTP client) and the MCP SDK. No post-install scripts or background services.\n  Verification status: the test suite is mock-based; the Dashboard API paths are modelled from the public API shape and have not yet been exercised live — docs/VERIFICATION.md defines the checklist. Community-maintained; not affiliated with or endorsed by Cisco/Meraki — trademarks belong to their owners.\n---\n\n# Fabric AIops\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or sponsored by Cisco, Meraki, Arista, Ubiquiti, or any network-controller vendor.** Product and trademark names belong to their owners. Source at [github.com/AIops-tools/Fabric-AIops](https://github.com/AIops-tools/Fabric-AIops) under the MIT license.\n\nGoverned network-fabric controller operations — **34 MCP tools** over **four platforms** (Cisco Meraki Dashboard: full read+write; Cisco Catalyst Center and Arista CloudVision Portal: read subsets; UniFi Network: read subset + device restart), every one wrapped with the bundled `@governed_tool` harness: a local unified audit log under `~/.fabric-aiops/`, token/runaway budget guard, undo-token recording, and descriptive risk tiers. The controller secret is stored **encrypted** (`~/.fabric-aiops/secrets.enc`, Fernet + scrypt) — never plaintext on disk.\n\n> **Standalone**: the governance harness is bundled in the package (`fabric_aiops.governance`) — fabric-aiops has no external skill-family dependency. The test suite is mock-based; no platform has yet been exercised against a live controller (see `docs/VERIFICATION.md`).\n\n## Platform support\n\n| Platform | `platform:` | Coverage | Auth |\n|----------|-------------|----------|------|\n| Cisco Meraki Dashboard | `meraki` | full (all reads + all 8 writes) | API key (Bearer / X-Cisco-Meraki-API-Key) |\n| Cisco Catalyst Center | `catalyst` | read subset: sites (as orgs/networks), device+site+client health, issues→alerts, inventory, interface stats | `username:password` → short-lived X-Auth-Token (auto-refresh on 401) |\n| Arista CloudVision Portal | `cvp` | read subset: containers (as orgs/networks), inventory (+ complianceCode drift signal), events→alerts, users→admins | service-account token (Bearer) |\n| UniFi Network | `unifi` | read subset: sites (as orgs/networks), stat/device inventory+statuses, stat/health, alarms→alerts, stat/sta clients, device port_table→switch ports; **plus the device-restart write** (cmd/devmgr) | API key (`X-API-KEY`, stateless); base_url = classic `https://<host>:8443` or UniFi OS console `https://<console>/proxy/network` |\n\nOps a platform does not map — and **every write on catalyst/cvp (on unifi, every write except reboot)** — return a teaching \"not supported on `<platform>` yet — open an issue or PR\" error, never a silent no-op. Full matrix in the repo README.\n\n## What This Skill Does\n\n| Domain | Tools | Count | Read or Write |\n|--------|-------|:-----:|:-------------:|\n| **Overview** | fabric fleet overview | 1 | 1 read |\n| **Organizations** | list/get, licensing, admins, device statuses, API usage | 6 | 6 read |\n| **Networks** | list/get, VLANs, health alerts, traffic | 5 | 5 read |\n| **Devices** | inventory (by model), status, uplinks, switch ports, SSIDs | 5 | 5 read |\n| **Clients** | list, detail, usage, connectivity | 4 | 4 read |\n| **Health (flagship)** | uplink loss/latency RCA, network health score, config template drift | 3 | 3 read |\n| **Remediation** | reboot, claim, remove, bind, unbind | 5 | 5 write (high) |\n| | update device, update VLAN | 2 | 2 write (medium) |\n| | blink LEDs | 1 | 1 write (low) |\n| **Undo** | list recorded reversible writes | 1 | 1 read |\n| | apply a recorded inverse (governed, single-use, `dry_run`) | 1 | 1 write (medium) |\n\n`network_health_score` and `config_template_drift` are injected-only (they score data you already hold); `uplink_loss_and_latency_rca` accepts injected `records` for offline analysis, or pulls live from a configured target. Meraki device models carry a product-type prefix: **MX** appliance, **MS** switch, **MR** wireless AP, **MV** camera, **MG** cellular gateway.\n\n## Quick Install\n\n```bash\nuv tool install fabric-aiops\nfabric-aiops init       # interactive wizard: platform choice (meraki/catalyst/cvp/unifi) + encrypted secret\nfabric-aiops doctor\n```\n\nOr as an OpenClaw plugin, which installs this skill and its MCP server together:\n\n```bash\nopenclaw plugins install clawhub:@zw008/fabric-aiops\nopenclaw skills info fabric-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## When to Use This Skill\n\n- Triage an organization (`overview`): network count + device status/product rollup\n- Find the worst WAN uplinks (`health uplink-rca` / `uplink_loss_and_latency_rca`): ranked by loss + latency with a likely cause and action\n- Score fleet health per network (`health score` / `network_health_score`): a composite 0-100, worst first, every component shown\n- List/inspect organizations, networks, devices (by model), and clients\n- Reboot/blink a device, update device or VLAN attributes (reversible), claim/remove devices, or bind/unbind a config template — all with dry-run + double-confirm\n\n**Do NOT use when** the target is OT/industrial equipment (use industrial-aiops), a hypervisor, a storage appliance, a backup product, a container cluster, or device-level CLI/SSH network automation.\n\n## Related Skills — Skill Routing\n\n| If the user wants… | Use |\n|--------------------|-----|\n| Cisco Meraki fabric: uplinks, health, config templates, device lifecycle | **fabric-aiops** (this skill) |\n| Cisco Catalyst Center (DNA Center): site/device/client health, issues, inventory | **fabric-aiops** (this skill, `platform: catalyst`) |\n| Arista CloudVision Portal: inventory, compliance drift signal, events | **fabric-aiops** (this skill, `platform: cvp`) |\n| UniFi Network (self-hosted controller / UniFi OS console): site health, alarms, clients, device restart | **fabric-aiops** (this skill, `platform: unifi`) |\n| OT / industrial edge (Modbus, OPC-UA, PLC, PROFINET) | the **industrial-aiops** line |\n| Hypervisor VM lifecycle (power, snapshot, migrate) | a hypervisor ops skill |\n| Container/cluster lifecycle | a cluster ops skill |\n\n## Common Workflows\n\n### \"The branch VPN keeps dropping\" — diagnose degraded WAN uplinks\n\n1. `fabric-aiops health uplink-rca` → worst MX WAN uplinks ranked by avg loss + latency, each citing the measured numbers plus a likely cause and action\n2. `fabric-aiops health uplink-rca --loss-pct 2 --latency-ms 100` → tighten the thresholds if nothing crosses the defaults but users still complain\n3. `fabric-aiops device uplinks` → the raw per-appliance uplink statuses across the org (WAN1/WAN2, active vs failover) behind the ranking — confirm the flagged appliance rather than trusting the summary\n4. `fabric-aiops network alerts <networkId>` → check whether the controller already raised a matching alert (independent corroboration before you touch anything)\n5. **Failure branch**: if the RCA returns no uplink records at all, the org has no appliances reporting uplink telemetry, or the API key lacks org-wide read — run `fabric-aiops doctor` and re-check the org id with `fabric-aiops org list` rather than assuming the WAN is healthy.\n\n### Rank the fleet and fix the worst network's device attributes (reversible)\n\n1. `fabric-aiops overview` → org-level rollup: network count and device status/product mix\n2. `fabric-aiops health score` → composite 0-100 per network, worst first, with every scoring component shown\n3. `fabric-aiops org device-statuses` → find the offline/alerting devices dragging the worst network's score\n4. `fabric-aiops device status <serial>` → confirm the device before changing it\n5. `fabric-aiops remediate update-device <serial> '{\"name\":\"branch-ap-01\"}' --dry-run` → preview the exact `PUT /devices/<serial>` call; then run without `--dry-run` (double confirmation). The real before-state is fetched first and recorded as a faithful inverse\n6. **Failure branch**: wrong attribute or wrong device — `fabric-aiops undo list`, then `fabric-aiops undo apply <id>` restores the captured prior attributes. Re-run `fabric-aiops device status <serial>` to confirm the restore landed rather than trusting the undo's success message.\n\n### Bring a drifted network back to its config template (reversible)\n\n1. `fabric-aiops network list` → the networks in scope and their ids\n2. Pass the template plus its bound networks to `config_template_drift(template=..., networks=[...])` → the settings that deviate, per network\n3. `fabric-aiops network vlans <networkId>` → confirm the drifted VLAN's current values before changing anything\n4. Fix the specific setting — `fabric-aiops remediate update-vlan <networkId> <vlanId> '{\"name\":\"data\"}' --dry-run`, then for real — or re-establish the binding itself: `fabric-aiops remediate bind <networkId> <templateId> --dry-run`, then without `--dry-run` (double confirmation). Both capture the real before-state and record an inverse descriptor (for `bind`, the inverse is unbind or a rebind to the prior template)\n5. **Failure branch**: if the rebind makes things worse, `fabric-aiops undo apply <id>` returns the network to its captured prior binding; `fabric-aiops remediate unbind <networkId>` is the manual escape hatch. Re-run `config_template_drift` to confirm the drift actually cleared instead of trusting the write's success message.\n\n### Stage a replacement device into a branch network\n\n1. `fabric-aiops device inventory` → confirm the replacement serial is in the org inventory and unassigned\n2. `fabric-aiops network get <networkId>` → confirm the target network\n3. `fabric-aiops remediate claim <networkId> <serial> --dry-run` → preview `POST /networks/<networkId>/devices/claim`; then run for real (double confirmation) — the inverse (remove from network) is recorded\n4. `fabric-aiops remediate blink-leds <serial> --duration 30` → low-risk physical confirmation that you are at the right box in the rack\n5. `fabric-aiops health score` → confirm the network's score recovers once the device reports in\n6. **Failure branch**: wrong network — `fabric-aiops undo apply <id>` or `fabric-aiops remediate remove <networkId> <serial>`. Note `fabric-aiops remediate reboot <serial>` is `no undo` by construction (a reboot has no safe inverse); it records only the before-state, so use it last, not as a first response.\n\n### Offline analysis (no live controller)\n\n1. Export the org's uplink, device-status, and template data to JSON\n2. Feed it straight to the analysis tools — `uplink_loss_and_latency_rca(records=[...])`, `network_health_score(device_statuses=[...])`, `config_template_drift(template=..., networks=[...])` — no connection or credentials required\n3. **Failure branch**: a tool that rejects the injected records means the export is missing fields the analysis needs (loss/latency samples, device status, template settings) — re-export rather than hand-editing, so the findings stay traceable to the controller.\n\n## Governance & Safety\n\nThe skill delivers reads and writes and records them; it does **not** decide\nwhether a write is permitted. That is your agent's judgement, or the permission\nof the account you connect it with (a Meraki API key whose admin has read-only\norganization access — writes then fail at the controller). There is no read-only\nswitch, 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 `~/.fabric-aiops/audit.db` (relocatable via `FABRIC_AIOPS_HOME`): params, result, status, duration, and the risk tier. The CLI writes the same row the MCP path does.\n- `FABRIC_AUDIT_APPROVED_BY` / `FABRIC_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 `FABRIC_RUNAWAY_MAX=0`.\n- Destructive writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI.\n- Mutating/reversible writes fetch the real before-state and record an inverse descriptor (`update_device`/`update_network_vlan`→restore prior values, `claim`↔`remove`, `bind`↔`unbind`/rebind); irreversible ops (`reboot_device`, `blink_device_leds`) record only the before-state.\n\n## References\n\n- `references/capabilities.md` — full tool + field reference\n- `references/cli-reference.md` — CLI command reference\n- `references/setup-guide.md` — onboarding, credentials, and connectivity\n\nFile v0.11.5:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"fabric-aiops\",\n  \"version\": \"0.11.5\",\n  \"publishedAt\": 1789601127380\n}\n\nFile v0.11.5:references/agent-guardrails.md\n\n# Agent guardrails — running fabric-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\n## Authorization is not this tool's job — decide it where it belongs\n\nWhether a write should happen is your decision, or the account's. The tool does\nnot gate it — there is no read-only switch and no approval prompt to configure.\nThe two right places to control read vs write:\n\n- **The account you connect with.** Give it a Meraki API key whose admin has\n  read-only organization access (or the read-only equivalent on your\n  controller). A write then fails at the controller, which is the only place the\n  permission actually lives — no skill-side flag can be argued around by a model,\n  but a revoked permission cannot be.\n- **Your agent's system prompt.** If you want an observe-only session, tell the\n  model not to call the write tools (they are clearly tagged `[WRITE]`).\n\nWhat the tool *does* guarantee is that you can always see what happened:\n\n## What the tool enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Log everything you do, over both MCP and the CLI\" | Every call is audited to `~/.fabric-aiops/audit.db` regardless of what the model says it did — and the CLI writes the same row the MCP path does, so there is no unaudited entry point. Reversible writes also record an undo token capturing the *prior* state. |\n| \"Don't invent a value when a field is missing\" | A field the controller did not return comes back as `null`, never as `\"\"`. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | Anything with a `limit` returns `{\"<items>\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}`, where `<items>` names what was listed — `devices`, `alerts`, `topApplications`, `worst`, `driftedNetworks` or `undos`. Read the key the tool documents rather than assuming `devices`. Truncation is measured against the full result, not guessed from a length coincidence. |\n| \"Preserve the ordering / tell me what's most urgent\" | The ranked analyses return worst-first and carry the numbers that produced each ranking (`avgLossPct`, `score`, `alertPenalty`), so priority is in the payload rather than implied by list position. |\n| \"Confirm before anything destructive\" | Destructive operations require a `--dry-run`-able preview + double confirmation at the CLI. |\n| \"Don't get stuck retrying\" | The runaway guard trips a circuit breaker if the same call is hammered in a tight loop — a stuck agent is stopped rather than left to burn calls and time. |\n| \"Don't guess at an unsupported platform\" | An operation a platform does not map raises a teaching `PlatformUnsupported` error naming the platform — never a silent no-op the model can mistake for success. |\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 a network fabric through its CONTROLLER API using the fabric-aiops\nMCP tools (Cisco Meraki Dashboard, Cisco Catalyst Center, Arista CloudVision\nPortal, or UniFi Network, depending on the configured target).\n\nTOOL USE\n- Before answering any question about the current fabric, you MUST call a tool.\n  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.\n- If a tool returns \"not supported on <platform> yet\", say so. Do not substitute\n  a different tool and present its output as the answer to the original question.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result has \"truncated\": true,\n  say so and re-run with a higher limit instead of treating the partial result\n  as complete.\n- A null field means the controller did not return that value. Report it as\n  \"not available\" — never infer it.\n- Report values exactly as returned. Do not normalise, translate, or prettify\n  status strings, severities, model names, or identifiers.\n- In the ranked analyses, work worst-first and cite the measured number\n  (avgLossPct, avgLatencyMs, score, alertPenalty) behind each ranking.\n\nIDENTIFIERS — keep these straight, they are not interchangeable\n- An ORGANIZATION id scopes the whole account (on Catalyst Center, CVP, and\n  UniFi a site/container stands in for it).\n- A NETWORK id names one site/branch inside an organization.\n- A DEVICE SERIAL names one physical device. It is not a device name, not a MAC,\n  and not a network id.\n- An UPLINK names a WAN interface on one appliance (e.g. wan1/wan2), scoped to\n  that device's serial — an uplink is never addressed on its own.\n- Never pass an organization id where a network id is expected, or a device name\n  where a serial is expected. If you do not have the right id, call the list\n  tool that returns it (org_list, network_list, device_inventory) first.\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 connectivity, capacity, or availability problem unless a tool\n  result supports it.\n- Do not add generic advice that does not follow from the tool output.\n```\n\n## Recommended setup for a local model\n\nStart with a connection that *cannot* write, verify, and widen the account's\npermission only when you trust the setup — the fleet-affecting operations here\n(`reboot_device`, `remove_device_from_network`, `bind_network_to_template`) hit\nproduction hardware and live networks:\n\n```bash\n# e.g. use a Meraki API key whose admin has read-only organization access. Then:\nfabric-aiops doctor\n```\n\nOptionally annotate the audit trail with who is operating and why — recorded on\nevery row, never required:\n\n```bash\nexport FABRIC_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport FABRIC_AUDIT_RATIONALE=\"scheduled maintenance window 2026-07-20\"\n```\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 `overview` and the three\n  flagship analyses (`uplink_loss_and_latency_rca`, `network_health_score`,\n  `config_template_drift`) — they do the multi-step correlation inside one call,\n  so the model does not have to chain reads and keep org/network/serial ids\n  straight across turns.\n- **The model ignores later tool results in a long context.** Ask narrower\n  questions and use `--limit` deliberately rather than pulling a whole org\n  inventory in one go.\n- **The model confuses sites with networks on Catalyst Center / CVP / UniFi.**\n  On those platforms a site or container stands in for both the organization and\n  the network level. Tell the model which one your target is scoped to.\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/Fabric-AIops](https://github.com/AIops-tools/Fabric-AIops/issues)\nwith the model, runtime, and what went wrong.\n\nFile v0.11.5:references/capabilities.md\n\n# fabric-aiops capabilities\n\n> 34 MCP tools (25 read, 9 write) over four platforms —\n> Cisco Meraki Dashboard (reference, full read+write), Cisco Catalyst Center\n> (read subset), Arista CloudVision Portal (read subset), UniFi Network (read\n> subset + device restart). All API paths are modelled from the public API\n> shapes and need live verification. Community-maintained; not affiliated with\n> Cisco/Meraki/Arista/Ubiquiti.\n\nMeraki hierarchy: **organizations → networks → devices**. Device models carry a\nproduct-type prefix: **MX** appliance, **MS** switch, **MR** wireless AP, **MV**\ncamera, **MG** cellular gateway.\n\n**Multi-platform**: the tables below show the reference (Meraki) API per tool.\nOn `catalyst`, canonical organizations/networks are **sites**\n(`/dna/intent/api/v1/site`, `site-health`), device statuses come from\n`device-health`, alerts from `issues` (P1→critical, P2→warning), inventory from\n`network-device`, switch ports from per-device `interface` stats (pass the\ndevice uuid), and clients from `client-health` (aggregate) / `client-detail`\n(by MAC). On `cvp`, organizations/networks are **containers**\n(`/cvpservice/inventory/containers`), devices come from\n`/cvpservice/inventory/devices` (rows carry the `complianceCode` config-drift\nsignal), alerts from `getAllEvents.do`, and admins from `getUsers.do`.\nOn `unifi`, organizations/networks are **sites** (`/api/self/sites`; the\ncanonical id is the site's short name — the `/api/s/{site}/` path segment),\ndevice inventory/statuses come from `stat/device` (state 1 → online; uptime,\nfirmware), switch ports from the device detail's `port_table` (pass the device\n**MAC** where Meraki takes a serial), clients from `stat/sta` / `stat/user`,\nalerts from `stat/alarm` (`*_Lost_Contact` → critical), `network_get` from\n`stat/health` (per-subsystem rollup), and `reboot_device` maps to\n`POST /api/s/{site}/cmd/devmgr {\"cmd\": \"restart-device\", \"mac\": ...}` — the\nonly non-Meraki write. Device-scoped calls fill the site from the target's\ndefault `org_id`. Auth is a UniFi API key (`X-API-KEY`); a UniFi OS console's\n`base_url` carries the `/proxy/network` prefix.\nAny tool a platform does not map — and **every write on catalyst/cvp (on\nunifi, every write except reboot)** — returns a teaching \"not supported on\n<platform> yet — open an issue or PR\" error instead of a silent no-op. The\nfull per-op matrix is in the repo README.\n\n## Read tools (25)\n\n### Overview + organizations\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `overview` | `/organizations/{id}/networks` + `/devices/statuses` | organizationId, networks, devicesTotal, devicesByStatus, devicesByProductType |\n| `org_list` | `GET /organizations` | id, name, url, apiEnabled |\n| `org_get` | `GET /organizations/{id}` | one org detail |\n| `org_licensing` | `GET /organizations/{id}/licenses/overview` | status, expiration, per-device-type counts |\n| `org_admins` | `GET /organizations/{id}/admins` | name, email, access level |\n| `org_device_statuses` | `GET /organizations/{id}/devices/statuses` | total, byStatus, byProductType, devices[] |\n| `org_api_requests` | `GET /organizations/{id}/apiRequests/overview` | totalRequests, rateLimited429, responseCodeCounts |\n\n### Networks\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `network_list` | `GET /organizations/{id}/networks` | id, name, productTypes, tags |\n| `network_get` | `GET /networks/{id}` | one network detail |\n| `network_vlans` | `GET /networks/{id}/appliance/vlans` | id, subnet, applianceIp |\n| `network_alerts` | `GET /networks/{id}/health/alerts` | total, bySeverity, alerts[] |\n| `network_traffic` | `GET /networks/{id}/traffic` | applicationCount, topApplications[] (by bytes) |\n\n### Devices\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `device_inventory` | `GET /organizations/{id}/devices` | total, byModelFamily, matched, devices[] (filterable by model) |\n| `device_status` | `GET /organizations/{id}/devices/statuses` | one device's status row |\n| `device_uplinks` | `GET /organizations/{id}/uplinks/statuses` | appliance/gateway WAN uplink statuses |\n| `switch_ports` | `GET /devices/{serial}/switch/ports` | MS port configuration |\n| `wireless_ssids` | `GET /networks/{id}/wireless/ssids` | MR SSIDs (number, name, enabled) |\n\n### Clients\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `client_list` | `GET /networks/{id}/clients` | clients seen in the window |\n| `client_get` | `GET /networks/{id}/clients/{clientId}` | description, MAC, IP, VLAN, manufacturer |\n| `client_usage` | `GET .../clients/{clientId}/usageHistory` | samples, totalSentKb, totalReceivedKb, totalKb |\n| `client_connectivity` | `GET .../clients/{clientId}/connectionStats` | assoc, auth, dhcp, dns, success |\n\n### Health (flagship)\n| Tool | Source | Returns |\n|------|--------|---------|\n| `uplink_loss_and_latency_rca` | `GET /organizations/{id}/devices/uplinksLossAndLatency` or injected `records` | uplinksEvaluated, degradedCount, thresholds, worst[]{serial, uplink, avgLossPct, avgLatencyMs, degraded, cause, action}, note |\n| `network_health_score` | injected only | networksEvaluated, fleetScore, summary, weights, worst[]{networkId, score, band, onlinePct, uplinkHealthPct, alertPenalty}, note |\n| `config_template_drift` | injected only | templateId, boundNetworks, driftedCount, compliantCount, settingsChecked, driftedNetworks[]{networkId, deviations[]}, note |\n\n`uplink_loss_and_latency_rca` accepts `records=` for offline analysis or pulls\nlive from a `target`/`org_id`. `network_health_score` and `config_template_drift`\nare injected-only (they score data you already hold, e.g. from\n`org_device_statuses` / `device_uplinks`).\n\n### Undo\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `undo_list` | _(local `undo.db`, no API call)_ | recorded, not-yet-applied reversible writes: undoId, original tool, inverse tool, note |\n\n## Write tools (9) — all support `dry_run`; CLI adds double-confirm\n\n| Tool | Risk | Meraki API path | Undo / safety |\n|------|------|----------------------|---------------|\n| `reboot_device` | **high** | `POST /devices/{serial}/reboot` (unifi: `POST /api/s/{site}/cmd/devmgr` `{\"cmd\": \"restart-device\", \"mac\": ...}`) | captures prior status; no safe inverse, no undo |\n| `claim_devices_into_network` | **high** | `POST /networks/{id}/devices/claim` | inverse = remove the claimed serials |\n| `remove_device_from_network` | **high** | `POST /networks/{id}/devices/remove` | inverse = claim it back into the network |\n| `bind_network_to_template` | **high** | `POST /networks/{id}/bind` | captures the prior binding; inverse = rebind prior / unbind |\n| `unbind_network_from_template` | **high** | `POST /networks/{id}/unbind` | captures the prior template; inverse = rebind to it |\n| `update_device` | medium | `PUT /devices/{serial}` | fetches + captures the changed keys' prior values; inverse = restore them |\n| `update_network_vlan` | medium | `PUT /networks/{id}/appliance/vlans/{vlanId}` | fetches + captures prior values; inverse = restore them |\n| `blink_device_leds` | low | `POST /devices/{serial}/blinkLeds` | locator aid; no config change, no undo |\n| `undo_apply` | medium | _(local `undo.db`, then dispatches the recorded inverse tool)_ | executes a recorded inverse — itself governed and audited, single-use |\n\n## Out of scope (by design)\n\n- Full org/network **provisioning** workflows (create org, create network)\n- Firmware upgrade orchestration\n- SSID/switch-port config CRUD beyond the writes above\n- OT / industrial equipment (use the `industrial-aiops` line) and device-level\n  CLI/SSH network automation\n\n- On **catalyst/cvp/unifi**: the unmapped reads in the matrix (licensing,\n  VLANs, traffic, uplink telemetry, ...), the unmapped writes (all on\n  catalyst/cvp; all but reboot on unifi), CVP configlet-content retrieval,\n  Catalyst Center per-client listing, UniFi legacy cookie login\n  (`POST /api/login` — use an API key) and blink-LED (`set-locate` has no\n  bounded duration), and deep pagination\n\nWant one of these — a missing Meraki call, a ❌ filled in on Catalyst Center,\nCloudVision Portal, or UniFi Network (writes included), or another controller\nplatform entirely? Open an issue or PR — feedback and contributions welcome (a\nplatform is one descriptor module: path templates + response adapters).\n\nFile v0.11.5:references/cli-reference.md\n\n# fabric-aiops CLI reference\n\n> Controller API paths (Meraki / Catalyst Center / CVP / UniFi Network) are\n> modelled from the public API shapes and have not yet been exercised live\n> (see docs/VERIFICATION.md). Not affiliated with Cisco/Meraki/Arista/Ubiquiti.\n\n## Setup & diagnostics\n\n```bash\nfabric-aiops init                      # interactive onboarding wizard (platform: meraki/catalyst/cvp/unifi)\nfabric-aiops doctor [--skip-auth]      # config + secret store + connectivity (canonical org/site/container probe)\nfabric-aiops mcp                       # start the MCP server (stdio transport)\n```\n\n## Secrets (encrypted store ~/.fabric-aiops/secrets.enc)\n\n```bash\nfabric-aiops secret set <target> [--value <key>]   # store API key (hidden prompt if no --value)\nfabric-aiops secret list                            # names only — values never shown\nfabric-aiops secret rm <target>\nfabric-aiops secret migrate                         # import legacy plaintext .env (FABRIC_<T>_APIKEY)\nfabric-aiops secret rotate-password                 # re-encrypt under a new master password\n```\n\n## Read commands\n\n```bash\nfabric-aiops overview [--org-id <id>] [--target <t>]   # networks + device status/product rollup\n\nfabric-aiops org list                                  # organizations visible to the key\nfabric-aiops org get [--org-id <id>]\nfabric-aiops org licensing [--org-id <id>]\nfabric-aiops org admins [--org-id <id>]\nfabric-aiops org device-statuses [--org-id <id>]       # online/offline/alerting rollup\nfabric-aiops org api-usage [--org-id <id>]             # response-code counts, 429 rate-limits\n\nfabric-aiops network list [--org-id <id>]\nfabric-aiops network get <networkId>\nfabric-aiops network vlans <networkId>\nfabric-aiops network alerts <networkId>                # health alerts by severity\nfabric-aiops network traffic <networkId> [--timespan 86400]\n\nfabric-aiops device inventory [--model MS] [--org-id <id>]   # MX/MS/MR/MV/MG\nfabric-aiops device status <serial> [--org-id <id>]\nfabric-aiops device uplinks [--org-id <id>]\nfabric-aiops device switch-ports <serial>              # MS ports\nfabric-aiops device ssids <networkId>                  # MR SSIDs\n\nfabric-aiops client list <networkId> [--timespan 86400]\nfabric-aiops client get <networkId> <clientId>\nfabric-aiops client usage <networkId> <clientId>\nfabric-aiops client connectivity <networkId> <clientId>\n\nfabric-aiops health uplink-rca [--loss-pct 5] [--latency-ms 150] [--org-id <id>]   # flagship RCA\nfabric-aiops health score [--org-id <id>]              # composite per-network health from live data\n```\n\n## Write commands (governed; risk tier in parentheses)\n\n```bash\nfabric-aiops remediate reboot <serial> [--dry-run]                       # (high) no undo; double confirm\nfabric-aiops remediate blink-leds <serial> [--duration 20]               # (low)  locator aid\nfabric-aiops remediate update-device <serial> '{\"name\":\"ap1\"}' [--dry-run]   # (medium) captures before\nfabric-aiops remediate update-vlan <networkId> <vlanId> '{\"name\":\"data\"}' [--dry-run]  # (medium)\nfabric-aiops remediate claim <networkId> <serial...> [--dry-run]         # (high) inverse = remove\nfabric-aiops remediate remove <networkId> <serial> [--dry-run]           # (high) inverse = claim back\nfabric-aiops remediate bind <networkId> <templateId> [--auto-bind] [--dry-run]   # (high) captures prior binding\nfabric-aiops remediate unbind <networkId> [--dry-run]                    # (high) captures prior template\n```\n\n## Common options\n\n- `--target, -t <name>` — target name from `config.yaml` (omit to use the default/first target)\n- `--org-id, -o <id>` — Meraki organization id (omit to use the target's default `org_id`)\n- `--dry-run` — print the API call that would be made, change nothing\n- State-changing commands require two confirmations (except `blink-leds`, low risk)\n\nFile v0.11.5:references/setup-guide.md\n\n# fabric-aiops setup & security guide\n\n> Not yet exercised against a live controller of any platform (Meraki\n> organization, Catalyst Center appliance, CloudVision Portal instance, or\n> UniFi controller) — see docs/VERIFICATION.md. Community-maintained; not affiliated\n> with or endorsed by Cisco/Meraki/Arista/Ubiquiti.\n\n## 1. Install\n\n```bash\nuv tool install fabric-aiops\n```\n\n## 2. Create the platform credential\n\n**Cisco Meraki Dashboard (`platform: meraki`)** — in the Dashboard:\n**Organization → Settings → API access → Generate API key**. Copy the key.\nfabric-aiops sends it as `Authorization: Bearer <key>` (or, with\n`auth_style: meraki-key`, `X-Cisco-Meraki-API-Key`) against the Dashboard API\nbase `https://api.meraki.com/api/v1`.\n\n**Cisco Catalyst Center (`platform: catalyst`)** — use a Catalyst Center\naccount (a read-only role suffices for the current read subset) and store the\nsecret as a single `username:password` string. fabric-aiops exchanges it via\n`POST /dna/system/api/v1/auth/token` (HTTP Basic) for a short-lived (~1 h)\n`X-Auth-Token`, attached per request and auto-refreshed once on a 401. A\n`base_url` is required (`https://<catalyst-center-host>`).\n\n**Arista CloudVision Portal (`platform: cvp`)** — create a service-account\ntoken in CloudVision: **Settings → Access Control → Service Accounts**.\nfabric-aiops sends it as `Authorization: Bearer <token>`. A `base_url` is\nrequired (`https://<cvp-host>`).\n\n**UniFi Network (`platform: unifi`)** — create an **API key** in the UniFi\nconsole (UniFi OS: **Settings → Control Plane → Integrations**; self-hosted\nNetwork Server 9.0+: the admin's API-key page). fabric-aiops sends it as\n`X-API-KEY` on every request (stateless). The legacy cookie login\n(`POST /api/login`) is **not** supported — use an API key. A `base_url` is\nrequired and encodes the controller layout:\n- classic self-hosted controller: `https://<host>:8443`\n- UniFi OS console (UDM / UDM-Pro / Cloud Key Gen2):\n  `https://<console>/proxy/network` — keep the `/proxy/network` suffix; every\n  API path is issued relative to it.\n\nSet the target's `org_id` to the site's short name (e.g. `default`) —\ndevice-scoped calls (device get, switch ports, restart) use it as the\n`/api/s/{site}/` scope.\n\n## 3. Onboard\n\n```bash\nfabric-aiops init\n```\n\nThe wizard asks for the platform (`meraki` / `catalyst` / `cvp` / `unifi`), collects\n(non-secret) connection details into `~/.fabric-aiops/config.yaml`, and stores\nthe secret **encrypted** into `~/.fabric-aiops/secrets.enc`. Example config:\n\n```yaml\ntargets:\n  - name: org1\n    platform: meraki\n    org_id: \"123456\"            # default organization id (optional)\n    verify_ssl: true\n    # base_url: https://api.meraki.eu/api/v1   # override only for a region/proxy\n    # auth_style: meraki-key                    # use X-Cisco-Meraki-API-Key instead of Bearer\n  - name: campus\n    platform: catalyst\n    base_url: https://catalyst.example.com     # required (per-install)\n    org_id: \"site-uuid\"          # default site id (optional)\n    # verify_ssl: false          # only for self-signed lab controllers\n  - name: dc-fabric\n    platform: cvp\n    base_url: https://cvp.example.com          # required (per-install)\n    org_id: \"root\"               # default container key (optional)\n  - name: home-lab\n    platform: unifi\n    base_url: https://unifi.example.com:8443   # classic controller\n    # base_url: https://console.example.com/proxy/network   # UniFi OS console\n    org_id: \"default\"            # site short name (fills /api/s/{site}/ scopes)\n```\n\n## 4. Non-interactive use (MCP server / CI / cron)\n\nExport the master password so the encrypted store can be unlocked without a\nprompt:\n\n```bash\nexport FABRIC_AIOPS_MASTER_PASSWORD='your-master-password'\n```\n\n## Credential security\n\n- The controller secret (Meraki API key / Catalyst Center `username:password`\n  / CVP service-account token / UniFi API key) is **never** written to disk in plaintext. It lives only in\n  `~/.fabric-aiops/secrets.enc`, encrypted with Fernet (AES-128-CBC + HMAC),\n  the key derived from your master password via scrypt. Only a per-store random\n  salt and the ciphertext are on disk (chmod 600); the master password itself is\n  never stored.\n- A legacy plaintext env var `FABRIC_<TARGET_NAME_UPPER>_APIKEY` is still honoured\n  as a fallback with a deprecation warning — migrate with `fabric-aiops secret\n  migrate` (it imports then renames the old `.env`).\n- The key is held only in memory during a session and is never logged or echoed;\n  exception text and tracebacks are scrubbed of secret-shaped strings before\n  being written to the audit log.\n\n## Audit-annotation env vars (optional)\n\nThe skill does not decide whether a write is permitted — that is the agent's\njudgement or the connecting controller account's role. If you want the audit\ntrail to record *who* ran a destructive op and *why*, set these; they are\nrecorded on the row, never required, and gate nothing:\n\n```bash\nexport FABRIC_AUDIT_APPROVED_BY='you@example.com'\nexport FABRIC_AUDIT_RATIONALE='why this destructive op is justified'\n```\n\n## Governance harness state\n\nState lives under `~/.fabric-aiops/` (relocate with `FABRIC_AIOPS_HOME`):\n\n- `audit.db` — every tool call (SQLite), with risk tier and any approver/rationale\n- `undo.db` — inverse descriptors for reversible writes (e.g. `update_device`,\n  `bind_network_to_template`)\n- budget / runaway guard — caps cumulative tool calls and wall-time; trips on\n  tight poll/retry loops (also your first line of defense against Dashboard API\n  rate limits)\n\n## Verify\n\n```bash\nfabric-aiops doctor\n```\n\n`doctor` checks the config file, the encrypted store and its permissions, that a\nsecret (and, for on-prem platforms, a `base_url`) is present per target, and\n(unless `--skip-auth`) connectivity via the canonical top-of-hierarchy read —\nMeraki organizations, Catalyst Center sites, CVP containers, or UniFi sites —\nwhich also exercises the platform's full auth flow (including the Catalyst\nCenter session-token exchange and, on unifi, the `X-API-KEY` header against\nthe configured base URL — the fastest way to confirm a UniFi OS console's\n`/proxy/network` prefix is right).\n\nFile v0.11.5:skill-card.md\n\n## Description:\n\nfabric-aiops helps agents inspect and operate controller-managed network fabrics across Meraki, Catalyst Center, CloudVision, and UniFi with health analyses, guided remediation commands, audit logging, dry-run previews, and undo support where available.\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 engineers, operators, and agents use this skill to review fabric health, inspect controller inventory, diagnose uplink and configuration drift issues, and stage guarded remediation for supported controller-managed networks.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can perform production-impacting controller writes without an in-skill approval or read-only gate.\n\nMitigation: Use read-only controller credentials by default, expose write-capable credentials only to supervised sessions, and require an external approval process for write-capable MCP use.\n\nRisk: Remediation actions may affect live network devices, VLANs, template bindings, or device membership.\n\nMitigation: Prefer dry-run previews, confirm target identifiers against controller state, and use the recorded undo path only after checking that the inverse action is appropriate.\n\nRisk: The artifact states that live controller verification has not yet been completed.\n\nMitigation: Treat first use on each controller platform as a staged rollout with low-privilege credentials, non-production targets where possible, and post-action validation.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/zw008/skills/fabric-aiops)\n- [Project homepage](https://github.com/AIops-tools/Fabric-AIops)\n- [fabric-aiops capabilities](references/capabilities.md)\n- [fabric-aiops CLI reference](references/cli-reference.md)\n- [fabric-aiops setup & security guide](references/setup-guide.md)\n- [Agent guardrails](references/agent-guardrails.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown with inline shell commands and structured operational guidance]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include dry-run remediation steps, controller health analysis, audit or undo guidance, and configuration setup instructions.]\n\n## Skill Version(s):\n\n0.11.5 (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.11.4: 7 files, 21315 bytes\n\nFiles: references/agent-guardrails.md (7654b), references/capabilities.md (8457b), references/cli-reference.md (3845b), references/setup-guide.md (6207b), skill-card.md (3247b), SKILL.md (18452b), _meta.json (132b)\n\nFile v0.11.4:SKILL.md\n\n---\nname: fabric-aiops\nslug: fabric-aiops\ndisplayName: \"Fabric AIops\"\nsummary: \"Governed Cisco Meraki fabric ops: uplink RCA, health score, drift; 34 tools with audit/undo.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Fabric-AIops\ntags: [aiops, mcp, governance, fabric]\ndescription: >\n  Use this skill whenever the user needs to operate a network fabric through a controller API — Cisco Meraki Dashboard (full read+write), Cisco Catalyst Center / DNA Center (read subset), Arista CloudVision Portal / CVP (read subset), or UniFi Network (self-hosted controller / UniFi OS console; read subset + device restart) — a one-shot fabric health overview; organization/site/container reads (list/get, licensing, admins, org-wide device statuses, API usage); network reads (list/get, VLANs, health alerts, traffic); device reads (inventory by model MX/MS/MR/MV/MG, status, uplinks, switch ports / interface stats, wireless SSIDs); client reads (list, detail, usage, connectivity); three flagship analyses — uplink loss & latency RCA (rank worst MX WAN uplinks + cause/action), network health score (composite per-network), and config template drift (settings drifted from a bound template); and eight guarded writes (reboot, blink LEDs, update device, update VLAN, claim/remove devices, bind/unbind a config template — Meraki-only except device restart, which unifi also maps; other unmapped writes return a teaching \"not supported yet\" error).\n  Always use this skill for \"Meraki org overview\", \"which uplinks are worst\", \"uplink loss and latency\", \"WAN degradation RCA\", \"network health score\", \"config template drift\", \"list Meraki networks/devices/clients\", \"reboot a Meraki device\", \"blink device LEDs\", \"claim a device into a network\", \"bind a network to a template\", \"Catalyst Center site health / device health / issues\", \"DNA Center inventory\", \"CloudVision inventory / compliance / events\", \"UniFi site health / alarms / clients\", \"restart a UniFi AP or switch\" when the context is a controller-managed network fabric.\n  Do NOT use when the target is OT / industrial equipment (Modbus, OPC-UA, PLCs — use industrial-aiops), a hypervisor, a storage appliance, a backup product, a container/cluster orchestrator, or device-level CLI/SSH network automation (negative routing hints only).\n  Covers common controller fabric operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers). The test suite is mock-based; no platform has yet been exercised against a live controller (see docs/VERIFICATION.md).\ninstaller:\n  kind: uv\n  package: fabric-aiops\nargument-hint: \"[org/network/device id or describe your fabric task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"fabric-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"FABRIC_AIOPS_CONFIG\",\"FABRIC_AIOPS_MASTER_PASSWORD\"]},\"homepage\":\"https://github.com/AIops-tools/Fabric-AIops\",\"emoji\":\"🛰️\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed network-fabric controller operations. The governance harness (audit, policy, token/runaway budget, undo, risk-tiers) is bundled in the package — no external skill-family dependency. Multi-platform by construction (a platform registry): meraki (Cisco Meraki Dashboard, reference platform, full read+write), catalyst (Cisco Catalyst Center, read subset — sites stand in for organizations/networks), cvp (Arista CloudVision Portal, read subset — containers stand in for organizations/networks), and unifi (UniFi Network controller / UniFi OS console, read subset — sites stand in for organizations/networks — plus the device-restart write via a cmd/devmgr command envelope). Unmapped ops raise a teaching \"not supported on <platform> yet\" error; all writes are Meraki-only except UniFi device restart.\n  All write operations are audited to a local SQLite DB under ~/.fabric-aiops/ (relocatable via FABRIC_AIOPS_HOME).\n  Credentials: the controller secret (Meraki API key / Catalyst Center username:password / CVP service-account token / UniFi API key) is stored ENCRYPTED in ~/.fabric-aiops/secrets.enc (Fernet/AES-128 + scrypt-derived key) — never plaintext on disk. Run 'fabric-aiops init' to onboard, or 'fabric-aiops secret set <target>' to add one. The store is unlocked by a master password from FABRIC_AIOPS_MASTER_PASSWORD (non-interactive/MCP/CI) or an interactive prompt (CLI on a TTY). A legacy plaintext env var FABRIC_<TARGET_NAME_UPPER>_APIKEY is still honoured as a fallback with a deprecation warning (migrate with 'fabric-aiops secret migrate'). Meraki/CVP/UniFi secrets ride the platform auth header (Authorization: Bearer, X-Cisco-Meraki-API-Key, or UniFi's X-API-KEY) at request time; the Catalyst Center secret is exchanged via POST /dna/system/api/v1/auth/token for a short-lived X-Auth-Token (auto-refreshed once on 401). UniFi legacy cookie login (POST /api/login) is not implemented — use an API key (UniFi OS console or self-hosted Network Server 9.0+; a UniFi OS console's base_url carries the /proxy/network prefix). Secrets are held only in memory and never logged or echoed.\n  State-changing operations require double confirmation at the CLI layer and support --dry-run. All write tools pass through the @governed_tool decorator (pre-check + budget guard + audit + risk-tier label) and take a dry_run preview. Mutating/reversible writes fetch the real before-state first and record a faithful inverse undo descriptor; irreversible ops (reboot, blink) record only the before-state.\n  Webhooks: none — no outbound network calls beyond the configured controller REST API base URL.\n  SSL: verify_ssl defaults to true; disable only for a self-signed on-prem controller proxy.\n  Transitive dependencies: httpx (HTTP client) and the MCP SDK. No post-install scripts or background services.\n  Verification status: the test suite is mock-based; the Dashboard API paths are modelled from the public API shape and have not yet been exercised live — docs/VERIFICATION.md defines the checklist. Community-maintained; not affiliated with or endorsed by Cisco/Meraki — trademarks belong to their owners.\n---\n\n# Fabric AIops\n\n> **Disclaimer**: Community-maintained open-source project, **not affiliated with, endorsed by, or sponsored by Cisco, Meraki, Arista, Ubiquiti, or any network-controller vendor.** Product and trademark names belong to their owners. Source at [github.com/AIops-tools/Fabric-AIops](https://github.com/AIops-tools/Fabric-AIops) under the MIT license.\n\nGoverned network-fabric controller operations — **34 MCP tools** over **four platforms** (Cisco Meraki Dashboard: full read+write; Cisco Catalyst Center and Arista CloudVision Portal: read subsets; UniFi Network: read subset + device restart), every one wrapped with the bundled `@governed_tool` harness: a local unified audit log under `~/.fabric-aiops/`, token/runaway budget guard, undo-token recording, and descriptive risk tiers. The controller secret is stored **encrypted** (`~/.fabric-aiops/secrets.enc`, Fernet + scrypt) — never plaintext on disk.\n\n> **Standalone**: the governance harness is bundled in the package (`fabric_aiops.governance`) — fabric-aiops has no external skill-family dependency. The test suite is mock-based; no platform has yet been exercised against a live controller (see `docs/VERIFICATION.md`).\n\n## Platform support\n\n| Platform | `platform:` | Coverage | Auth |\n|----------|-------------|----------|------|\n| Cisco Meraki Dashboard | `meraki` | full (all reads + all 8 writes) | API key (Bearer / X-Cisco-Meraki-API-Key) |\n| Cisco Catalyst Center | `catalyst` | read subset: sites (as orgs/networks), device+site+client health, issues→alerts, inventory, interface stats | `username:password` → short-lived X-Auth-Token (auto-refresh on 401) |\n| Arista CloudVision Portal | `cvp` | read subset: containers (as orgs/networks), inventory (+ complianceCode drift signal), events→alerts, users→admins | service-account token (Bearer) |\n| UniFi Network | `unifi` | read subset: sites (as orgs/networks), stat/device inventory+statuses, stat/health, alarms→alerts, stat/sta clients, device port_table→switch ports; **plus the device-restart write** (cmd/devmgr) | API key (`X-API-KEY`, stateless); base_url = classic `https://<host>:8443` or UniFi OS console `https://<console>/proxy/network` |\n\nOps a platform does not map — and **every write on catalyst/cvp (on unifi, every write except reboot)** — return a teaching \"not supported on `<platform>` yet — open an issue or PR\" error, never a silent no-op. Full matrix in the repo README.\n\n## What This Skill Does\n\n| Domain | Tools | Count | Read or Write |\n|--------|-------|:-----:|:-------------:|\n| **Overview** | fabric fleet overview | 1 | 1 read |\n| **Organizations** | list/get, licensing, admins, device statuses, API usage | 6 | 6 read |\n| **Networks** | list/get, VLANs, health alerts, traffic | 5 | 5 read |\n| **Devices** | inventory (by model), status, uplinks, switch ports, SSIDs | 5 | 5 read |\n| **Clients** | list, detail, usage, connectivity | 4 | 4 read |\n| **Health (flagship)** | uplink loss/latency RCA, network health score, config template drift | 3 | 3 read |\n| **Remediation** | reboot, claim, remove, bind, unbind | 5 | 5 write (high) |\n| | update device, update VLAN | 2 | 2 write (medium) |\n| | blink LEDs | 1 | 1 write (low) |\n| **Undo** | list recorded reversible writes | 1 | 1 read |\n| | apply a recorded inverse (governed, single-use, `dry_run`) | 1 | 1 write (medium) |\n\n`network_health_score` and `config_template_drift` are injected-only (they score data you already hold); `uplink_loss_and_latency_rca` accepts injected `records` for offline analysis, or pulls live from a configured target. Meraki device models carry a product-type prefix: **MX** appliance, **MS** switch, **MR** wireless AP, **MV** camera, **MG** cellular gateway.\n\n## Quick Install\n\n```bash\nuv tool install fabric-aiops\nfabric-aiops init       # interactive wizard: platform choice (meraki/catalyst/cvp/unifi) + encrypted secret\nfabric-aiops doctor\n```\n\nOr as an OpenClaw plugin, which installs this skill and its MCP server together:\n\n```bash\nopenclaw plugins install clawhub:@zw008/fabric-aiops\nopenclaw skills info fabric-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## When to Use This Skill\n\n- Triage an organization (`overview`): network count + device status/product rollup\n- Find the worst WAN uplinks (`health uplink-rca` / `uplink_loss_and_latency_rca`): ranked by loss + latency with a likely cause and action\n- Score fleet health per network (`health score` / `network_health_score`): a composite 0-100, worst first, every component shown\n- List/inspect organizations, networks, devices (by model), and clients\n- Reboot/blink a device, update device or VLAN attributes (reversible), claim/remove devices, or bind/unbind a config template — all with dry-run + double-confirm\n\n**Do NOT use when** the target is OT/industrial equipment (use industrial-aiops), a hypervisor, a storage appliance, a backup product, a container cluster, or device-level CLI/SSH network automation.\n\n## Related Skills — Skill Routing\n\n| If the user wants… | Use |\n|--------------------|-----|\n| Cisco Meraki fabric: uplinks, health, config templates, device lifecycle | **fabric-aiops** (this skill) |\n| Cisco Catalyst Center (DNA Center): site/device/client health, issues, inventory | **fabric-aiops** (this skill, `platform: catalyst`) |\n| Arista CloudVision Portal: inventory, compliance drift signal, events | **fabric-aiops** (this skill, `platform: cvp`) |\n| UniFi Network (self-hosted controller / UniFi OS console): site health, alarms, clients, device restart | **fabric-aiops** (this skill, `platform: unifi`) |\n| OT / industrial edge (Modbus, OPC-UA, PLC, PROFINET) | the **industrial-aiops** line |\n| Hypervisor VM lifecycle (power, snapshot, migrate) | a hypervisor ops skill |\n| Container/cluster lifecycle | a cluster ops skill |\n\n## Common Workflows\n\n### \"The branch VPN keeps dropping\" — diagnose degraded WAN uplinks\n\n1. `fabric-aiops health uplink-rca` → worst MX WAN uplinks ranked by avg loss + latency, each citing the measured numbers plus a likely cause and action\n2. `fabric-aiops health uplink-rca --loss-pct 2 --latency-ms 100` → tighten the thresholds if nothing crosses the defaults but users still complain\n3. `fabric-aiops device uplinks` → the raw per-appliance uplink statuses across the org (WAN1/WAN2, active vs failover) behind the ranking — confirm the flagged appliance rather than trusting the summary\n4. `fabric-aiops network alerts <networkId>` → check whether the controller already raised a matching alert (independent corroboration before you touch anything)\n5. **Failure branch**: if the RCA returns no uplink records at all, the org has no appliances reporting uplink telemetry, or the API key lacks org-wide read — run `fabric-aiops doctor` and re-check the org id with `fabric-aiops org list` rather than assuming the WAN is healthy.\n\n### Rank the fleet and fix the worst network's device attributes (reversible)\n\n1. `fabric-aiops overview` → org-level rollup: network count and device status/product mix\n2. `fabric-aiops health score` → composite 0-100 per network, worst first, with every scoring component shown\n3. `fabric-aiops org device-statuses` → find the offline/alerting devices dragging the worst network's score\n4. `fabric-aiops device status <serial>` → confirm the device before changing it\n5. `fabric-aiops remediate update-device <serial> '{\"name\":\"branch-ap-01\"}' --dry-run` → preview the exact `PUT /devices/<serial>` call; then run without `--dry-run` (double confirmation). The real before-state is fetched first and recorded as a faithful inverse\n6. **Failure branch**: wrong attribute or wrong device — `fabric-aiops undo list`, then `fabric-aiops undo apply <id>` restores the captured prior attributes. Re-run `fabric-aiops device status <serial>` to confirm the restore landed rather than trusting the undo's success message.\n\n### Bring a drifted network back to its config template (reversible)\n\n1. `fabric-aiops network list` → the networks in scope and their ids\n2. Pass the template plus its bound networks to `config_template_drift(template=..., networks=[...])` → the settings that deviate, per network\n3. `fabric-aiops network vlans <networkId>` → confirm the drifted VLAN's current values before changing anything\n4. Fix the specific setting — `fabric-aiops remediate update-vlan <networkId> <vlanId> '{\"name\":\"data\"}' --dry-run`, then for real — or re-establish the binding itself: `fabric-aiops remediate bind <networkId> <templateId> --dry-run`, then without `--dry-run` (double confirmation). Both capture the real before-state and record an inverse descriptor (for `bind`, the inverse is unbind or a rebind to the prior template)\n5. **Failure branch**: if the rebind makes things worse, `fabric-aiops undo apply <id>` returns the network to its captured prior binding; `fabric-aiops remediate unbind <networkId>` is the manual escape hatch. Re-run `config_template_drift` to confirm the drift actually cleared instead of trusting the write's success message.\n\n### Stage a replacement device into a branch network\n\n1. `fabric-aiops device inventory` → confirm the replacement serial is in the org inventory and unassigned\n2. `fabric-aiops network get <networkId>` → confirm the target network\n3. `fabric-aiops remediate claim <networkId> <serial> --dry-run` → preview `POST /networks/<networkId>/devices/claim`; then run for real (double confirmation) — the inverse (remove from network) is recorded\n4. `fabric-aiops remediate blink-leds <serial> --duration 30` → low-risk physical confirmation that you are at the right box in the rack\n5. `fabric-aiops health score` → confirm the network's score recovers once the device reports in\n6. **Failure branch**: wrong network — `fabric-aiops undo apply <id>` or `fabric-aiops remediate remove <networkId> <serial>`. Note `fabric-aiops remediate reboot <serial>` is `no undo` by construction (a reboot has no safe inverse); it records only the before-state, so use it last, not as a first response.\n\n### Offline analysis (no live controller)\n\n1. Export the org's uplink, device-status, and template data to JSON\n2. Feed it straight to the analysis tools — `uplink_loss_and_latency_rca(records=[...])`, `network_health_score(device_statuses=[...])`, `config_template_drift(template=..., networks=[...])` — no connection or credentials required\n3. **Failure branch**: a tool that rejects the injected records means the export is missing fields the analysis needs (loss/latency samples, device status, template settings) — re-export rather than hand-editing, so the findings stay traceable to the controller.\n\n## Governance & Safety\n\nThe skill delivers reads and writes and records them; it does **not** decide\nwhether a write is permitted. That is your agent's judgement, or the permission\nof the account you connect it with (a Meraki API key whose admin has read-only\norganization access — writes then fail at the controller). There is no read-only\nswitch, 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 `~/.fabric-aiops/audit.db` (relocatable via `FABRIC_AIOPS_HOME`): params, result, status, duration, and the risk tier. The CLI writes the same row the MCP path does.\n- `FABRIC_AUDIT_APPROVED_BY` / `FABRIC_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 `FABRIC_RUNAWAY_MAX=0`.\n- Destructive writes support `--dry-run` / `dry_run=True` and double confirmation at the CLI.\n- Mutating/reversible writes fetch the real before-state and record an inverse descriptor (`update_device`/`update_network_vlan`→restore prior values, `claim`↔`remove`, `bind`↔`unbind`/rebind); irreversible ops (`reboot_device`, `blink_device_leds`) record only the before-state.\n\n## References\n\n- `references/capabilities.md` — full tool + field reference\n- `references/cli-reference.md` — CLI command reference\n- `references/setup-guide.md` — onboarding, credentials, and connectivity\n\nFile v0.11.4:_meta.json\n\n{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"fabric-aiops\",\n  \"version\": \"0.11.4\",\n  \"publishedAt\": 1789535613987\n}\n\nFile v0.11.4:references/agent-guardrails.md\n\n# Agent guardrails — running fabric-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\n## Authorization is not this tool's job — decide it where it belongs\n\nWhether a write should happen is your decision, or the account's. The tool does\nnot gate it — there is no read-only switch and no approval prompt to configure.\nThe two right places to control read vs write:\n\n- **The account you connect with.** Give it a Meraki API key whose admin has\n  read-only organization access (or the read-only equivalent on your\n  controller). A write then fails at the controller, which is the only place the\n  permission actually lives — no skill-side flag can be argued around by a model,\n  but a revoked permission cannot be.\n- **Your agent's system prompt.** If you want an observe-only session, tell the\n  model not to call the write tools (they are clearly tagged `[WRITE]`).\n\nWhat the tool *does* guarantee is that you can always see what happened:\n\n## What the tool enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Log everything you do, over both MCP and the CLI\" | Every call is audited to `~/.fabric-aiops/audit.db` regardless of what the model says it did — and the CLI writes the same row the MCP path does, so there is no unaudited entry point. Reversible writes also record an undo token capturing the *prior* state. |\n| \"Don't invent a value when a field is missing\" | A field the controller did not return comes back as `null`, never as `\"\"`. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | Anything with a `limit` returns `{\"devices\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}`. Truncation is measured against the full result, not guessed from a length coincidence. |\n| \"Preserve the ordering / tell me what's most urgent\" | The ranked analyses return worst-first and carry the numbers that produced each ranking (`avgLossPct`, `score`, `alertPenalty`), so priority is in the payload rather than implied by list position. |\n| \"Confirm before anything destructive\" | Destructive operations require a `--dry-run`-able preview + double confirmation at the CLI. |\n| \"Don't get stuck retrying\" | The runaway guard trips a circuit breaker if the same call is hammered in a tight loop — a stuck agent is stopped rather than left to burn calls and time. |\n| \"Don't guess at an unsupported platform\" | An operation a platform does not map raises a teaching `PlatformUnsupported` error naming the platform — never a silent no-op the model can mistake for success. |\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 a network fabric through its CONTROLLER API using the fabric-aiops\nMCP tools (Cisco Meraki Dashboard, Cisco Catalyst Center, Arista CloudVision\nPortal, or UniFi Network, depending on the configured target).\n\nTOOL USE\n- Before answering any question about the current fabric, you MUST call a tool.\n  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.\n- If a tool returns \"not supported on <platform> yet\", say so. Do not substitute\n  a different tool and present its output as the answer to the original question.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result has \"truncated\": true,\n  say so and re-run with a higher limit instead of treating the partial result\n  as complete.\n- A null field means the controller did not return that value. Report it as\n  \"not available\" — never infer it.\n- Report values exactly as returned. Do not normalise, translate, or prettify\n  status strings, severities, model names, or identifiers.\n- In the ranked analyses, work worst-first and cite the measured number\n  (avgLossPct, avgLatencyMs, score, alertPenalty) behind each ranking.\n\nIDENTIFIERS — keep these straight, they are not interchangeable\n- An ORGANIZATION id scopes the whole account (on Catalyst Center, CVP, and\n  UniFi a site/container stands in for it).\n- A NETWORK id names one site/branch inside an organization.\n- A DEVICE SERIAL names one physical device. It is not a device name, not a MAC,\n  and not a network id.\n- An UPLINK names a WAN interface on one appliance (e.g. wan1/wan2), scoped to\n  that device's serial — an uplink is never addressed on its own.\n- Never pass an organization id where a network id is expected, or a device name\n  where a serial is expected. If you do not have the right id, call the list\n  tool that returns it (org_list, network_list, device_inventory) first.\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 connectivity, capacity, or availability problem unless a tool\n  result supports it.\n- Do not add generic advice that does not follow from the tool output.\n```\n\n## Recommended setup for a local model\n\nStart with a connection that *cannot* write, verify, and widen the account's\npermission only when you trust the setup — the fleet-affecting operations here\n(`reboot_device`, `remove_device_from_network`, `bind_network_to_template`) hit\nproduction hardware and live networks:\n\n```bash\n# e.g. use a Meraki API key whose admin has read-only organization access. Then:\nfabric-aiops doctor\n```\n\nOptionally annotate the audit trail with who is operating and why — recorded on\nevery row, never required:\n\n```bash\nexport FABRIC_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport FABRIC_AUDIT_RATIONALE=\"scheduled maintenance window 2026-07-20\"\n```\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 `overview` and the three\n  flagship analyses (`uplink_loss_and_latency_rca`, `network_health_score`,\n  `config_template_drift`) — they do the multi-step correlation inside one call,\n  so the model does not have to chain reads and keep org/network/serial ids\n  straight across turns.\n- **The model ignores later tool results in a long context.** Ask narrower\n  questions and use `--limit` deliberately rather than pulling a whole org\n  inventory in one go.\n- **The model confuses sites with networks on Catalyst Center / CVP / UniFi.**\n  On those platforms a site or container stands in for both the organization and\n  the network level. Tell the model which one your target is scoped to.\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/Fabric-AIops](https://github.com/AIops-tools/Fabric-AIops/issues)\nwith the model, runtime, and what went wrong.\n\nFile v0.11.4:references/capabilities.md\n\n# fabric-aiops capabilities\n\n> 34 MCP tools (25 read, 9 write) over four platforms —\n> Cisco Meraki Dashboard (reference, full read+write), Cisco Catalyst Center\n> (read subset), Arista CloudVision Portal (read subset), UniFi Network (read\n> subset + device restart). All API paths are modelled from the public API\n> shapes and need live verification. Community-maintained; not affiliated with\n> Cisco/Meraki/Arista/Ubiquiti.\n\nMeraki hierarchy: **organizations → networks → devices**. Device models carry a\nproduct-type prefix: **MX** appliance, **MS** switch, **MR** wireless AP, **MV**\ncamera, **MG** cellular gateway.\n\n**Multi-platform**: the tables below show the reference (Meraki) API per tool.\nOn `catalyst`, canonical organizations/networks are **sites**\n(`/dna/intent/api/v1/site`, `site-health`), device statuses come from\n`device-health`, alerts from `issues` (P1→critical, P2→warning), inventory from\n`network-device`, switch ports from per-device `interface` stats (pass the\ndevice uuid), and clients from `client-health` (aggregate) / `client-detail`\n(by MAC). On `cvp`, organizations/networks are **containers**\n(`/cvpservice/inventory/containers`), devices come from\n`/cvpservice/inventory/devices` (rows carry the `complianceCode` config-drift\nsignal), alerts from `getAllEvents.do`, and admins from `getUsers.do`.\nOn `unifi`, organizations/networks are **sites** (`/api/self/sites`; the\ncanonical id is the site's short name — the `/api/s/{site}/` path segment),\ndevice inventory/statuses come from `stat/device` (state 1 → online; uptime,\nfirmware), switch ports from the device detail's `port_table` (pass the device\n**MAC** where Meraki takes a serial), clients from `stat/sta` / `stat/user`,\nalerts from `stat/alarm` (`*_Lost_Contact` → critical), `network_get` from\n`stat/health` (per-subsystem rollup), and `reboot_device` maps to\n`POST /api/s/{site}/cmd/devmgr {\"cmd\": \"restart-device\", \"mac\": ...}` — the\nonly non-Meraki write. Device-scoped calls fill the site from the target's\ndefault `org_id`. Auth is a UniFi API key (`X-API-KEY`); a UniFi OS console's\n`base_url` carries the `/proxy/network` prefix.\nAny tool a platform does not map — and **every write on catalyst/cvp (on\nunifi, every write except reboot)** — returns a teaching \"not supported on\n<platform> yet — open an issue or PR\" error instead of a silent no-op. The\nfull per-op matrix is in the repo README.\n\n## Read tools (25)\n\n### Overview + organizations\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `overview` | `/organizations/{id}/networks` + `/devices/statuses` | organizationId, networks, devicesTotal, devicesByStatus, devicesByProductType |\n| `org_list` | `GET /organizations` | id, name, url, apiEnabled |\n| `org_get` | `GET /organizations/{id}` | one org detail |\n| `org_licensing` | `GET /organizations/{id}/licenses/overview` | status, expiration, per-device-type counts |\n| `org_admins` | `GET /organizations/{id}/admins` | name, email, access level |\n| `org_device_statuses` | `GET /organizations/{id}/devices/statuses` | total, byStatus, byProductType, devices[] |\n| `org_api_requests` | `GET /organizations/{id}/apiRequests/overview` | totalRequests, rateLimited429, responseCodeCounts |\n\n### Networks\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `network_list` | `GET /organizations/{id}/networks` | id, name, productTypes, tags |\n| `network_get` | `GET /networks/{id}` | one network detail |\n| `network_vlans` | `GET /networks/{id}/appliance/vlans` | id, subnet, applianceIp |\n| `network_alerts` | `GET /networks/{id}/health/alerts` | total, bySeverity, alerts[] |\n| `network_traffic` | `GET /networks/{id}/traffic` | applicationCount, topApplications[] (by bytes) |\n\n### Devices\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `device_inventory` | `GET /organizations/{id}/devices` | total, byModelFamily, matched, devices[] (filterable by model) |\n| `device_status` | `GET /organizations/{id}/devices/statuses` | one device's status row |\n| `device_uplinks` | `GET /organizations/{id}/uplinks/statuses` | appliance/gateway WAN uplink statuses |\n| `switch_ports` | `GET /devices/{serial}/switch/ports` | MS port configuration |\n| `wireless_ssids` | `GET /networks/{id}/wireless/ssids` | MR SSIDs (number, name, enabled) |\n\n### Clients\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `client_list` | `GET /networks/{id}/clients` | clients seen in the window |\n| `client_get` | `GET /networks/{id}/clients/{clientId}` | description, MAC, IP, VLAN, manufacturer |\n| `client_usage` | `GET .../clients/{clientId}/usageHistory` | samples, totalSentKb, totalReceivedKb, totalKb |\n| `client_connectivity` | `GET .../clients/{clientId}/connectionStats` | assoc, auth, dhcp, dns, success |\n\n### Health (flagship)\n| Tool | Source | Returns |\n|------|--------|---------|\n| `uplink_loss_and_latency_rca` | `GET /organizations/{id}/devices/uplinksLossAndLatency` or injected `records` | uplinksEvaluated, degradedCount, thresholds, worst[]{serial, uplink, avgLossPct, avgLatencyMs, degraded, cause, action}, note |\n| `network_health_score` | injected only | networksEvaluated, fleetScore, summary, weights, worst[]{networkId, score, band, onlinePct, uplinkHealthPct, alertPenalty}, note |\n| `config_template_drift` | injected only | templateId, boundNetworks, driftedCount, compliantCount, settingsChecked, driftedNetworks[]{networkId, deviations[]}, note |\n\n`uplink_loss_and_latency_rca` accepts `records=` for offline analysis or pulls\nlive from a `target`/`org_id`. `network_health_score` and `config_template_drift`\nare injected-only (they score data you already hold, e.g. from\n`org_device_statuses` / `device_uplinks`).\n\n### Undo\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `undo_list` | _(local `undo.db`, no API call)_ | recorded, not-yet-applied reversible writes: undoId, original tool, inverse tool, note |\n\n## Write tools (9) — all support `dry_run`; CLI adds double-confirm\n\n| Tool | Risk | Meraki API path | Undo / safety |\n|------|------|----------------------|---------------|\n| `reboot_device` | **high** | `POST /devices/{serial}/reboot` (unifi: `POST /api/s/{site}/cmd/devmgr` `{\"cmd\": \"restart-device\", \"mac\": ...}`) | captures prior status; no safe inverse, no undo |\n| `claim_devices_into_network` | **high** | `POST /networks/{id}/devices/claim` | inverse = remove the claimed serials |\n| `remove_device_from_network` | **high** | `POST /networks/{id}/devices/remove` | inverse = claim it back into the network |\n| `bind_network_to_template` | **high** | `POST /networks/{id}/bind` | captures the prior binding; inverse = rebind prior / unbind |\n| `unbind_network_from_template` | **high** | `POST /networks/{id}/unbind` | captures the prior template; inverse = rebind to it |\n| `update_device` | medium | `PUT /devices/{serial}` | fetches + captures the changed keys' prior values; inverse = restore them |\n| `update_network_vlan` | medium | `PUT /networks/{id}/appliance/vlans/{vlanId}` | fetches + captures prior values; inverse = restore them |\n| `blink_device_leds` | low | `POST /devices/{serial}/blinkLeds` | locator aid; no config change, no undo |\n| `undo_apply` | medium | _(local `undo.db`, then dispatches the recorded inverse tool)_ | executes a recorded inverse — itself governed and audited, single-use |\n\n## Out of scope (by design)\n\n- Full org/network **provisioning** workflows (create org, create network)\n- Firmware upgrade orchestration\n- SSID/switch-port config CRUD beyond the writes above\n- OT / industrial equipment (use the `industrial-aiops` line) and device-level\n  CLI/SSH network automation\n\n- On **catalyst/cvp/unifi**: the unmapped reads in the matrix (licensing,\n  VLANs, traffic, uplink telemetry, ...), the unmapped writes (all on\n  catalyst/cvp; all but reboot on unifi), CVP configlet-content retrieval,\n  Catalyst Center per-client listing, UniFi legacy cookie login\n  (`POST /api/login` — use an API key) and blink-LED (`set-locate` has no\n  bounded duration), and deep pagination\n\nWant one of these — a missing Meraki call, a ❌ filled in on Catalyst Center,\nCloudVision Portal, or UniFi Network (writes included), or another controller\nplatform entirely? Open an issue or PR — feedback and contributions welcome (a\nplatform is one descriptor module: path templates + response adapters).\n\nFile v0.11.4:references/cli-reference.md\n\n# fabric-aiops CLI reference\n\n> Controller API paths (Meraki / Catalyst Center / CVP / UniFi Network) are\n> modelled from the public API shapes and have not yet been exercised live\n> (see docs/VERIFICATION.md). Not affiliated with Cisco/Meraki/Arista/Ubiquiti.\n\n## Setup & diagnostics\n\n```bash\nfabric-aiops init                      # interactive onboarding wizard (platform: meraki/catalyst/cvp/unifi)\nfabric-aiops doctor [--skip-auth]      # config + secret store + connectivity (canonical org/site/container probe)\nfabric-aiops mcp                       # start the MCP server (stdio transport)\n```\n\n## Secrets (encrypted store ~/.fabric-aiops/secrets.enc)\n\n```bash\nfabric-aiops secret set <target> [--value <key>]   # store API key (hidden prompt if no --value)\nfabric-aiops secret list                            # names only — values never shown\nfabric-aiops secret rm <target>\nfabric-aiops secret migrate                         # import legacy plaintext .env (FABRIC_<T>_APIKEY)\nfabric-aiops secret rotate-password                 # re-encrypt under a new master password\n```\n\n## Read commands\n\n```bash\nfabric-aiops overview [--org-id <id>] [--target <t>]   # networks + device status/product rollup\n\nfabric-aiops org list                                  # organizations visible to the key\nfabric-aiops org get [--org-id <id>]\nfabric-aiops org licensing [--org-id <id>]\nfabric-aiops org admins [--org-id <id>]\nfabric-aiops org device-statuses [--org-id <id>]       # online/offline/alerting rollup\nfabric-aiops org api-usage [--org-id <id>]             # response-code counts, 429 rate-limits\n\nfabric-aiops network list [--org-id <id>]\nfabric-aiops network get <networkId>\nfabric-aiops network vlans <networkId>\nfabric-aiops network alerts <networkId>                # health alerts by severity\nfabric-aiops network traffic <networkId> [--timespan 86400]\n\nfabric-aiops device inventory [--model MS] [--org-id <id>]   # MX/MS/MR/MV/MG\nfabric-aiops device status <serial> [--org-id <id>]\nfabric-aiops device uplinks [--org-id <id>]\nfabric-aiops device switch-ports <serial>              # MS ports\nfabric-aiops device ssids <networkId>                  # MR SSIDs\n\nfabric-aiops client list <networkId> [--timespan 86400]\nfabric-aiops client get <networkId> <clientId>\nfabric-aiops client usage <networkId> <clientId>\nfabric-aiops client connectivity <networkId> <clientId>\n\nfabric-aiops health uplink-rca [--loss-pct 5] [--latency-ms 150] [--org-id <id>]   # flagship RCA\nfabric-aiops health score [--org-id <id>]              # composite per-network health from live data\n```\n\n## Write commands (governed; risk tier in parentheses)\n\n```bash\nfabric-aiops remediate reboot <serial> [--dry-run]                       # (high) no undo; double confirm\nfabric-aiops remediate blink-leds <serial> [--duration 20]               # (low)  locator aid\nfabric-aiops remediate update-device <serial> '{\"name\":\"ap1\"}' [--dry-run]   #\n\nArchive v0.11.3: 7 files, 21261 bytes\n\nFiles: references/agent-guardrails.md (7654b), references/capabilities.md (8457b), references/cli-reference.md (3845b), references/setup-guide.md (6207b), skill-card.md (3132b), SKILL.md (18452b), _meta.json (132b)\n\nArchive v0.11.2: 7 files, 21195 bytes\n\nFiles: references/agent-guardrails.md (7654b), references/capabilities.md (8457b), references/cli-reference.md (3845b), references/setup-guide.md (6207b), skill-card.md (3057b), SKILL.md (18452b), _meta.json (132b)\n\nArchive v0.11.1: 7 files, 21082 bytes\n\nFiles: references/agent-guardrails.md (7654b), references/capabilities.md (8457b), references/cli-reference.md (3845b), references/setup-guide.md (6207b), skill-card.md (2772b), SKILL.md (18458b), _meta.json (132b)\n\nArchive v0.11.0: 7 files, 21047 bytes\n\nFiles: references/agent-guardrails.md (7654b), references/capabilities.md (8457b), references/cli-reference.md (3845b), references/setup-guide.md (6207b), skill-card.md (3009b), SKILL.md (18146b), _meta.json (132b)\n\nArchive v0.10.0: 7 files, 21137 bytes\n\nFiles: references/agent-guardrails.md (7654b), references/capabilities.md (8457b), references/cli-reference.md (3845b), references/setup-guide.md (6207b), skill-card.md (3129b), SKILL.md (18251b), _meta.json (132b)\n\nArchive v0.9.0: 7 files, 20945 bytes\n\nFiles: references/agent-guardrails.md (7654b), references/capabilities.md (8457b), references/cli-reference.md (3845b), references/setup-guide.md (6207b), skill-card.md (2862b), SKILL.md (18251b), _meta.json (131b)\n\nArchive v0.8.0: 7 files, 21056 bytes\n\nFiles: references/agent-guardrails.md (7654b), references/capabilities.md (8457b), references/cli-reference.md (3845b), references/setup-guide.md (6207b), skill-card.md (3058b), SKILL.md (18251b), _meta.json (131b)","readmeExcerpt":"Skill: fabric-aiops Owner: zw008 Summary: Use this skill whenever the user needs to operate a network fabric through a controller API — Cisco Meraki Dashboard (full read+write), Cisco Catalyst Center / DNA Center (read subset), Arista CloudVision Portal / CVP (read subset), or UniFi Network (self-hosted controller / UniFi OS console; read subset + device restart) — a one-shot fabric health overview; organization/site","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"uv tool install fabric-aiops\nfabric-aiops init       # interactive wizard: platform choice (meraki/catalyst/cvp/unifi) + encrypted secret\nfabric-aiops doctor"},{"language":"bash","snippet":"openclaw plugins install clawhub:@zw008/fabric-aiops\nopenclaw skills info fabric-aiops          # expect: Visible to model: yes"},{"language":"text","snippet":"You operate a network fabric through its CONTROLLER API using the fabric-aiops\nMCP tools (Cisco Meraki Dashboard, Cisco Catalyst Center, Arista CloudVision\nPortal, UniFi Network, or Cisco ACI, depending on the configured target).\n\nTOOL USE\n- Before answering any question about the current fabric, you MUST call a tool.\n  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.\n- If a tool returns \"not supported on <platform> yet\", say so. Do not substitute\n  a different tool and present its output as the answer to the original question.\n\nREADING RESULTS\n- Read the whole result before concluding. If a result has \"truncated\": true,\n  say so and re-run with a higher limit instead of treating the partial result\n  as complete.\n- A null field means the controller did not return that value. Report it as\n  \"not available\" — never infer it.\n- Report values exactly as returned. Do not normalise, translate, or prettify\n  status strings, severities, model names, or identifiers.\n- In the ranked analyses, work worst-first and cite the measured number\n  (avgLossPct, avgLatencyMs, score, alertPenalty) behind each ranking.\n\nIDENTIFIERS — keep these straight, they are not interchangeable\n- An ORGANIZATION id scopes the whole account (on Catalyst Center, CVP, and\n  UniFi a site/container stands in for it).\n- A NETWORK id names one site/branch inside an organization.\n- A DEVICE SERIAL names one physical device. It is not a device name, not a MAC,\n  and not a network id.\n- An UPLINK names a WAN interface on one appliance (e.g. wan1/wan2), scoped to\n  that device's serial — an uplink is never addressed on its own.\n- Never pass an organization id where a network id is expected, or a device name\n  where a serial is expected. If you do not have the right id, call th"},{"language":"bash","snippet":"# e.g. use a Meraki API key whose admin has read-only organization access. Then:\nfabric-aiops doctor"},{"language":"bash","snippet":"export FABRIC_AUDIT_APPROVED_BY=\"your.name@example.com\"\nexport FABRIC_AUDIT_RATIONALE=\"scheduled maintenance window 2026-07-20\""},{"language":"bash","snippet":"fabric-aiops init                      # interactive onboarding wizard (platform: meraki/catalyst/cvp/unifi)\nfabric-aiops doctor [--skip-auth]      # config + secret store + connectivity (canonical org/site/container probe)\nfabric-aiops mcp                       # start the MCP server (stdio transport)"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: fabric-aiops\nslug: fabric-aiops\ndisplayName: \"Fabric AIops\"\nsummary: \"Governed Cisco Meraki + ACI fabric ops: uplink RCA, ACI endpoint trace; 37 tools with audit/undo.\"\nlicense: MIT\nhomepage: https://github.com/AIops-tools/Fabric-AIops\ntags: [aiops, mcp, governance, fabric]\ndescription: >\n  Use this skill whenever the user needs to operate a network fabric through a controller API — Cisco Meraki Dashboard (full read+write), Cisco Catalyst Center / DNA Center (read subset), Arista CloudVision Portal / CVP (read subset), or UniFi Network (self-hosted controller / UniFi OS console; read subset + device restart) — a one-shot fabric health overview; organization/site/container reads (list/get, licensing, admins, org-wide device statuses, API usage); network reads (list/get, VLANs, health alerts, traffic); device reads (inventory by model MX/MS/MR/MV/MG, status, uplinks, switch ports / interface stats, wireless SSIDs); client reads (list, detail, usage, connectivity); three flagship analyses — uplink loss & latency RCA (rank worst MX WAN uplinks + cause/action), network health score (composite per-network), and config template drift (settings drifted from a bound template); and eight guarded writes (reboot, blink LEDs, update device, update VLAN, claim/remove devices, bind/unbind a config template — Meraki-only except device restart, which unifi also maps; other unmapped writes return a teaching \"not supported yet\" error).\n  Always use this skill for \"Meraki org overview\", \"which uplinks are worst\", \"uplink loss and latency\", \"WAN degradation RCA\", \"network health score\", \"config template drift\", \"list Meraki networks/devices/clients\", \"reboot a Meraki device\", \"blink device LEDs\", \"claim a device into a network\", \"bind a network to a template\", \"Catalyst Center site health / device health / issues\", \"DNA Center inventory\", \"CloudVision inventory / compliance / events\", \"UniFi site health / alarms / clients\", \"restart a UniFi AP or switch\" when the context is a controller-managed network fabric.\n  Do NOT use when the target is OT / industrial equipment (Modbus, OPC-UA, PLCs — use industrial-aiops), a hypervisor, a storage appliance, a backup product, a container/cluster orchestrator, or device-level CLI/SSH network automation (negative routing hints only).\n  Covers common controller fabric operations with a built-in governance harness (audit, policy, token budget, undo, risk-tiers). The test suite is mock-based; no platform has yet been exercised against a live controller (see docs/VERIFICATION.md).\ninstaller:\n  kind: uv\n  package: fabric-aiops\nargument-hint: \"[org/network/device id or describe your fabric task]\"\nallowed-tools:\n  - Bash\nmetadata: {\"openclaw\":{\"requires\":{\"anyBins\":[\"fabric-aiops\",\"uvx\"]},\"optional\":{\"env\":[\"FABRIC_AIOPS_CONFIG\",\"FABRIC_AIOPS_MASTER_PASSWORD\"]},\"homepage\":\"https://github.com/AIops-tools/Fabric-AIops\",\"emoji\":\"🛰️\",\"os\":[\"macos\",\"linux\"]}}\ncompatibility: >\n  Standalone, self-governed network-fabric controller o"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b067awq2s97bn3d7p5qfhw5827pxc\",\n  \"slug\": \"fabric-aiops\",\n  \"version\": \"0.12.0\",\n  \"publishedAt\": 1789962986404\n}"},{"path":"references/agent-guardrails.md","content":"# Agent guardrails — running fabric-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\n## Authorization is not this tool's job — decide it where it belongs\n\nWhether a write should happen is your decision, or the account's. The tool does\nnot gate it — there is no read-only switch and no approval prompt to configure.\nThe two right places to control read vs write:\n\n- **The account you connect with.** Give it a Meraki API key whose admin has\n  read-only organization access (or the read-only equivalent on your\n  controller). A write then fails at the controller, which is the only place the\n  permission actually lives — no skill-side flag can be argued around by a model,\n  but a revoked permission cannot be.\n- **Your agent's system prompt.** If you want an observe-only session, tell the\n  model not to call the write tools (they are clearly tagged `[WRITE]`).\n\nWhat the tool *does* guarantee is that you can always see what happened:\n\n## What the tool enforces — do not waste prompt budget on these\n\n| You might be tempted to prompt | Why you don't need to |\n|---|---|\n| \"Log everything you do, over both MCP and the CLI\" | Every call is audited to `~/.fabric-aiops/audit.db` regardless of what the model says it did — and the CLI writes the same row the MCP path does, so there is no unaudited entry point. Reversible writes also record an undo token capturing the *prior* state. |\n| \"Don't invent a value when a field is missing\" | A field the controller did not return comes back as `null`, never as `\"\"`. Absent and empty are distinguishable in the payload. |\n| \"Tell me if the output was cut off\" | Anything with a `limit` returns `{\"<items>\": [...], \"returned\": N, \"limit\": L, \"truncated\": true/false}`, where `<items>` names what was listed — `devices`, `alerts`, `topApplications`, `worst`, `driftedNetworks` or `undos`; on ACI, `endpoints`, `faults`, `contracts` or `entries`. Read the key the tool documents rather than assuming `devices`. Truncation is measured against the full result, not guessed from a length coincidence. |\n| \"Preserve the ordering / tell me what's most urgent\" | The ranked analyses return worst-first and carry the numbers that produced each ranking (`avgLossPct`, `score`, `alertPenalty`), so priority is in the payload rather than implied by list position. The ACI reads carry an explicit `rank` on findings and on `aci_faults_list` rows; related-fault candidates are sorted active-first but unranked. |\n| \"Confirm before anything destructive\" | Destruc"},{"path":"references/capabilities.md","content":"# fabric-aiops capabilities\n\n> 37 MCP tools (28 read, 9 write) over five platforms —\n> Cisco Meraki Dashboard (reference, full read+write), Cisco Catalyst Center\n> (read subset), Arista CloudVision Portal (read subset), UniFi Network (read\n> subset + device restart), Cisco ACI APIC (three ACI-native reads). The first\n> four platforms' API paths are modelled from the public API shapes and need live\n> verification; the ACI reads are built against real, anonymized APIC responses.\n> Community-maintained; not affiliated with Cisco/Meraki/Arista/Ubiquiti.\n\nMeraki hierarchy: **organizations → networks → devices**. Device models carry a\nproduct-type prefix: **MX** appliance, **MS** switch, **MR** wireless AP, **MV**\ncamera, **MG** cellular gateway.\n\n**Multi-platform**: the tables below show the reference (Meraki) API per tool.\nOn `catalyst`, canonical organizations/networks are **sites**\n(`/dna/intent/api/v1/site`, `site-health`), device statuses come from\n`device-health`, alerts from `issues` (P1→critical, P2→warning), inventory from\n`network-device`, switch ports from per-device `interface` stats (pass the\ndevice uuid), and clients from `client-health` (aggregate) / `client-detail`\n(by MAC). On `cvp`, organizations/networks are **containers**\n(`/cvpservice/inventory/containers`), devices come from\n`/cvpservice/inventory/devices` (rows carry the `complianceCode` config-drift\nsignal), alerts from `getAllEvents.do`, and admins from `getUsers.do`.\nOn `unifi`, organizations/networks are **sites** (`/api/self/sites`; the\ncanonical id is the site's short name — the `/api/s/{site}/` path segment),\ndevice inventory/statuses come from `stat/device` (state 1 → online; uptime,\nfirmware), switch ports from the device detail's `port_table` (pass the device\n**MAC** where Meraki takes a serial), clients from `stat/sta` / `stat/user`,\nalerts from `stat/alarm` (`*_Lost_Contact` → critical), `network_get` from\n`stat/health` (per-subsystem rollup), and `reboot_device` maps to\n`POST /api/s/{site}/cmd/devmgr {\"cmd\": \"restart-device\", \"mac\": ...}` — the\nonly non-Meraki write. Device-scoped calls fill the site from the target's\ndefault `org_id`. Auth is a UniFi API key (`X-API-KEY`); a UniFi OS console's\n`base_url` carries the `/proxy/network` prefix.\nAny tool a platform does not map — and **every write on catalyst/cvp (on\nunifi, every write except reboot)** — returns a teaching \"not supported on\n<platform> yet — open an issue or PR\" error instead of a silent no-op. The\nfull per-op matrix is in the repo README.\n\n## Read tools (28)\n\n### Overview + organizations\n| Tool | Meraki API path | Returns |\n|------|----------------------|---------|\n| `overview` | `/organizations/{id}/networks` + `/devices/statuses` | organizationId, networks, devicesTotal, devicesByStatus, devicesByProductType |\n| `org_list` | `GET /organizations` | id, name, url, apiEnabled |\n| `org_get` | `GET /organizations/{id}` | one org detail |\n| `org_licensing` | `GET /organizations/{id}/licenses/overview` | sta"},{"path":"references/cli-reference.md","content":"# fabric-aiops CLI reference\n\n> Controller API paths (Meraki / Catalyst Center / CVP / UniFi Network) are\n> modelled from the public API shapes and have not yet been exercised live\n> (see docs/VERIFICATION.md). Not affiliated with Cisco/Meraki/Arista/Ubiquiti.\n\n## Setup & diagnostics\n\n```bash\nfabric-aiops init                      # interactive onboarding wizard (platform: meraki/catalyst/cvp/unifi)\nfabric-aiops doctor [--skip-auth]      # config + secret store + connectivity (canonical org/site/container probe)\nfabric-aiops mcp                       # start the MCP server (stdio transport)\n```\n\n## Secrets (encrypted store ~/.fabric-aiops/secrets.enc)\n\n```bash\nfabric-aiops secret set <target> [--value <key>]   # store API key (hidden prompt if no --value)\nfabric-aiops secret list                            # names only — values never shown\nfabric-aiops secret rm <target>\nfabric-aiops secret migrate                         # import legacy plaintext .env (FABRIC_<T>_APIKEY)\nfabric-aiops secret rotate-password                 # re-encrypt under a new master password\n```\n\n## Read commands\n\n```bash\nfabric-aiops overview [--org-id <id>] [--target <t>]   # networks + device status/product rollup\n\nfabric-aiops org list                                  # organizations visible to the key\nfabric-aiops org get [--org-id <id>]\nfabric-aiops org licensing [--org-id <id>]\nfabric-aiops org admins [--org-id <id>]\nfabric-aiops org device-statuses [--org-id <id>]       # online/offline/alerting rollup\nfabric-aiops org api-usage [--org-id <id>]             # response-code counts, 429 rate-limits\n\nfabric-aiops network list [--org-id <id>]\nfabric-aiops network get <networkId>\nfabric-aiops network vlans <networkId>\nfabric-aiops network alerts <networkId>                # health alerts by severity\nfabric-aiops network traffic <networkId> [--timespan 86400]\n\nfabric-aiops device inventory [--model MS] [--org-id <id>]   # MX/MS/MR/MV/MG\nfabric-aiops device status <serial> [--org-id <id>]\nfabric-aiops device uplinks [--org-id <id>]\nfabric-aiops device switch-ports <serial>              # MS ports\nfabric-aiops device ssids <networkId>                  # MR SSIDs\n\nfabric-aiops client list <networkId> [--timespan 86400]\nfabric-aiops client get <networkId> <clientId>\nfabric-aiops client usage <networkId> <clientId>\nfabric-aiops client connectivity <networkId> <clientId>\n\nfabric-aiops health uplink-rca [--loss-pct 5] [--latency-ms 150] [--org-id <id>]   # flagship RCA\nfabric-aiops health score [--org-id <id>]              # composite per-network health from live data\n\n# Cisco ACI targets (platform: aci) — read-only, ACI-native references\nfabric-aiops aci trace --mac <mac> | --ip <ip> [--limit 5]   # endpoint → leaf/interface → EPG → BD → VRF → contracts\nfabric-aiops aci segment <tenant> <app> <epg>                # an EPG's BD, VRF and contracts\nfabric-aiops aci faults [--severity critical] [--include-cleared] [--limit 50]   # worst-first\n```\n\n## Write commands (governed; risk ti"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2270,"uniquenessScore":38,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T07:53:49.677Z","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-10T07:53:49.677Z","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-10T10:45:00.761Z","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"}]}}}