Add New Playbook
-
Click on the [Playbook] main tab.
-
Click on the
button.

-
In the [Add New Playbook] popup window, enter the “Name” of the Playbook, and a corresponding “Description”.
-
Click [OK].

Create Playbook
To create a Playbook:
-
Click on the [Playbook] main tab.
-
Doubleclick your new Playbook.
The [Node] panel will appear on the right side of the screen.
- Click and hold a Node from the [Node] panel on the right side of the window, and drag it to the Playbook Field.
Nodes
Nodes are individual components that perform specific tasks, such as device communication, data processing, or conditional logic. They can be visually connected to create complex operational sequences called Playbooks.
Once a Node is in the Playbook Field, click the
button in the top right corner of the node to change the descriptive Alias of the Node.

Node List
The [Node] panel is on the right side of the screen. These are the different components that can be composed together to create a Playbook.
| Node Option | Explanation |
|---|---|
| And | Only proceed after both inputs have received a signal |
| Backup Device | Run a device backup |
| Chat App (Webhook) | Send messages to one of the following applications: Teams/Slack/Mattermost/Webex/Line using a pre-configured Webhook |
| Compliance Remediation | Get information from a Compliance Rule Set configured to run this playbook |
| Merge by Device | Combine inputs to a single output per device |
| Device Search | Search for devices in the inventory to be acted upon |
| Send an email with tabular data | |
| Execute Script | Run a Python script configured here on your Script Executor Container and output the results |
| Execute Existing Script | Run a Python script already saved on your Script Executor Container and output the results |
| Incident | Get information from an alert policy configured to run this Playbook |
| Load Configuration | Load and output a configuration file from a previous device backup |
| Memo | Save a note |
| Raise Compliance Violation | Create a Violation on the passed in device with a configured message and severity |
| Regex Match | Execute a regular expression against the output of a node |
| Rule Set | Run a Rule Set against the output of a node |
| Run Code | Run a block of code on your devices |
| Run Code with Automatic Retry | Run a block of code on your devices a number of times or until it is successful |
| Schedule | Schedule this playbook to run automatically |
| Set Variables | Set or update variables before forwarding input |
| Sleep | Delay for a number of milliseconds before forwarding input |
| SSH Exec | Execute a command on remote SSH host |
| To CSV | Serialize data to text formatted as comma separated values |
| To Json | Serialize data to text formatted as JSON |
| Update Fields | Update a Device’s custom fields, variables can be placed into a fields by writing the variable name wrapped in {curly brackets} |
| Upload File | Send a file to your devices |
Node Types by Position
Nodes are classified into “Start”, “Middle”, and “Terminal” based on their input/output terminals:
Start Nodes (Initiate processes)
- Device Search: Selects devices from inventory
- Compliance Remediation: Triggers on policy violations
- Incident: Starts with alert policy triggers
- Schedule: Time-based activation
Middle Nodes (Process data/decisions)
- And: Requires multiple input conditions
- Execute Script: Run a Python script configured here on your Script Executor Container and output the results
- Execute Existing Script: Run a Python script already saved on your Script Executor Container and output the results
- Regex Match: Filters text outputs and can set variables from Java 8 regex style capture groups
- Run Code: Executes a series of commands on your device
- Run Code With Automatic Retry: Run a series of commands on your device a number of times or until it is successful
- Ruleset: Run a ruleset against the output of a node
- Merge by Device: Combines inputs based on the device each is associated to
- Sleep: Adds timed delays (1ms-2h)
- SSH Exec: Runs CLI commands
- Load Configuration: Load a previously backed up configuration file, often for use in verification nodes later in the Playbook
- Backup Device: Run a device backup
- Set Variables: Set or update variables on inputs for use as replacements later in the Playbook
- To CSV: Serialize inputs to text formatted as comma separated values
- To Json: Serialize data to text formatted as JSON
- Update Fields: Update a Device’s custom fields, variables can be placed into fields by writing the variable name wrapped in {curly brackets}
- Upload File: Send a file to your devices
Terminal Nodes (Final outputs)
- Email: Send an email with a configurable summary of actions performed in the playbook
- Chat Webhook: Sends a message to Teams/Slack/Mattermost/Webex/Line using a pre-configured Webhook integration
- Raise Compliance Violation: Sends Compliance Violation notifications
Note:
There have been recent changes to the Nodes side panel:
- The icon for the [Regex Match], Node has been updated:
- A new node, [Merge by Device], has been added:
- A new node, [Load Configuration], has been added:
- A new node, [Raise Compliance Violation], has been added:
Node Search
You can search for Nodes that you want to add by name, or filter the Nodes that are visible in the Nodes list by using the Nodes Search function at the top of the right sidepanel.

