ImmyBot Command Reference

This comprehensive guide explains the powerful scripting capabilities available in ImmyBot through Metascripts, Cloud Scripts, and their associated commands.

Understanding Server-Side Scripts

Metascripts

A Metascript is a PowerShell script that runs in the ImmyBot backend and can execute commands on remote computers. Metascripts provide a powerful way to orchestrate actions across multiple devices while maintaining state in the ImmyBot backend.

Key capabilities of Metascripts:

  • Execute commands on remote computers
  • Pass objects between the server and client
  • Maintain context across reboots
  • Access ImmyBot’s internal APIs and data

Example: Comparing PowerShell Versions

$ServerPSVersionTable = $PSVersionTable
$ComputerPSVersionTable = Invoke-ImmyCommand {
    $ServerPSVersionTable = $using:ServerPSVersionTable
    Write-Host "Running from $env:ComputerName but ImmyBot backend is running PowerShell $($ServerPSVersionTable.PSVersion)" -ForegroundColor Green
    return $PSVersionTable
}
$VerbosePreference = 'Continue'
Write-Verbose "Running from ImmyBot backend, but the computer is running Windows PowerShell $($ComputerPSVersionTable.PSVersion)"

Output:

PowerShell Version Comparison

Invoke-ImmyCommand is modeled after PowerShell’s native Invoke-Command, with the ability to pass real objects into and out of the remote runspace while preserving stream information. This approach is superior to capturing standard output and standard error as strings, which is common in many automation tools.

Cloud Scripts

Cloud Scripts are similar to Metascripts but target a Tenant instead of a specific computer. They’re particularly useful for:

  • Managing tenant-wide settings
  • Interacting with cloud services like Microsoft 365
  • Performing operations across all computers in a tenant
  • Manipulating settings in each customer’s Azure environment

Collectively, Metascripts and Cloud Scripts are referred to as "server-side scripts" in ImmyBot.

Common Commands

These commands are available in all server-side scripts.

Azure Integration Commands

Connect-ImmyAzureAD

Provides a wrapper around Connect-AzureAD to authenticate with Azure AD.

Usage:

Connect-ImmyAzureAD [-UseMSPTenant] [<CommonParameters>]

Example:

# Authenticate with Azure AD and retrieve all users

Connect-ImmyAzureAD
$users = Get-AzureADUser -All $true
Write-Host "Found $($users.Count) users in Azure AD"

Parameters:

  • -UseMSPTenant: Authenticate using the MSP tenant instead of the current tenant

Documentation: Microsoft Connect-AzureAD Reference

Get-ImmyAzureAuthHeader

Obtains an authentication header for the specified Microsoft endpoint.

Usage:

Get-ImmyAzureAuthHeader [[-Endpoint] <string>] [-UseMSPTenant] [<CommonParameters>]
Get-ImmyAzureAuthHeader [-ResourceUri] <uri> [-UseMSPTenant] [<CommonParameters>]

Example:

# Get authentication header for Microsoft Graph API

$Header = Get-ImmyAzureAuthHeader -Endpoint "MSGraph" -ErrorAction Stop

# Use the header to make a Graph API request

$Groups = Invoke-RestMethod "https://graph.microsoft.com/v1.0/groups/" -Headers $Header
Write-Host "Found $($Groups.value.Count) groups in Azure AD"

Parameters:

  • -Endpoint: Endpoint to authenticate against. Accepts "MSGraph" (default), "AzureAD", or "KeyVault"
  • -ResourceUri: Obtain the auth header for an arbitrary resource URI instead of a named endpoint
  • -UseMSPTenant: Retrieve the auth header from the MSP tenant instead of the current tenant

Returns: A dictionary containing the authentication header

RMM Integration Commands

Get-ProviderInfo

Retrieves an instance of an RMM Provider for the specified type.

Alias: Get-RmmInfo

Usage:

Get-ProviderInfo [-ProviderType] <string> [-IncludeClients] [-IgnoreLinkedProvider] [<CommonParameters>]

Example:

# Get information about the ConnectWise Automate integration

$RmmInfo = Get-ProviderInfo -ProviderType CWAutomate
Write-Host "Connected to $($RmmInfo.LinkName) ($($RmmInfo.ProviderType))"

