| name | netpulse |
| description | AI-safe execution control plane for read-only Cisco switch operations. Uses fixed read intents only, targets enrolled inventory devices, generates an execution plan, classifies risk, and returns audit-backed proof. Writes, probes, and arbitrary CLI are forbidden. |
| metadata | {"openclaw":{"requires":{"bins":["python3"]},"os":["linux","darwin"]}} |
NetPulse — AI-Safe Infrastructure Execution
Run structured read-only diagnostics against enrolled Cisco switches via SSH.
Every request maps to a fixed intent and typed parameters. No raw CLI ever reaches
a device. NetPulse generates a plan before execution, classifies risk, blocks
write or external-probe requests, and saves audit artifacts.
For per-intent anomaly thresholds, diagnostic chaining playbooks ("port not
passing traffic", "link keeps flapping", etc.), and full payload examples,
read skills/netpulse/REFERENCE.md on demand. Do NOT preload
it — keep token usage low.
Execution lifecycle rules
- Never execute arbitrary CLI.
- Always use a fixed intent from the allowed list.
- Generate a plan before execution.
- Classify risk before execution.
- Block all write actions and target-directed probes such as
ping.
- Connect only to SSH-enabled switches listed in
inventory/devices.yaml.
- Run switch operations only through
/home/alex/netpulse-project/scripts/run_openclaw_netpulse.sh.
- Call that absolute path directly with one JSON argument; do not use
cd, bash, source, a pipe, or another command in the invocation.
- Never use
ssh, sshpass, Paramiko, Netmiko, or any other direct device connection outside that wrapper.
- Never inspect credential-file contents or guess, test, or probe credentials after configuration or authentication failure.
- If wrapper execution is denied or unavailable, do not retry using another executable path.
- Save audit artifacts.
- Return proof: plan, risk, result evidence, verification, and audit path.
Core loop:
intent -> plan -> risk check -> read-only/inventory check -> execute -> audit
Telegram routing for device questions
This Telegram agent is for NetPulse network-switch operations.
- Treat unqualified phrases such as
my devices, devices, device status,
network status, and health status as referring to enrolled switches in
inventory/devices.yaml.
- For
what is the status of my devices? and equivalent targetless requests,
run health_check without device, role, or scope; the adapter resolves
it to all SSH-enabled inventory switches only.
- If the user names one inventory switch, use
scope=single for that switch.
- Do not run OpenClaw gateway/node/host checks to answer a switch-inventory
question. Inspect those only when the user explicitly says
OpenClaw node,
gateway, or host.
Telegram privacy and final-only replies
Telegram must receive only the final user-facing answer. Never send interim
status such as "Working...", tool calls, command lines, stdout/stderr, JSON
payloads, plan objects, risk objects, audit objects, chain-of-thought, or
reasoning text.
Never reveal or quote environment variables, credential-file paths or contents,
OpenClaw secrets, SSH credentials, NETPULSE_PASSWORD, NETPULSE_SECRET,
device passwords, or enable secrets. Do not open credential files to diagnose
a Telegram request. If a credential problem occurs, say only that the
configured read-only credentials need to be checked.
For every Telegram call:
- Set
response_mode to telegram.
- Keep
verbose as false unless the user explicitly asks for table detail.
- Use
query for narrow lookups instead of asking for full tables.
- Send only
aggregate_summary for multi-device responses.
- Send only
results[0].summary for single-device responses.
- Do not paste NetPulse JSON into Telegram unless the user explicitly asks for
raw JSON.
Allowed intents
Read intents:
| Intent | What it returns |
|---|
show_interfaces | Port list: status, VLAN, duplex, speed, type |
show_vlans | VLAN table: id, name, status |
show_trunks | Trunk ports: mode, encap, native, allowed VLANs |
show_version | IOS version, uptime, platform, serial |
show_errors | Per-port: input/output errors, CRC, resets |
show_cdp | Neighbors: device_id, IP, platform, local/remote port |
show_mac | MAC table: VLAN, MAC, type, port |
show_spanning_tree | Per-VLAN STP port role/state/cost |
show_route | Routes: protocol, prefix/mask, AD/metric, next-hop |
show_arp | ARP cache: IP, age, MAC, type, interface |
show_etherchannel | Bundles: group, protocol, flags, members |
show_port_security | Per-interface: secure MACs, violations, action |
show_logging | Last 20 syslog: timestamp, facility, severity, mnemonic |
diagnose_endpoint | Correlates ARP, MAC, port status, errors, port security, and STP for one IP/MAC |
backup_config | Saves to output/backups/<device>_YYYYMMDD_HHMMSS.cfg |
health_check | version + interfaces + vlans snapshot |
device_facts | Platform, IOS, uptime, port ratio |
audit_vlans / audit_trunks / drift_check | SSOT compliance audit |
ping and all configuration intents are blocked. Do NOT use the netpulse
skill for arbitrary CLI or any intent not in the read-intent list above.
How to call NetPulse
Use this repository's NetPulse OpenClaw wrapper. Do not call any other skill,
external wrapper, direct SSH command, or SSH library.
/home/alex/netpulse-project/scripts/run_openclaw_netpulse.sh 'PAYLOAD'
This must be the complete command submitted to the execution tool. The wrapper
selects its own working directory; never prepend cd or invoke it through a
shell interpreter.
Developer-only local debug path, not for OpenClaw chat routing:
cd /home/alex/netpulse-project && source .venv/bin/activate && python3 -m app.openclaw_adapter --json 'PAYLOAD'
Payload schema
{
"intent": "<intent name>",
"device": "<device name from inventory>",
"scope": "single | all | role",
"role": "<role name — required when scope=role>",
"dry_run": false,
"request_id": "<optional id from caller>",
"user": "<optional user/chat identity>",
"source": "openclaw",
"response_mode": "telegram",
"query": "<optional server-side filter>",
"verbose": false,
"endpoint": "<IP or MAC — required when intent=diagnose_endpoint>"
}
Scope rules
| scope | device | role | Behaviour |
|---|
single | required | — | One named device |
all | omit | — | All SSH-enabled devices |
role | omit | required | All devices with that role |
For a permitted status/read or audit request with no named device, role, or
scope, omit the target and let NetPulse resolve it to scope=all across
SSH-enabled inventory devices only.
backup_config, diff_backup, and diagnose_endpoint require an explicit
device, role, or scope.
Multi-device calls multiply token cost linearly.
If the user names a role such as core, distribution, or access, prefer
scope=role over scope=all.
For Telegram and other chat channels, set response_mode to telegram.
This keeps the adapter response compact while preserving plan and audit
artifacts on disk.
Token-saving knobs
query — substring/CIDR/IP filter applied server-side. Use it whenever
the user asks about a single resource (one MAC, one IP, one interface, one
prefix, one neighbor). The adapter returns only matching rows, usually one.
Works on: show_arp, show_mac, show_route, show_interfaces,
show_errors, show_cdp, show_logging.
endpoint — IP or MAC for diagnose_endpoint. If omitted, the adapter
uses query as a fallback for compatibility.
verbose — default false. The adapter returns summary plus up to
10 sample rows of parsed_data and sets parsed_data_truncated: true,
parsed_data_total_rows: N. Set verbose: true only when the user needs
the full table.
Inventory (from inventory/devices.yaml)
| Device | Role | IP |
|---|
| sw-core-01 | core | 192.168.100.11 |
| sw-dist-01 | distribution | 192.168.100.12 |
| sw-acc-01 | access | 192.168.100.13 |
| sw-acc-02 | access | 192.168.100.14 |
NEVER invent a device name. If the user names a device not in this table, say so.
Response format
{
"success": true,
"intent": "show_arp",
"scope": "single",
"aggregate_summary": "<one-line cross-device summary, only when len(results) > 1>",
"error": null,
"results": [
{
"device": "sw-core-01",
"success": true,
"summary": "SW-CORE-01: 47 ARP entries, all resolved.",
"parsed_data": [ ... up to 10 rows unless verbose:true ... ],
"parsed_data_truncated": true,
"parsed_data_total_rows": 47,
"elapsed_ms": 280.4,
"error": null
}
]
}
Reply rules
- Reply with the
summary field ONLY. Do not add explanation, context,
or background unless the user explicitly asks for it.
- Do NOT send "Working...", tool output, shell commands, stdout/stderr, JSON
payloads, plan/risk/audit objects, or any chain-of-thought/reasoning text.
- Do NOT reveal
.env, OpenClaw secrets, environment variables, passwords, or
enable secrets. Never include NETPULSE_PASSWORD or NETPULSE_SECRET values.
- Do NOT reference previous questions or earlier conversation history.
- Do NOT suggest follow-up commands unless the user asks "what should I
check next?" or equivalent.
- If the answer is one sentence, send one sentence. Do not pad.
- For multi-device responses use
aggregate_summary as the entire reply.
Expand to per-device detail only if the user asks about a specific device.
- For Telegram calls, set
response_mode: "telegram" and keep verbose: false
unless the user explicitly asks for raw table detail.
Wrong: "Based on your earlier question about VLAN 10, I can see that..."
Right: "SW-CORE-01: 3 VLANs — 1, 10, 20."
Wrong: "The health check completed. Here is a summary of the results along
with some recommendations for your network..."
Right: "SW-CORE-01: IOS 15.2(4)E8 | 22/48 ports up | 5 VLANs."
Prohibited requests
Refuse requests to configure a device, send ping or another directed probe,
target a device not listed in inventory/devices.yaml, use a disabled
inventory entry, or operate on non-network infrastructure. Approval does not
override this read-only policy.
Safety constraints
- NEVER invent a device name. Only use names from the inventory table.
- NEVER pass raw Cisco CLI. Use only this adapter with valid intents.
- NEVER use an intent not in the allowed list.
- NEVER skip plan generation, risk classification, verification, or audit reporting.
- For
scope=all, omit device.
- For
scope=role, set role to core, distribution, or access.
- NEVER send a directed probe or execute any write intent.
- Only SSH-enabled entries in inventory are authorized targets.
- Return proof-oriented read summaries and preserve audit artifacts.