Add Node
To add a Node:
-
Click the [Playbook] main tab.
-
Doubleclick the Playbook to which the Node will be added.
-
Click and drag a Node from the Node list in the righthand panel, to the Playbook Field.
Select Device
To select a device:
-
Click the [Playbook] main tab.
-
Create or open a Playbook.
-
Add a “Device Search” Node to you workflow from the Node list on the right side of the window.
-
On the “Device Search” Node, click [Device Selection].

There are three options in the [Device Selection] window:

| Option | Explanation |
|---|---|
| All Devices | Select all devices in the [Inventory] tab |
| Search | Select the [Add Criteria] and select options to select devices |
| Static List | Select devices from the [Inventory] tab and add to the selection |
Selecting “Search” allows you to narrow your search using multiple criteria.

Run Code
To run code on a device:
-
Add a “Run Code” Node to your workflow from the Node list on the right side of the window.
-
Click the [Code Editor] button.
-
Enter a
clicommand for the devices you have selected.

Raise Compliance Violation
The [Raise Compliance Violation] Node sends Compliance Violation notifications to users via four methods:
- Webhook to Teams/Slack/Webex/Line/PagerDuty/Google Chat
- Both email and Webhook
- Notifications in ThirdEye’s [Inventory] main tab > Editor [Compliance] tab.

To view the details of the Violation in ThirdEye’s [Compliance] tab:
-
Click the [Inventory] main tab.
-
Doubleclick the device to open the its Editor window at the bottom of the screen.
-
Click the Editor’s [Compliance] tab.

The source of the Violation severity icon, Compliance Violation, Compliance Policy Name, and Violation message are displayed in the left sidepanel of the Editor.

For more information about the Violation, you can click the [Playbook] main tab to check the Violation History.
The History is located in the right sidepanel.

Connect Nodes
You can connect Nodes to create Playbook.

To connect nodes, click and drag from an output port (right side) of one Node, to an input port (left side) of another node.
Press [Backspace] on your keyboard to remove unwanted connections.

Nodes may also be connected by holding shift and dragging one close to another, a preview line will show where the connection will be made once you let go of the Node. The Node you’re dragging will only ever connect to the first handle, however you can move this node up or down to select the handle you want to connect to on the other Node.
Remove Nodes or Connection
To remove a node, or a connection, select the desired item, and click on [Backspace] on your keyboard.
Running a Playbook
-
Open the [Playbook] main tab.
-
Doubleclick the Playbook you want to run.
-
Click the [Run]
button in the menu bar at the top of the window.
The Run button may be disabled based on your permissions and the Playbook’s approval status. Playbooks are subject to the [Approval Function]. Approvals for Playbooks may be managed within both the Playbooks and Jobs Tabs. The same permissions for Jobs are applicable to Playbooks.
| Permission | Explanation |
|---|---|
| Permission to approve a tool job execution. | Authority to approve playbooks that have been requested for approval (approval request). |
| Permission to run a tool job without approval. | Authority to execute a playbook without requesting approval. |
View the Approvals log for a Playbook:
-
Click the [Playbook] main tab.
-
Doubleclick the Playbook you want to review.
-
Click the [Job Approvals Log]
button to the right of the Nodes panel.
Viewing the Output of a Playbook Run
If you’ve just run a Playbook, you’ll be brought to the Output screen automatically.
To view the output of a previously run Playbook:
-
Click the [Playbook] main tab.
-
Click the Playbook you want to see a previous output for.
-
Browse the History panel on the right side of the screen.
-
If the execution you’re interested in is not present, search terms may be added to help find it.