Parameters:

  • -ProviderType: (Mandatory) The type of RMM provider (e.g., "CWAutomate", "NinjaRMM")
  • -IncludeClients: Include client information from the RMM
  • -IgnoreLinkedProvider: When running in the context of a maintenance item linked to a provider, return the provider of the specified type instead of the linked provider

Returns: A ProviderInfo object containing the provider link details, an instance of the provider for making API calls, and (with -IncludeClients) the linked clients

Example: Updating a ConnectWise Automate EDF Field

param(
    [string]$FieldName,
    [string]$Value,
    $Computer
)

# Get the current computer if not specified

if(!$Computer) {
    $Computer = Get-ImmyComputer
}

# Get the RMM computer and provider information

$RmmComputer = Get-RmmComputer -Computer $Computer -ProviderType CWAutomate
$RmmInfo = Get-ProviderInfo -ProviderType CWAutomate

# Find the EDF field

$EDF = Get-CWAComputerEDF -FieldName $FieldName -Computer $Computer
if(!$EDF) {
    Write-Warning "Aborting: Unable to find EDF $FieldName"
    return
}

# Update the EDF field value

$ExtraFieldDefinitionId = $EDF.ExtraFieldDefinitionId
$ValueProperty = $EDF | Select-Object *FieldSettings* | Get-Member -MemberType NoteProperty | Select-Object -First 1 | ForEach-Object {$_.Name}
$PatchPath = "$ValueProperty/Value"
$Uri = "cwa/api/v1/computers/$($RmmComputer.RmmDeviceId)/extrafields/$ExtraFieldDefinitionId"
$Body = ConvertTo-Json @(@{"op"="replace";"path"=$PatchPath;"value"=$Value})
Invoke-CWARestMethod $Uri -Provider $RmmInfo.Provider -Method PATCH -Body $Body

Metascript Commands

Remote Execution

Invoke-ImmyCommand

A powerful command that allows you to execute scripts remotely on devices.

Usage:

Invoke-ImmyCommand [-ScriptBlock] <scriptblock> [-Computer <PSComputer[]>] [-ContextString <string>] [-ArgumentList <array>] [-Timeout <int>] [-ConnectTimeout <int>] [-AgentConnectionWaitTimeout <timespan>] [-Parallel] [-DisableConnectTimeoutWarnings] [-IncludeLocals] [-ScriptType <string>] [-ScriptName <string>] [-CircuitBreakerPolicy <string>] [<CommonParameters>]

Examples:

# Basic example - run a command on the current computer
Invoke-ImmyCommand {
    Write-Output "Hello from $env:COMPUTERNAME"
    Get-Service | Where-Object { $_.Status -eq 'Running' } | Select-Object -First 5
}

# Run a command on all workstations in parallel
Get-ImmyComputer -TargetGroupFilter Workstations | Invoke-ImmyCommand -Parallel {
    $ComputerInfo = Get-ComputerInfo
    [PSCustomObject]@{
        ComputerName = $env:COMPUTERNAME
        OSVersion = $ComputerInfo.OsVersion
        LastBoot = $ComputerInfo.OsLastBootUpTime
        FreeMemory = [math]::Round($ComputerInfo.OsFreePhysicalMemory / 1MB, 2)
    }
} | Format-Table -AutoSize

Parameters:

  • -ScriptBlock: The PowerShell script to execute remotely
  • -Computer: The target computer(s) to run the script on
  • -ContextString: Either "System" (default) or "User" execution context
  • -TerminateFromNoLoggedOnUser: Dynamic parameter, only available with -ContextString User. When no user is logged on, turns the per-computer skip into a terminating error instead of a warning
  • -ArgumentList: Arguments to pass to the script
  • -Timeout: Maximum execution time in seconds (default: 120)
  • -ConnectTimeout: Time to wait for connection in seconds (only has an effect when service bus script results are enabled in app preferences)
  • -DisableConnectTimeoutWarnings: Suppress timeout warnings (only has an effect when service bus script results are enabled in app preferences)
  • -Parallel: Run the script on all computers simultaneously
  • -AgentConnectionWaitTimeout: How long to wait for an offline agent to connect before continuing
  • -IncludeLocals: Include the calling script’s variables in the remote script block
  • -ScriptType: Script language of the script block (PowerShell or CommandLine)
  • -ScriptName: Name used for metric tracking (defaults to the calling script’s name)
  • -CircuitBreakerPolicy: Circuit breaker policy applied to the computer (default: Unrestricted)

