{"skill":{"slug":"unifi-advisor","displayName":"UniFi Advisor","summary":"Read-only UniFi network advisor covering the Site Manager cloud API and the Network Integration API. Query devices, clients, networks, firewall zones and pol...","description":"---\nname: unifi-advisor\ndescription: Read-only UniFi network advisor covering the Site Manager cloud API and the Network Integration API. Query devices, clients, networks, firewall zones and policies, ACL rules, DNS policies, VPN tunnels, DPI, ISP metrics, and related UniFi state. Use when inspecting UniFi environments with GET-only operations and no writes.\nmetadata: {\"openclaw\":{\"requires\":{\"env\":[\"UNIFI_API_KEY\"],\"bins\":[\"python3\"]},\"primaryEnv\":\"UNIFI_API_KEY\"}}\n---\n\n# UniFi Network Advisor\n\nRead-only skill covering two official UniFi API surfaces. All operations are GET-only — no writes, no mutations of any kind.\n\n## API surfaces\n\nEverything goes through `https://api.ui.com`. No direct local connection required.\n\n| Prefix | Surface | Proxied via | Env vars needed |\n|---|---|---|---|\n| SM | Site Manager | `api.ui.com/v1/...` | `UNIFI_API_KEY` |\n| NET | Network Integration | `api.ui.com/v1/connector/consoles/{hostId}/proxy/network/integration/v1/...` | `UNIFI_API_KEY` (host/site resolved automatically) |\n\n## How to call the script\n\n```\npython3 {baseDir}/scripts/unifi.py <subcommand> [--site SITE] [--id ID] [--limit N] [--next-token TOKEN] [subcommand-specific flags]\n```\n\nSome subcommands require additional flags — see the table below. Use `python3 {baseDir}/scripts/unifi.py list` to see all subcommands with descriptions.\n\n## Subcommands\n\n### Site Manager (SM) — cloud, single API key\n\n| Subcommand | Endpoint | Required flags | Description |\n|---|---|---|---|\n| `hosts` | GET /v1/hosts | — | All UniFi OS consoles on the UI account |\n| `host` | GET /v1/hosts/{id} | `--id` | Console details |\n| `sites` | GET /v1/sites | — | All sites across all consoles |\n| `cloud-devices` | GET /v1/devices | — | All devices across all sites |\n| `isp-metrics` | GET /ea/isp-metrics/{type} | — | ISP performance metrics |\n| `sdwan` | GET /v1/sd-wan-configs | — | SD-WAN configurations |\n| `sdwan-config` | GET /v1/sd-wan-configs/{id} | `--id` | Specific SD-WAN config |\n| `sdwan-status` | GET /v1/sd-wan-configs/{id}/status | `--id` | SD-WAN deployment status |\n\n### Network Integration (NET) — proxied via api.ui.com, site resolved automatically\n\n| Subcommand | Endpoint | Required flags | Description |\n|---|---|---|---|\n| `info` | GET /v1/info | — | Controller version and capabilities |\n| `net-sites` | GET /v1/sites | — | Sites managed by this console |\n| `devices` | GET /v1/sites/{siteId}/devices | — | Adopted devices overview |\n| `device` | GET /v1/sites/{siteId}/devices/{id} | `--id` | Device details |\n| `device-stats` | GET /v1/sites/{siteId}/devices/{id}/statistics/latest | `--id` | Latest device statistics |\n| `devices-pending` | GET /v1/pending-devices | — | Devices pending adoption (console-scoped) |\n| `clients` | GET /v1/sites/{siteId}/clients | — | Connected clients overview |\n| `client` | GET /v1/sites/{siteId}/clients/{id} | `--id` | Client details |\n| `networks` | GET /v1/sites/{siteId}/networks | — | Networks overview |\n| `network` | GET /v1/sites/{siteId}/networks/{id} | `--id` | Network details |\n| `network-refs` | GET /v1/sites/{siteId}/networks/{id}/references | `--id` | What references a specific network (devices, clients, WiFi) |\n| `wifi` | GET /v1/sites/{siteId}/wifi/broadcasts | — | WiFi broadcast (SSID) overview |\n| `wifi-details` | GET /v1/sites/{siteId}/wifi/broadcasts/{id} | `--id` | WiFi broadcast details |\n| `firewall-zones` | GET /v1/sites/{siteId}/firewall/zones | — | Firewall zones |\n| `firewall-zone` | GET /v1/sites/{siteId}/firewall/zones/{id} | `--id` | Firewall zone details |\n| `firewall-policies` | GET /v1/sites/{siteId}/firewall/policies | — | Firewall policies |\n| `firewall-policy` | GET /v1/sites/{siteId}/firewall/policies/{id} | `--id` | Firewall policy details |\n| `firewall-ordering` | GET /v1/sites/{siteId}/firewall/policies/ordering | `--from-zone` `--to-zone` | Policy ordering between two zones |\n| `acl-rules` | GET /v1/sites/{siteId}/acl-rules | — | ACL rules |\n| `acl-rule` | GET /v1/sites/{siteId}/acl-rules/{id} | `--id` | ACL rule details |\n| `acl-ordering` | GET /v1/sites/{siteId}/acl-rules/ordering | — | ACL rule ordering |\n| `dns-policies` | GET /v1/sites/{siteId}/dns/policies | — | DNS policies |\n| `dns-policy` | GET /v1/sites/{siteId}/dns/policies/{id} | `--id` | DNS policy details |\n| `traffic-lists` | GET /v1/sites/{siteId}/traffic-matching-lists | — | Traffic matching lists |\n| `traffic-list` | GET /v1/sites/{siteId}/traffic-matching-lists/{id} | `--id` | Traffic matching list details |\n| `vouchers` | GET /v1/sites/{siteId}/hotspot/vouchers | — | Hotspot vouchers |\n| `voucher` | GET /v1/sites/{siteId}/hotspot/vouchers/{id} | `--id` | Voucher details |\n| `wans` | GET /v1/sites/{siteId}/wans | — | WAN interfaces overview |\n| `vpn-tunnels` | GET /v1/sites/{siteId}/vpn/site-to-site-tunnels | — | Site-to-site VPN tunnels |\n| `vpn-servers` | GET /v1/sites/{siteId}/vpn/servers | — | VPN server configurations |\n| `radius` | GET /v1/sites/{siteId}/radius/profiles | — | RADIUS profiles |\n| `device-tags` | GET /v1/sites/{siteId}/device-tags | — | Device tags |\n| `dpi-categories` | GET /v1/dpi/categories | — | DPI application categories |\n| `dpi-applications` | GET /v1/dpi/applications | — | DPI applications |\n| `countries` | GET /v1/countries | — | Countries list (for geo-IP rules) |\n\n## Examples\n\n```bash\n# List all sites and pick one to work with\npython3 {baseDir}/scripts/unifi.py library\n\n# firewall-ordering: get zone IDs first, then query ordering between two of them\n# --from-zone and --to-zone must be real UUIDs from the firewall-zones output\npython3 {baseDir}/scripts/unifi.py firewall-zones --site hq\npython3 {baseDir}/scripts/unifi.py firewall-ordering --site hq --from-zone <zoneId> --to-zone <zoneId>\n\n# network-refs: get network list first, then query references for a specific network\npython3 {baseDir}/scripts/unifi.py networks --site hq\npython3 {baseDir}/scripts/unifi.py network-refs --site hq --id <networkId>\n\n# sdwan-config / sdwan-status: list configs first to get an ID\npython3 {baseDir}/scripts/unifi.py sdwan\npython3 {baseDir}/scripts/unifi.py sdwan-config --id <configId>\npython3 {baseDir}/scripts/unifi.py sdwan-status --id <configId>\n```\n\n## Site library\n\nOn every invocation the skill builds a site library by joining:\n- `GET /v1/hosts` — host names (user-set), hardware model, connection state, `apiIntegration` flag\n- `GET /v1/sites` — `siteId` per `hostId`\n\nLabels come directly from the name the user set in the UniFi UI — e.g. \"HQ\" → `hq`, \"Branch Office\" → `branch-office`, \"Remote Site\" → `remote-site`. The library is cached in `~/.openclaw/unifi-skill.json` for 15 minutes to avoid redundant API calls.\n\nHosts without Network API support (e.g. a NAS device with `apiIntegration: false`) are included in the library but will return a clear error if targeted with NET subcommands.\n\nRun `library` to see the current library including state, hardware, and API capability of each host.\n\n## Site selection\n\nAll NET subcommands accept `--site <hint>`. The hint is matched against label, name, hardware shortname, hardware name, timezone, and IP — partial matches work.\n\n| User says | Use |\n|---|---|\n| \"the main office network\" | `--site hq` |\n| \"remote site firewall\" | `--site remote-site` |\n| \"the branch office\" | `--site branch-office` |\n| \"the Dream Machine Pro\" | `--site udmpro` |\n| \"the warehouse AP\" | `--site warehouse` |\n\nIf `--site` is omitted the first entry in the library is used. If the hint is ambiguous the skill lists the matching labels and asks for a more specific hint.\n\n**Always specify `--site` when the user mentions a location or device.** When the user says \"my network\" without specifying, run `library` first to show what sites are available and ask which one they mean.\n\n## How to give advice\n\n### Devices (`devices`, `device`)\n- `status != \"online\"` → offline or disconnected — surface to user\n- `firmwareStatus: \"updateAvailable\"` → firmware update pending\n- `device-stats` → CPU/memory/uptime signals for performance issues\n\n### Clients (`clients`, `client`)\n- High noise or weak signal → coverage gap, suggest AP placement review\n- Unexpected clients on sensitive VLANs → flag for review\n\n### Firewall (`firewall-policies`, `firewall-zones`, `acl-rules`)\n- Policies allowing all traffic between sensitive zones → flag as overly broad\n- Cross-zone allow rules → confirm intentional with user\n- Check `firewall-ordering` — rules are evaluated in order; misplaced rules cause unexpected behaviour\n\n### DNS (`dns-policies`)\n- Custom DNS policies can bypass filtering — flag any unexpected overrides\n\n### VPN (`vpn-tunnels`, `vpn-servers`)\n- Tunnel state down → connectivity issue to surface\n- Verify expected peers are configured\n\n### ISP metrics (`isp-metrics`)\n- Packet loss > 1% or latency spikes → WAN quality issue, advise checking with ISP\n\n## Notes\n\n- `network-refs` requires `--id` (a network ID). Only networks with active references (devices, clients, or WiFi assigned to them) return data — unused networks return a handled error: `\"Network '...' has no active references\"`. Run `networks` first to list all networks, then pass the ID of one that carries traffic.\n- `firewall-ordering` requires both `--from-zone` and `--to-zone`. Run `firewall-zones` first to list zone IDs. The API returns the ordered policy IDs for traffic flowing from the source zone to the destination zone.\n- `sdwan-config` and `sdwan-status` require `--id`. Run `sdwan` first to list configs and get an ID. These return empty on accounts without SD-WAN configured.\n\n## Source & contributing\n\nSource code, issue tracker, and contributions: [github.com/arseni-mik/open_claw-unifi-skill](https://github.com/arseni-mik/open_claw-unifi-skill/tree/main)\n\n## Constraints\n\n- All operations are GET-only. Never suggest using this skill to make changes.\n- Guide the user to make changes in the UniFi dashboard or mobile app.\n- Do not expose raw API keys in responses.\n","tags":{"latest":"1.0.2"},"stats":{"comments":0,"downloads":415,"installsAllTime":0,"installsCurrent":0,"stars":0,"versions":3},"createdAt":1778239957259,"updatedAt":1780234302431},"latestVersion":{"version":"1.0.2","createdAt":1780234302431,"changelog":"Move site library cache to ~/.openclaw for backup coverage","license":"MIT-0"},"metadata":{"setup":[{"key":"UNIFI_API_KEY","required":true}],"os":null,"systems":null},"owner":{"handle":"arseni-mik","userId":"s172mg1aabwe4y035d4cj7pk2186agtj","displayName":"arseni-mik","image":"https://avatars.githubusercontent.com/u/77124149?v=4"},"moderation":null}