Previous executions may also be searched in the [Job History] section of the [Jobs] main tab.
The Playbook Output screen
The Output screen is divided into two main sections. The upper section provides a display of the Playbook exactly as it was when it was executed. Nodes that have created outputs while executing will have their output handles highlighted in green. You can click on a Node, or a Node’s output handle in order to navigate the bottom panel to that Node’s output.

The bottom panel provides tabular data for each of a Node’s output. At its top is a selector to choose which Node’s output you wish to see. If the selected Node has one or more outputs, a series of tabs will be displayed which can be used to view individual outputs in a table. When selecting a Node in this panel, the top panel will fly to the newly selected node to help locate it in the Playbook.

Inside of this tabular data, individual rows may be selected, if the row has more information associated to it, a panel will open with that data. For example, the output of a Run Code node will have the output of the commands executed on the device hidden until a row is selected.
Sometimes you may want to see all interactions the Playbook performed against a specific device. In this case click the table icon in the top left of the bottom panel.

From here there’s a search bar in the top left to find the device you’re interested in, and the panel will display a timeline of every output of every node related to that device. Since this might get farily long, clicking on any node’s name left of the line will filter down the display to node outputs that caused or were caused by that specific output. Clicking it again will remove that filter. Clicking the [device] button in the top right will return you to the tabular output display.

Using Replacement Values
Many nodes will emit metadata alongside their main result. For a Run Code node this may be device or status. These will all be visible in the table for the Node’s output after starting the Playbook.
If a field supports substitution, you may reference a value by surrounding its name with {curly braces}
A number of nodes support templated substitution for these values:
- Regex Match: The
Regular ExpressionandCompare Againstinputs both support substitution. - Run Code:
Commandssupport substitution. - Run Code With Automatic Retry:
Commandssupport substitution. - SSH Exec:
Commandsupports substitution. - Set Variables:
Variable Valuessupport substitution. - Update Fields:
Field Valuessupport substitution. - Upload File:
Commands to pull file from serversupport substitution. - Raise Compliance Violation:
Messagesupports substitution.
If you want to extract a piece of information into it’s own piece of metadata to be output as a column from a node, the easiest way to do so it to use the Regex Match Node. It supports Java style regular expressions and named match groups will be pulled into a value with that name.
e.g. to pull a Cisco device’s uptime into a value named uptime you can pass the output of show version to a Regex Match node with the Regular Expression:
lab-router uptime is (?<uptime>[\w ,]+)
And Compare Against set to its default of {result}, then this Regular Expression is not designed to match the entire Compare Against value, so let’s enable Partial Match to indicate that we want it to count as a match if the Expression is at least present.
Once this is configured, the output of the Regex Match will include any matched uptimes in a new uptime column, which can be used in subsequent nodes as {uptime}
We can also chain these to capture more specific information by changing Compare Against, for example, if you want to check for switches reset recently, you could check for an uptime that does not match the regex day:
Connect the uptime Regex Match Node to a new Regex Match Node and set the Regular Expression to :
day
Set Compare Against to {uptime}, and again make sure Partial Match is enabled.
Then we can inspect the output of nonMatches or connect handle of this new node to an Email, Webhook, Raise Compliance Violation, or Set Variables node with a message like ‘Device reset recently: {uptime}’ to recieve the results in another way.
Keyboard Shortcuts
In the following shortcuts, Mod will refer to Control on Windows, or Command on Mac
| Shortcut | Command |
|---|---|
| Shift + A | Open Add Node Context Menu |
| Mod + D | Duplicate Selected Node(s) |
| Shift + F | Fit the View to Contents of the Playbook |
| Mod + S | Save the Playbook |
| Mod + Enter | Validate the Playbook |
Node creation shortcuts are performed by holding a key and left clicking on the Playbook field where you want the new node.
| Key | Node |
|---|---|
| M | Memo |
| D | Device Search |
| C | Run Code |
| U | Upload File |
| E | |
| S | Sleep |
| R | Regex Match |
| V | Ruleset |
| L | Load Config |
| W | Chat Webhook |
| P | Execute Script (Python) |
| F | Execute Existing Script (file) |
Import Playbook
To import a Playbook:
-
Click the [Playbook] main tab.
-
Click the
button
in the menu bar at the top of the window. -
Doubleclick the Playbook .json file you want to import.
-
The Playbook file will appear in the [Playbook] interface.
Export Playbook
To export a Playbook:
-
Click the [Playbook] main tab.
-
Doubleclick the [Playbook] you want to export.
-
Click the click the [Export]
button in the menu bar at the top of the window. -
Download the Playbook as a .json file.
-
Click the [Close Playbook]
button in the menu bar at the top of the window.
Playbook Categories
The Playbook Category Feature introduces organizational improvements for Playbook management.
With Playbook Categories you can:
- Create and edit custom categories
- label using colored tags in Playbook lists
- Create multiple categories within one playbook
Create Playbook Category
To create a Playbook Category:
-
Click the [Playbook] main tab.
-
Click the
button next to the “Playbook” main tab title to open the [Categories] window.