Using the $using Scope Modifier:

The $using scope modifier allows you to reference variables from the calling script in your remote script block:

$AppName = "Microsoft Office"
$Results = Invoke-ImmyCommand {
    $App = Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -like "*$using:AppName*" }
    if ($App) {
        return [PSCustomObject]@{
            Name = $App.Name
            Version = $App.Version
            Installed = $true
        }
    } else {
        return [PSCustomObject]@{
            Name = $using:AppName
            Version = $null
            Installed = $false
        }
    }
}

Email Notifications

Send-ImmyEmail

Sends an ImmyBot-styled email to specified recipients.

Usage:

Send-ImmyEmail [-Subject] <string> [-Body] <string> [[-To] <List[string]>] [[-Bcc] <List[string]>] [<CommonParameters>]

Example:

# Send an email through ImmyBot's built-in email (no -To specified)
Send-ImmyEmail -Subject "Weekly Maintenance Report" -Body "All systems have been updated successfully."

# Send an email to specific recipients
Send-ImmyEmail -Subject "Critical Update Required" -Body "Please approve the pending update." -To @("[email protected]", "[email protected]")

Parameters:

  • -Subject: Email subject line
  • -Body: Email body content (can be HTML)
  • -To: List of email addresses to send to
  • -Bcc: List of email addresses to BCC

Returns: A status message (for example, "Sent")

Computer Management

Refresh-ComputerSystemInfo

Updates ImmyBot’s inventory information for the specified computer.

Usage:

# Refresh information for the current computer
Refresh-ComputerSystemInfo

# Refresh information for all servers
Get-ImmyComputer -TargetGroupFilter Servers | Refresh-ComputerSystemInfo

This command runs the WindowsSystemInfo inventory task and updates the computer information that includes:

  • ComputerName
  • SerialNumber
  • ChassisTypes
  • DomainRole
  • Domain
  • OsName
  • OsInstallDate
  • LastBootTime
  • Model
  • Manufacturer
  • OsDisplayVersion
  • EditionId
  • Version
  • BuildNumber
  • UBR
  • LastInstallSuccessUtc
  • LastScanSuccessUtc

Parameters:

  • -Computer: The computer to refresh information for (defaults to current session computer)

Returns: None – the computer’s inventory is updated in place

Get-RmmComputer

Retrieves RMM-specific information about a computer. This is an alias for Get-ProviderAgent.

Usage:

Get-RmmComputer [-Computer <PSComputer[]>] [-ProviderType <string>] [<CommonParameters>]

Example:

# Get RMM information for the current computer
$RmmComputer = Get-RmmComputer
Write-Host "RMM Device ID: $($RmmComputer.RmmDeviceId)"

Parameters:

  • -Computer: The computer(s) to retrieve agent details for (defaults to the current session computer)
  • -ProviderType: Only return agents for the specified provider type (e.g., "CWAutomate")

Returns: A PSProviderAgent object containing the provider’s agent details for the computer, including agent and client IDs, online status, agent version, and device details

Get-ImmyComputer

Retrieves ImmyBot computer objects.

Get-ImmyComputer has two implementations, bound by script context. This one is available in Metascripts and Cloud Scripts. A separate implementation with a narrower parameter set (no -DeviceId, -IncludeOffline, or -UseParentTenant) is available only in Filter Scripts – see Get-ImmyComputer (Filter Script) under Filter Script Commands.

Behavior differs by context: in a Cloud Script (or whenever -TargetGroupFilter is specified), it returns all computers matching the filter; in a Metascript without -TargetGroupFilter, it returns the current session’s computer.

Usage:

Get-ImmyComputer [[-TargetGroupFilter] <string>] [[-InventoryKeys] <array>] [[-DeviceId] <guid>] [-IncludeOffline] [-OnboardingOnly] [-IncludeTags] [-UseParentTenant] [<CommonParameters>]

Example:

# Cloud Script - returns all computers in the tenant
# (in a Metascript without -TargetGroupFilter, returns only the current session's computer)
$Computers = Get-ImmyComputer
Write-Host "Found $($Computers.Count) computers in the tenant"

# Get computers along with a specific inventory key's data, then filter on it
$WindowsComputers = Get-ImmyComputer -InventoryKeys WindowsSystemInfo | Where-Object { $_.Inventory.WindowsSystemInfo.OsName -like "*Windows 10*" }

Parameters:

  • -TargetGroupFilter: Target group filter to apply when retrieving computers: All, Servers, Workstations, PortableDevices, WorkstationsAndPortableDevices, DomainControllers, PrimaryDomainControllers
  • -InventoryKeys: Array of inventory key names whose data should be included on the returned computer objects (for example WindowsSystemInfo) – it does not filter which computers are returned; filter on the returned .Inventory data with Where-Object
  • -DeviceId: The DeviceId of a specific computer to retrieve
  • -IncludeOffline: Include offline computers in the results
  • -OnboardingOnly: Limit the results to only onboarding computers
  • -IncludeTags: Include tags in the computer information
  • -UseParentTenant: Retrieve computers from the parent tenant instead of the current tenant

Returns: A collection of computer objects, one per computer, with data for any requested -InventoryKeys attached under .Inventory

Session Control

Set-ImmySession

Updates the reboot preference of the current maintenance session.

Usage:

Set-ImmySession [-RebootPreference] <string> [<CommonParameters>]

Example:

# Suppress reboots for the remainder of this session
Set-ImmySession -RebootPreference Suppress

Parameters:

  • -RebootPreference: (Mandatory) The reboot preference for the session: Force, Normal, Suppress, or Prompt

Stop-ImmySession

Cancels the current maintenance session. The current maintenance action (if any) is marked as cancelled and the session is stopped. Only available within a maintenance session.

Usage:

Stop-ImmySession [-PendingMessage <string>] [-SuccessMessage <string>] [-FailureMessage <string>] [<CommonParameters>]

Example:

# Cancel the current maintenance session
Stop-ImmySession

Parameters:

  • -PendingMessage: Message recorded when the action is marked cancelled (default: "Cancelling session #{SessionId}…")
  • -SuccessMessage: Message recorded when the session is cancelled (default: "Cancelled session #{SessionId} successfully.")
  • -FailureMessage: Message recorded if cancellation fails (default: "Failed to cancel session #{SessionId}.")

The {SessionId} placeholder in each message is replaced with the current session ID.

Caching and Concurrency

Invoke-CommandCached

Invokes a script block and caches its result. The script block only runs when nothing is cached under the key or the previous value has expired; otherwise the cached value is returned. A keyed lock ensures only one script executes a given key at a time.

Usage:

Invoke-CommandCached -CacheKey <string> -ScriptBlock <scriptblock> -TTL <timespan> [-ForceUpdate] [<CommonParameters>]

Example:

# Cache the result for one hour
$Computers = Invoke-CommandCached -CacheKey "WorkstationInventory" -TTL (New-Timespan -Hours 1) -ScriptBlock {
    Get-ImmyComputer -TargetGroupFilter Workstations
}

Parameters:

  • -CacheKey: (Mandatory) Unique key to store the cached result under
  • -ScriptBlock: (Mandatory) Script block executed on a cache miss or after expiration
  • -TTL: (Mandatory) Time-To-Live for the cached item (e.g. New-Timespan -Hours 1)
  • -ForceUpdate: Bust the cache for this key even if it has not expired

Returns: The output of the script block – either freshly executed on a cache miss, or the cached value

Invoke-AtomicCommand

Acquires an exclusive lock for the given key across the entire ImmyBot instance (all Cloud and Meta scripts), then executes the script block. Use it to guard critical sections against concurrent execution. A watchdog releases locks held by deadlocked scripts.

Usage:

Invoke-AtomicCommand [-ScriptBlock] <scriptblock> -Key <string> [<CommonParameters>]

Example:

# Only one script at a time can run this critical section instance-wide
Invoke-AtomicCommand -Key "License-Refresh" -ScriptBlock {
    # critical section
}

