Template reference
A template is a YAML file with three sections: tasks, agents (or top-level modules), and transfer. Parsing is strict: an unknown field name is an error, so typos fail fast.
Minimal complete example
tasks:
- name: disk
type: local
local: { command: "df --output=pcent / | tail -1 | tr -d ' %'" }
variable: disk_pct
agents:
- name: "myhost"
group: "Servers"
interval: 300
modules:
- name: "Disk used"
type: generic_data
data: "{{ disk_pct }}"
unit: "%"
transfer:
mode: tentacle
tentacle: { address: "pandora.example.com" }
tasks: — ordered list of executions
Tasks run sequentially, in declared order. A task may use variables produced by earlier tasks in any of its string fields (chaining: login → token → authenticated request).
| Field | Required | Description |
|---|---|---|
name |
yes | Unique task identifier (used in logs) |
type |
yes | request or local |
request |
if type=request | HTTP request spec (below) |
local |
if type=local | Command spec (below) |
filter |
no | Extraction filter (below). Without it, the trimmed raw output is stored |
variable |
no | Name to store the result under. Must match [A-Za-z_][A-Za-z0-9_]* |
request: (HTTP)
| Field | Required | Default | Description |
|---|---|---|---|
url |
yes | — | Target URL. Supports {{ }} |
method |
no | GET |
GET, POST, PUT, DELETE, PATCH, HEAD |
headers |
no | — | Map of header → value. Values support {{ }} |
body |
no | — | Request body. Supports {{ }} |
timeout |
no | 30 |
Seconds |
skip_tls_verify |
no | false |
Accept invalid TLS certificates |
A response with status outside 2xx is a task failure. Response bodies are capped at 10 MiB.
local: (command)
| Field | Required | Default | Description |
|---|---|---|---|
command |
yes | — | Executed with /bin/sh -c. Supports {{ }}. Shell $ is untouched (awk '{print $5}' works as-is) |
timeout |
no | 30 |
Seconds; the process is killed on expiry |
A non-zero exit code is a task failure (stderr is included in the log).
filter: — extracting values
| Field | Required | Description |
|---|---|---|
type |
yes | jq or regexp |
expression |
yes | The filter expression |
Result cardinality (both filter types): 0 matches → variable unset (task failure semantics) · 1 match → scalar · N matches → array.
jq — the task output must be valid JSON. The expression runs with an embedded jq engine (no jq binary needed). Each value the expression emits is one element: .token → scalar, .items[].name → array, .items[] → array of objects.
regexp — Go RE2 syntax (no backtracking, no lookahead) applied to the raw output. Per match:
| Pattern shape | Each match becomes |
|---|---|
No capture group (cpu\d) |
The full match (string) |
One unnamed group ((\d+)%) |
Capture group 1 (string) |
2+ unnamed groups ((a)(b)(c)) |
Positional array: [[a, b, c], ...] |
Named groups ((?P<mount>...)) |
An object: group name → captured text |
Use (?m) for line-anchored multi-line patterns and (?i) for case-insensitive matching.
Do not mix named and unnamed groups in the same regexp if you want predictable access; the named form exposes only the named fields.
Type coercion: extracted strings that look numeric become numbers (recursively, including object fields), so arithmetic works on them.
Variables and {{ }} expressions
Any string field of tasks (after the producing task), agents, and modules may embed {{ expression }}. Expressions are evaluated with expr-lang against the variable store.
| Expression | Result |
|---|---|
{{ token }} |
Variable value |
{{ 100 - disk_pct }} |
Arithmetic |
{{ names[0] }} |
Array indexing |
{{ value.mount }} |
Object field (inside for_each) |
{{ names[index] }} |
Lockstep parallel array (inside for_each) |
Referencing an undefined variable is an error → the affected module is skipped (or the run aborts under --strict).
agents: — one block per agent
Required unless you use top-level modules: (see agent_plugin mode). Each agent becomes one <agent_data> XML document.
| Field | Required | Description |
|---|---|---|
name |
yes | Agent name |
modules |
yes | List of module blocks (at least one) |
alias |
no | Agent alias |
parent_agent_name |
no | Parent agent |
description |
no | Description |
version |
no | Agent version string |
os_name, os_version |
no | OS identification |
timestamp |
no | Override data timestamp |
address |
no | IP/hostname |
group |
no | Target group |
interval |
no | Seconds (integer) |
agent_mode |
no | Agent mode |
All string fields support {{ }}.
modules: — module blocks
Module blocks live inside an agent, or at the top level (only with transfer.mode: agent_plugin).
Control fields (executor semantics, not sent to Pandora):
| Field | Description |
|---|---|
for_each |
Array variable name. The block expands to one module per element; {{ value }} and {{ index }} become available. A scalar variable iterates as a 1-element array. For unnamed capture groups with 2+ groups, each value is an array so you can use {{ value[0] }}. Need several modules per element? Write several blocks with the same for_each |
when |
Raw boolean expr-lang expression (no {{ }}). False → module (or element) skipped. Inside for_each it is evaluated per element and sees value/index. Example: when: 'not (value.mount matches "^/DB")' |
Data fields — the two required plus the full set accepted by the dataserver. Values may be numbers or strings in YAML; all support {{ }}:
| Field | Required | Description |
|---|---|---|
name |
yes | Module name |
type |
yes | Module type (generic_data, generic_proc, generic_data_string, async_data, ...) |
data |
no | Module value |
description |
no | Description |
unit |
no | Unit label |
interval |
no | Module interval |
tags |
no | Tags |
module_group |
no | Module group |
module_parent, module_parent_unlink |
no | Parent module relation |
min_warning, max_warning, min_critical, max_critical |
no | Numeric thresholds |
min_warning_forced, max_warning_forced, min_critical_forced, max_critical_forced |
no | Forced threshold variants |
str_warning, str_critical |
no | String-match thresholds |
str_warning_forced, str_critical_forced |
no | Forced string thresholds |
warning_inverse, critical_inverse |
no | Invert threshold logic |
min, max |
no | Valid data range |
post_process |
no | Multiplier applied by the server |
disabled |
no | Create disabled |
status |
no | Force status |
timestamp |
no | Override data timestamp |
custom_id |
no | Custom identifier |
critical_instructions, warning_instructions, unknown_instructions |
no | Operator instructions |
quiet |
no | Quiet mode |
min_ff_event, min_ff_event_normal, min_ff_event_warning, min_ff_event_critical |
no | FlipFlop thresholds |
module_ff_interval, ff_type, ff_timeout, each_ff |
no | FlipFlop behavior |
crontab |
no | Cron-style module scheduling |
extra_data |
no | Extra payload |
alert_templates |
no | List of alert template names to bind |
transfer: — delivery
| Field | Required | Description |
|---|---|---|
mode |
yes | tentacle, local or agent_plugin |
tentacle.address |
for tentacle | Pandora server address |
tentacle.port |
no (default 41121) |
Tentacle port |
tentacle.binary |
no | Path to tentacle_client if not in $PATH |
tentacle.extra_args |
no | Extra tentacle client arguments (list) |
local.directory |
for local | Directory where the .data XML file is written |
module_prefix_separator |
no (default " - ") |
Separator for multi-agent prefixing in agent_plugin mode |
| Mode | Output | Use case |
|---|---|---|
tentacle |
Full <agent_data> XML sent via tentacle client |
Remote execution (cron, Discovery) |
local |
Full <agent_data> XML written to a directory |
Running on the Pandora server itself (point it at the incoming dir), or debugging |
agent_plugin |
Only <module> fragments printed to stdout — the real agent adds the header |
Running as module_plugin of a software agent |
agent_plugin specifics:
- Top-level
modules:without anyagents:block is allowed (and only allowed in this mode). - With multiple agents defined, each module name is prefixed
<agent_name> - <module_name>so modules cannot collide under the one real agent.