- Click the
button to open the [Add Category] window.

- Click the
button to select a .svg image for the Category.

-
Enter a name for the Category.
-
Click [OK] > [Close].
Edit Playbook Category
-
Click the
button next to the “Playbook” main tab title to open the [Categories] window. -
Click the category name in the [Categories] window.
-
Click the
button to open the [Edit Category] window.

- Click [OK] after editing.
Delete Playbook Category
-
Click the
button next to the “Playbook” main tab title to open the [Categories] window. -
Click the category name in the [Categories] window.
-
Click the
button to open the [Remove Category] window.

- Click [Yes].
Compliance Remediations
Playbooks may be executed automatically in response to Compliance Rule Violations.
-
Click the [Compliance] > [Rule Sets] tabs.
-
Doubleclick the Rule Set you wish to add a Remediation Playbook to in order to open it in the Editor at the bottom of the page.
-
Click the “Remediation job or playbook”
button in the lower right of the page.

Example:

Incident Actions
Playbooks may be executed automatically as a part of an Alert Policy.
-
Click the [Monitors] > [Alert Policies] tabs.
-
Add a “Alert Policy Name”, or select an existing Alert Policy.
-
Click [New Action].
You have the option to click [Send to Playbook].

Once added, select “Playbook to Run”, “Frequency” and “Perform the action when…”.

Example:

Incident example:

Script Executor Container
Some workflows may be easier to implement using a more traditional programming language. So to enable these workflows, we provide a Docker image at:
harbor.logicvein.com/lvi/lvi-script-sandbox:latest
This image comes with Python preinstalled, and exposes an API over SSH (Port: 2022) that allows for executing scripts in a more sandboxed environment. Once the image is pulled, it can be run with:
docker run -d \
--name lvi-script-sandbox \
--read-only \
--tmpfs /tmp:size=1G \
--cap-add=SYS_ADMIN \
--security-opt no-new-privileges \
- v ./scripts:/shared:ro \
- v ./packages:/packages \
lvi/lvi-script-sandbox:latest
The /shared volume is intended to allow for accessing files from the host, for example if you have a library of scripts you wish to use.
The /packages volume will be used to store pip installed packages.
Environment Variables
The following environment variables may be defined to override defaults:
- WORKSPACE_TIMEOUT: The maximum lifetime for created workspaces. Once this timeout is reached, the workspace’s directory will be deleted. The value must be of the form
<number><unit>where unit can besfor seconds,mfor minutes, orhfor hours. Default:60m.- One workspace will be created per Playbook run, the whole run will share one namespace regardless of how many script nodes are present.
- SCRIPT_TIMEOUT: The maximum execution time for each script. If a script exceeds this timeout, it will be terminated. The value must be of the form
<number><unit>where unit can besfor seconds,mfor minutes,hfor hours. Default:120s.
Test it out
You can connect to it from a terminal with the command:
ssh -p 2022 root@localhost shell
The default password will be sandbox. You should be able to log in and run some commands within the sandboxed environment.
Configuration
To set up a custom password to use as an API Key to connect from ThirdEye, run the following command:
ssh -p 2022 root@localhost passwd
And provide a new password when prompted.
If you need to have your scripts perform API calls against the ThirdEye server, you may set an API Key, by running the container with the following options:
docker run -d \
--name lvi-script-sandbox \
--tmpfs /tmp:size=1G \
--cap-add=SYS_ADMIN \
--security-opt no-new-privileges \
lvi/lvi-script-sandbox:latest
And then run:
ssh -p 2022 root@localhost setkey <new_key>
Packages
If you have mounted the /packages directory to a volume, the pip command will support the following: install uninstall and list. These packages will be available for all sessions and script executions.
ssh -p 2022 root@localhost pip install human-regex
Enabling the Execute Script Nodes
The server settings has a [Script Executor] option where you may Enable the Executor, provide a Hostname, Port, and the Password set earlier. Once the Executor is enabled, you will be able to access the Execute Script and Execute Existing Script Playbook Nodes.
Scripting
Input
Each input to the Execute Script Nodes will individually invoke python. Invocations will be performed concurrently with no ordering or timing guarantee.
The input for each Python script invocation will be inside a file named in.json and will be structured as follows:
device- Device-specific dataglobals- Values from previous nodesmetadata- Execution metadata
device (object)
Represents a managed network device and its associated metadata.
Properties
| Field | Type | Description |
|---|---|---|
| ipAddress | string | The IPv4 or IPv6 address of the device |
| hostname | string | null | The hostname of the device |
| adapterId | string | null | The NetLD “Adapter ID” used to manage this device |
| deviceType | string | null | Device type (e.g. router, switch, firewall) |
| hardwareVendor | string | null | Hardware manufacturer |
| model | string | null | Device model |
| softwareVendor | string | null | Operating system vendor |
| osVersion | string | null | Vendor-specific OS version |
| osType | string | null | OS type (e.g. IOS, NEXUS) |
| backupStatus | string | null | Backup status (see enum below) |
| complianceState | integer | Compliance state (see enum below) |
| severity | integer | Severity level (see enum below) |
| violationMessage | string | null | Message for highest severity violation |
| lastBackup | integer | null | Most recent backup timestamp |
| lastChange | integer | null | Last backup detecting a change |
| lastTelemetry | integer | null | Last telemetry collection |
| lastDiscover | integer | null | Last discovery run |
| backupElapsed | integer | Last backup duration (seconds, or 0 if failed) |
| uptimeSecs | integer | Device uptime in seconds |
| memoSummary | string | null | First 60 characters of device memo |
| endOfSale | integer | null | Hardware end-of-sale date |
| endOfLife | integer | null | Hardware end-of-life date |
| softwareEndOfSale | string | null | Software end-of-sale date |
| softwareEndOfLife | string | null | Software end-of-life date |
| uuid | string (UUID) | Unique identifier for the device |
| serialNumber | string | null | Device chassis serial number |
| network | string | Associated network |
| traits | string[] | Supported capabilities (e.g. ncm, snmp, icmp) |
| sysLocation | string | |
| sysDescr | string | |
| sysObjectID | string | |
| custom1–custom5 | string | Custom fields |
| customFields | string[] | Custom fields |
| ncmEnabled | boolean |
backupStatus enum
- SUCCESS
- FAILURE
- INVALID_CREDENTIAL
complianceState enum
- 0 = compliant
- 1 = unsaved changes
- 2 = policy violations
severity enum
- 1 = DEBUG
- 2 = INFORMATIONAL
- 3 = NOTICE
- 4 = WARNING
- 5 = ERROR
- 6 = CRITICAL
- 7 = ALERT
- 8 = EMERGENCY
globals (object)
Output values from the input connection.
- All columns are included
- Structure is dynamic
- Values will be pairs of type = string or list, value = value. If the type is list, the value will contain an array of strings.
metadata (object)
Execution metadata for the playbook.
Properties
| Field | Type | Description |
|---|---|---|
| author | string | Last user to save the playbook |
| execution_id | integer | Unique execution ID |
| execution_url | string (URI) | Link to execution |
| executor | string | User who triggered execution |
| final | boolean | Indicates final execution phase |
| job_id | integer | Playbook ID |
| node | string | Node alias |
| origin | string | Core server IP/hostname |
| playbook | string | Playbook name |
| started_at | integer | Execution start timestamp |
Example:
In practice, this will look like the following, fields have been omitted from device for brevity:
{
"device": {
"ipAddress": "10.0.0.1",
"hostname": "",
"adapterId": "Cisco::IOS",
"deviceType": "Switch",
"network": "Default",
"serialNumber": "FOC1721W1SR"
},
"globals": {
"status": { "type": "string", "value": "OK"},
"err_message": { "type": "string", "value": ""},
"result": {"type": "string", "value": "show version\nCisco IOS Software, C1900 Software (C1900-UNIVERSALK9-M), Version 15.4(3)M5, RELEASE SOFTWARE (fc1)\nTechnical Support: http://www.cisco.com/techsupport\nCopyright (c) 1986-2016 by Cisco Systems, Inc.\nCompiled Tue 09-Feb-16 02:36 by prod_rel_team\n..."}
},
"metadata": {
"author": "admin",
"execution_id": 8622,
"execution_url": "https://10.0.0.1/#action=playbook&executionId=736&scriptId=854618fa-7d14-48a1-b06d-d4c8874333b4&versionId=411",
"executor": "admin",
"job_id": 133,
"node": "Nurturing_Nexus",
"origin": "10.0.0.1",
"playbook": "Script Runner",
"started_at": 1774858794829
}
}
Output
If you have a simple string output you wish to use in downstream nodes, you can just print it out to standard out as is. The output will use that value as its result.
If you wish to introduce variables, or emit multiple outputs for a single input, you can print JSON to standard out, following the Schema:
Properties
| Field | Type | Description |
|---|---|---|
| status | string | Execution result status (success, failure) |
| output | object | Single output payload for the output handle |
| outputs | array | Multiple outputs for the eachOutput handle |
| error | object | null | Error details if execution failed |
output (object)
Single output container sent to the output handle.
Properties
| Field | Type | Description |
|---|---|---|
| raw | string | Base64 encoded value to use as the primary result value of this node |
| globals | object | Key-value pairs of global output variables, all values must be strings |
globals
| Type | Description |
|---|---|
| object | All properties are string values |
outputs (array)
Array of output objects sent to the eachOutput handle, where each item shares the same shape as output.
error
Represents execution error details:
| Field | Type | Description |
|---|---|---|
| code | string | Error code identifier |
| message | string | Human-readable error message |
Examples:
A minimal example script that outputs one value:
import base64
import json
data = {
"output": {
"raw": base64.b64encode(b"Hello").decode("utf-8"),
"globals": {
"foo": "bar"
}
}
}
print(json.dumps(data))
Multiple outputs:
import time
import base64
import json
data = {
"outputs": [
{
"raw": base64.b64encode(b"Hello").decode("utf-8"),
"globals": {
"foo": "bar"
}
},
{
"raw": base64.b64encode(b"Hello").decode("utf-8"),
"globals": {
"foo": "bar"
}
},
]
}
print(json.dumps(data))
And example of a failure, the error key takes priority over outputs, so if error is present, the node will be treated as having failed regardless of any output key presence:
import json
data = {
"error": {
"message": "this was bad",
"code": "15",
},
}
print(json.dumps(data))