Parameters:

  • -Key: (Mandatory) Unique lock key. The lock is shared across all Cloud and Meta scripts on the instance, so choose keys deliberately
  • -ScriptBlock: (Mandatory) Script block executed once the exclusive lock is acquired

Returns: The output of the script block

File Transfer

New-ImmyUploadSasUri

Creates a shared access signature (SAS) URI for ImmyBot’s upload blob storage that can be used to transfer files to or from the server or a computer.

Usage:

New-ImmyUploadSasUri [-BlobName <string>] [-Permission <string>] [-ExpiryTime <datetime>] [<CommonParameters>]

Example:

# Get a SAS Uri for uploading a file to a specific blob
$SasUri = New-ImmyUploadSasUri -BlobName "reports/report.zip" -Permission "rw"

Parameters:

  • -BlobName: Name of the target blob. When omitted, a container-level SAS is returned instead
  • -Permission: Permissions granted by the SAS, built from "racwdl" (r Read, a Add, c Create, w Write, d Delete, l List). Defaults to "rw" when -BlobName is specified and "rwl" when omitted. Delete ("d") is only allowed when -BlobName is specified
  • -ExpiryTime: Expiration for the SAS (defaults to 1 day from now)

Returns: The SAS URI string

Related: Upload-ImmyFile is a global Function script built on this cmdlet. It derives the blob name from the file name, requests a rw SAS URI, uploads the file from the target computer via Invoke-ImmyCommand and Invoke-RestMethod, and returns the uploaded blob’s URI. Use it for the common "upload a file from a computer and get a link back" case; use New-ImmyUploadSasUri directly when you need custom blob naming, permissions, or expiry.

API Access

Invoke-ImmyApi

Calls the ImmyBot HTTP API by operation ID and returns the response. Path and query parameters go at the top level of -Parameters; request bodies go under a body key. Responses are converted to PowerShell-friendly objects that work with Select-Object, Sort-Object, and Group-Object.

Requires an interactive auth context – it is unavailable in background or system-initiated metascripts.

Usage:

Invoke-ImmyApi [-Operation] <string> [[-Parameters] <hashtable>] [<CommonParameters>]

Example:

# List computers (query parameters at the top level)
$Computers = Invoke-ImmyApi -Operation Computers.GetAll -Parameters @{ name = "LAPTOP"; pageSize = 50 }

# Call an operation that takes a request body
Invoke-ImmyApi -Operation SomeOperation -Parameters @{ id = 5; body = @{ Name = "Example" } }

Parameters:

  • -Operation: (Mandatory) The API operation ID to invoke
  • -Parameters: Hashtable of path/query parameters and, for operations that accept one, the request body under a body key

Returns: The API response as PowerShell-friendly objects (each JSON object becomes a PSObject; top-level arrays are enumerated into the pipeline)

By default, HTTP failures throw a terminating error with the status code and response body available on the exception. With -ErrorAction SilentlyContinue (or Ignore), failures return a hashtable (Success, StatusCode, OperationId, Parameters, Error) instead of throwing.

Filter Script Commands

Filter Scripts run in one of two modes, set per script:

  • Optimized (recommended): the script runs once per tenant, returns only computer IDs (int[]), and its result is cached until the script is edited. It has no per-computer context – any filter that must evaluate the current session’s computer can only be done in Legacy mode.
  • Legacy: the script runs with the current session’s computer bound and may return fully hydrated computer objects, but results are never cached.

Returning IDs is a hard requirement in Optimized mode. Prefer Get-ImmyComputerIds, which returns exactly what Optimized mode expects. If you need filtering only Get-ImmyComputer provides (for example, inventory-based Where-Object), project just the IDs – returning full computer objects fails conversion per item and yields an empty result:

# This is an example of how to use Get-ImmyComputer in an Optimized Filter Script
Get-ImmyComputer -InventoryKeys WindowsSystemInfo |
    Where-Object { $_.Inventory.WindowsSystemInfo.OsName -like "*Windows 10*" } |
    Select-Object -ExpandProperty Id

Get-ImmyComputer

Returns a list of computers for the specified tenant, or all computers if it is cross-tenant scoped.

Get-ImmyComputer has two implementations, bound by script context. This one is available only in Filter Scripts (such as deployment target filters) and supports a narrower parameter set than the version available in Metascripts and Cloud Scripts – see Get-ImmyComputer (Metascript/Cloud Script) under Computer Management.

