cwa_* — ConnectWise Automate

The ConnectWise Automate (RMM) tool namespace — searching computers, running scripts and commands, and the output-capture quirks that make CWA different from a normal shell.

ConnectWise Automate (CWA) is the RMM. These tools find managed computers, read their state, and run scripts/commands on them. The hard part isn’t the API — it’s that CWA’s command channel lies about output. Read the output-capture section before you try to run anything and read its stdout.

Finding computers

The workhorse for locating computers. Almost always what you want — not cwa_get.

cwa_search(name=None, condition=None, page=1, page_size=50)
ParamTypeNotes
namestringSubstring match on computer name
conditionstringRaw OData condition for anything name can’t express
page / page_sizeintPagination; defaults 1 / 50

cwa_get

Direct record lookup by entity type and ID, or a filtered list. Use this when you already have an ID, or need an entity other than computers.

cwa_get(entity_type, id=None, condition=None, page=1, page_size=50)

entity_type is required. For finding a computer by name, use cwa_search instead — see the routing table.

cwa_status

Quick health overview — alerts and offline agents — without composing a query.

cwa_status(include_alerts=True, include_offline=True, offline_limit=10)

Running scripts and commands

cwa_execute

Run a saved CWA library script on a computer. This path uses Scripts/{id}/execute and is the clean way to get real, captured output.

cwa_execute(computer_id, script_id, parameters=None)

parameters is a {string: string} map of the script’s script-variable inputs. Discover script_id with cwa_search_scripts first — there is usually already a library script for what you need.

cwa_run_command

Queue an ad-hoc command on a computer. Verified against POST /Computers/{id}/CommandExecute.

cwa_run_command(computer_id, command=None, command_type="2", shell="cmd",
                parameters=None, auto_encode=True, force_encode=False,
                auto_salt_on_duplicate=True, poll=True, poll_attempts=20,
                poll_interval=2, fastalk=True)
command_typeMeaningOutput behavior
"2"Execute Command (default)Fire-and-forget — always returns Output: "ERR". Status reflects launch only.
"301"Invoke ScriptOnly runs scripts already in the CWA library; rejects ad-hoc text with "Invalid script to run"
"22"Update ConfigsReturns real status text in Output

Two built-in safety behaviors worth knowing:

  • Auto-encode: when command contains shell metacharacters (| & > < ^), it’s auto-wrapped as powershell.exe -NoProfile -NonInteractive -EncodedCommand <base64> so the metachars survive the JSON/parameter-array boundary. Disable with auto_encode=False; force with force_encode=True. The actual array sent comes back in rendered_parameters.
  • Auto-salt on duplicate: CWA returns 400 "Duplicate command." for an identical pending command. With auto_salt_on_duplicate=True (default) the call retries once with a :: leif-salt-<ms> suffix; retried_with_salt is set in the response when it fires.

cwa_run_powershell

The only path that returns real PowerShell stdout. It encodes your script as base64 UTF-16-LE and runs it through a library shim script.

cwa_run_powershell(computer_id, script, shim_script_id,
                   poll_interval=3, poll_attempts=20)

Prerequisite: a library script named Leif - Run Encoded PowerShell must exist. Find its ID with cwa_search_scripts(name="Leif - Run Encoded PowerShell") and pass it as shim_script_id. The shim must accept an EncodedCommand param, set @ScriptEngineEnableLogger@ = True, run powershell.exe -NoProfile -NonInteractive -EncodedCommand @EncodedCommand@, and log the output via a “Log Variable” step.

Returns status, output, diagnostic_message, history_id, ran_at, attempts.

Scripts and history

cwa_search_scripts

Search the CWA script library before writing your own diagnostic logic — there’s almost certainly already a “Get Eventlog Last 24h” or similar. Pass the discovered Id to cwa_execute.

cwa_search_scripts(name=None, condition=None, page=1, page_size=50)

cwa_script_history

Recent script-run history for a computer. Each record’s DiagnosticMessage is the full execution log with captured variable values — the primary stdout-capture surface in CWA. Filter to one script with script_id when polling a run you just triggered.

cwa_script_history(computer_id, script_id=None, limit=10)

Low-level access

cwa_raw_request

Raw authenticated CWA API call. Unlike the other tools it never raises on 4xx/5xx — it returns status_code, headers, and body_text so you can diagnose schema mismatches or explore endpoints.

cwa_raw_request(method, path, body=None, params=None)

path begins with / (e.g. /Commands).

cwa_probe_command_endpoint

Probes the known command-endpoint path variants with POST and reports status codes (200/202 working, 405 wrong method, 404 not found), caching the winner for subsequent cwa_run_command calls.

cwa_probe_command_endpoint(computer_id)

Getting real output from CWA

The recurring trap. CWA’s “Execute Command” channel reports launch success, not output. To actually read what ran:

  1. Look for a library script firstcwa_search_scripts(name="...").
  2. Run it with cwa_execute(computer_id, script_id) — this returns real captured output.
  3. For ad-hoc PowerShell, use cwa_run_powershell with the encoded-PS shim.
  4. To read back a past run, pull cwa_script_history and read DiagnosticMessage.

If you find yourself parsing "ERR" and wondering what went wrong: nothing did. You used the wrong channel.

  • Tools — catalog overview and routing rules
  • Network Topology — customer-site reachability for CWA-managed endpoints
  • Hudu — the IT documentation system CWA assets are documented in