Usage:

Get-ImmyComputer [[-InventoryKeys] <array>] [[-TargetGroupFilter] <string>] [-OnboardingOnly] [-IncludeTags] [<CommonParameters>]

Example:

# Legacy mode - returns computer objects
# Get all Windows 10 computers
Get-ImmyComputer -InventoryKeys WindowsSystemInfo | Where-Object {$_.Inventory.WindowsSystemInfo.OsName -like "*Windows*10*" }

# Get all Dell computers
Get-ImmyComputer -InventoryKeys WindowsSystemInfo | Where-Object {$_.Inventory.WindowsSystemInfo.Manufacturer -like "*Dell*" }

Parameters:

  • -InventoryKeys: Array of inventory key names whose data should be included on the returned computer objects (use Where-Object afterward to filter on that data)
  • -TargetGroupFilter: Target group filter to apply when retrieving computers: All, Servers, Workstations, PortableDevices, WorkstationsAndPortableDevices, DomainControllers, PrimaryDomainControllers
  • -OnboardingOnly: Limit the results to only onboarding computers
  • -IncludeTags: Include tags in the computer information

Returns: A collection of computer objects, one per computer, with data for any requested -InventoryKeys attached under .Inventory

Get-ImmyComputerIds

Returns an array of computer IDs matching the specified criteria. Supports filtering by target group, onboarding status, tag, and installed software (with optional version comparison).

Usage:

Get-ImmyComputerIds [-TargetGroupFilter <string>] [-OnboardingOnly] [-Tag <string>] [-SoftwareFilter <string>] [-SoftwareSearchMode <string>] [-SoftwareComparisonOperator <string>] -SoftwareVersion <string> [<CommonParameters>]

Example:

# Get the IDs of workstations that still need onboarding
Get-ImmyComputerIds -TargetGroupFilter Workstations -OnboardingOnly

# Get the IDs of computers with a version of Chrome older than 120
Get-ImmyComputerIds -SoftwareFilter "Chrome" -SoftwareComparisonOperator "<" -SoftwareVersion "120"

Parameters:

  • -TargetGroupFilter: Target group filter to apply: All, Servers, Workstations, PortableDevices, WorkstationsAndPortableDevices, DomainControllers, PrimaryDomainControllers
  • -OnboardingOnly: Limit the results to only onboarding computers
  • -Tag: Limit the results to computers with the specified tag (matches computer, owner tenant, or primary person tags)
  • -SoftwareFilter: Limit the results to computers with the specified software installed
  • -SoftwareSearchMode: How -SoftwareFilter is applied: Contains (default) or Regex
  • -SoftwareComparisonOperator: Comparison operator for -SoftwareVersion: <, <=, =, >, or >=
  • -SoftwareVersion: The software version to compare against (requires -SoftwareComparisonOperator)

Returns: An array of computer IDs (int[])

Best Practices

When working with ImmyBot commands, consider these best practices:

Error Handling: Always include proper error handling in your scripts

try {
    $Result = Invoke-ImmyCommand {
        # -ErrorAction Stop ensures non-terminating errors thrown inside
        # the script block are caught by this catch block
        Get-Service -Name WinRM -ErrorAction Stop
    } -ErrorAction Stop
}
catch {
    Write-Error "Failed to execute command: $_"
    throw
}

Timeout Management: Set appropriate timeouts for long-running operations

Invoke-ImmyCommand { Start-Process -FilePath "C:\Setup.exe" -Wait } -Timeout 300

Parallel Execution: Use the -Parallel parameter for bulk operations

Get-ImmyComputer -TargetGroupFilter All | Invoke-ImmyCommand -Parallel { Get-HotFix }

Variable Scope: Use the $using: scope modifier to reference local variables

$appName = "Chrome"
Invoke-ImmyCommand { Get-Process -Name "*$using:appName*" }

Context Awareness: Specify the appropriate context for your commands

# Run in system context (default)
Invoke-ImmyCommand { Get-Service } -ContextString System

# Run in user context
Invoke-ImmyCommand { Get-Process } -ContextString User

Was this article helpful?

Previous Article

Scripting Guide

Next Article

Deployment Resolution