---
title: Variables and conditions in input configurations
description: When running Elastic Agent in some environments, you might not know all the input configuration details up front. To solve this problem, the input configuration...
url: https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/4236/reference/fleet/dynamic-input-configuration
products:
  - Elastic Agent
  - Fleet
---

# Variables and conditions in input configurations
When running Elastic Agent in some environments, you might not know all the input configuration details up front. To solve this problem, the input configuration accepts variables and conditions that get evaluated at runtime using information from the running environment. Similar to autodiscovery, these capabilities allow you to apply configurations dynamically.
Let’s consider a unique agent policy that is deployed on two machines: a Linux machine named "linux-app" and a Windows machine named "winapp". Notice that the configuration has some variable references: `${host.name}` and `${host.platform}`:
```yaml
inputs:
 - id: unique-logfile-id
   type: logfile
   streams:
    - paths: /var/log/${host.name}/another.log
      condition: ${host.platform} == "linux"
    - path: c:/service/app.log
      condition: ${host.platform} == "windows"
```

At runtime, Elastic Agent resolves variables and evaluates the conditions based on values provided by the environment, generating two possible input configurations.
On the Windows machine:
```yaml
inputs:
 - id: unique-logfile-id
   type: logfile
   streams:
    - path: c:/service/app.log
```

On the Linux machine:
```yaml
inputs:
 - id: unique-logfile-id
   type: logfile
   streams:
    - paths: /var/log/linux-app/another.log
```

Using variable substitution along with conditions allows you to create concise, but flexible input configurations that adapt to their deployed environment.

## Variable substitution

The syntax for variable substitution is `${var}`, where `var` is the name of a variable defined by a provider. A *provider* defines key/value pairs that are used for variable substitution and conditions.
Elastic Agent supports a variety of providers, such as `host` and `local`, that supply variables to Elastic Agent. For example, earlier you saw `${host.name}` used to resolve the path to the host’s log file based on the `{host.platform}` value. Both of these values were provided by the `host` provider.
All providers are enabled by default when Elastic Agent starts. If a provider cannot be configured, its variables are ignored.
Refer to [Providers](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/4236/reference/fleet/providers) for more detail.
The following agent policy uses a custom key named `foo` to resolve a value defined by a local provider:
```yaml
inputs:
 - id: unique-logfile-id
   type: logfile
   streams:
    - paths: /var/log/${foo}/another.log

providers:
  local:
    vars:
      foo: bar
```

The policy generated by this configuration looks like this:
```yaml
inputs:
 - id: unique-logfile-id
   type: logfile
   streams:
    - paths: /var/log/bar/another.log
```

When an input uses a variable substitution that is not present in the current key/value mappings being evaluated, the input is removed in the result.
For example, this agent policy uses an unknown key:
```yaml
inputs:
  - id: logfile-foo
    type: logfile
    path: "/var/log/foo"
  - id: logfile-unknown
    type: logfile
    path: "${ unknown.key }"
```

The policy generated by this configuration looks like this:
```yaml
inputs:
  - id: logfile-foo
    type: logfile
    path: "/var/log/foo"
```


## Alternative variables and constants

Variable substitution can also define alternative variables or a constant.
To define a constant, use either `'` or `"`. When a constant is reached during variable evaluation, any remaining variables are ignored, so a constant should be the last entry in the substitution.
To define  alternatives, use `|` followed by the next variable or constant. The power comes from allowing the input to define the preference order of the substitution by chaining multiple variables together.
For example, the following agent policy chains together multiple variables to set the log path based on information provided by the running container environment. The constant `/var/log/other` is used to end of the path, which is common to both providers:
```yaml
inputs:
  - id: logfile-foo
    type: logfile
    path: "/var/log/foo"
  - id: logfile-container
    type: logfile
    path: "${docker.paths.log|kubernetes.container.paths.log|'/var/log/other'}"
```


## Escaping variables

In some cases the `${var}` syntax causes an issue with using a value where the actually wanted variable is `${var}`. In this case double `$$` can be provided for the variable.
The double `$$` causes the variable to be ignored and the extra `$` is removed from the beginning.
For example, the following agent policy uses the escaped variable so the actual value is used instead.
```yaml
inputs:
  - id: logfile-foo
    type: logfile
    path: "/var/log/foo"
    processors:
      - add_tags:
          tags: [$${development}]
          target: "environment"
```

The policy generated by this configuration looks like this:
```yaml
inputs:
  - id: logfile-foo
    type: logfile
    path: "/var/log/foo"
    processors:
      - add_tags:
          tags: [${development}]
          target: "environment"
```


## Conditions

A condition is a boolean expression that you can specify in your agent policy to control whether a configuration is applied to the running Elastic Agent. You can set a condition on inputs, streams, or even processors.
In this example, the input is applied if the host platform is Linux:
```yaml
inputs:
  - id: unique-logfile-id
    type: logfile
    streams:
      - paths:
         - /var/log/syslog
    condition: ${host.platform} == 'linux'
```

In this example, the stream is applied if the host platform is not Windows:
```yaml
inputs:
  - id: unique-system-metrics-id
    type: system/metrics
    streams:
      - metricsets:
          - load
        data_stream.dataset: system.cpu
        condition: ${host.platform} != 'windows'
```

In this example, the processor is applied if the host platform is not Windows:
```yaml
inputs:
  - id: unique-system-metrics-id
    type: system/metrics
    streams:
      - metricsets:
          - load
        data_stream.dataset: system.cpu
    processors:
      - add_fields:
          fields:
            platform: ${host.platform}
          target: host
        condition: ${host.platform} != 'windows'
```


### Condition syntax

The conditions supported by Elastic Agent are based on [EQL](https://docs-v3-preview.elastic.dev/elastic/elasticsearch/tree/main/reference/query-languages/eql/eql-syntax)'s boolean syntax, but add support for variables from providers and functions to manipulate the values.
**Supported operators:**
- Full PEMDAS math support for `+ - * / %`.
- Relational operators `< <= >= > == !=`
- Logical operators `and` and `or`

**Functions:**
- Array functions [`arrayContains`](#arrayContains-function)
- Dict functions [`hasKey`](#hasKey-function) (not in EQL)
- Length functions [`length`](#length-function)
- Math functions [`add`](#add-function), [`subtract`](#subtract-function), [`multiply`](#multiply-function), [`divide`](#divide-function), [`modulo`](#modulo-function)
- String functions [`concat`](#concat-function), [`endsWith`](#endsWith-function), [`indexOf`](#indexOf-function), [`match`](#match-function), [`number`](#number-function), [`startsWith`](#startsWith-function), [`string`](#string-function), [`stringContains`](#stringContains-function)

**Types:**
- Booleans `true` and `false`


### Condition examples

Run only when a specific label is included.
```eql
arrayContains(${docker.labels}, 'monitor')
```

Skip on Linux platform or macOS.
```eql
${host.platform} != "linux" and ${host.platform} != "darwin"
```

Run only for specific labels.
```eql
arrayContains(${docker.labels}, 'monitor') or arrayContains(${docker.label}, 'production')
```


### Function reference

The condition syntax supports the following functions.

#### `add`

`add(Number, Number) Number`
Usage:
```eql
add(1, 2) == 3
add(5, ${foo}) >= 5
```


#### `arrayContains`

`arrayContains(Array, String) Boolean`
Usage:
```eql
arrayContains(${docker.labels}, 'monitor')
```


#### `concat`

`concat(String, String) String`
<note>
  Parameters are coerced into strings before the concatenation.
</note>

Usage:
```eql
concat("foo", "bar") == "foobar"
concat(${var1}, ${var2}) != "foobar"
```


#### `divide`

`divide(Number, Number) Number`
Usage:
```eql
divide(25, 5) > 0
divide(${var1}, ${var2}) > 7
```


#### `endsWith`

`endsWith(String, String) Boolean`
Usage:
```eql
endsWith("hello world", "hello") == true
endsWith(${var1}, "hello") != true
```


#### `hasKey`

`hasKey(Dictionary, String) Boolean`
Usage:
```eql
hasKey(${host}, "platform")
```


#### `indexOf`

`indexOf(String, String, Number?) Number`
<note>
  Returns -1 if the string is not found.
</note>

Usage:
```eql
indexOf("hello", "llo") == 2
indexOf(${var1}, "hello") >= 0
```


#### `length`

`length(Array|Dictionary|string)`
Usage:
```eql
length("foobar") > 2
length(${docker.labels}) > 0
length(${host}) > 2
```


#### `match`

`match(String, Regexp) boolean`
<note>
  `Regexp` supports Go’s regular expression syntax. Conditions that use regular expressions are more expensive to run. If speed is critical, consider using `endWiths` or `startsWith`.
</note>

Usage:
```eql
match("hello world", "^hello") == true
match(${var1}, "world$") == true
```


#### `modulo`

`modulo(number, number) Number`
Usage:
```eql
modulo(25, 5) > 0
modulo(${var1}, ${var2}) == 0
```


#### `multiply`

`multiply(Number, Number) Number`
Usage:
```eql
multiply(5, 5) == 25
multiple(${var1}, ${var2}) > x
```


#### `number`

`number(String) Integer`
Usage:
```eql
number("42") == 42
number(${var1}) == 42
```


#### `startsWith`

`startsWith(String, String) Boolean`
Usage:
```eql
startsWith("hello world", "hello") == true
startsWith(${var1}, "hello") != true
```


#### `string`

`string(Number) String`
Usage:
```eql
string(42) == "42"
string(${var1}) == "42"
```


#### `stringContains`

`stringContains(String, String) Boolean`
Usage:
```eql
stringContains("hello world", "hello") == true
stringContains(${var1}, "hello") != true
```


#### `subtract`

`subtract(Number, Number) Number`
Usage:
```eql
subtract(5, 1) == 4
subtract(${foo}, 2) != 2
```


### Debugging

To debug configurations that include variable substitution and conditions, use the `inspect` command. This command shows the configuration that’s generated after variables are replaced and conditions are applied.
First run the Elastic Agent. For this example, we’ll use the following agent policy:
```yaml
outputs:
  default:
    type: elasticsearch
    hosts: [127.0.0.1:9200]
    apikey: <my-api-key>

providers:
  local_dynamic:
    items:
      - vars:
          key: value1
        processors:
          - add_fields:
              fields:
                custom: match1
              target: dynamic
      - vars:
          key: value2
        processors:
          - add_fields:
              fields:
                custom: match2
              target: dynamic
      - vars:
          key: value3
        processors:
          - add_fields:
              fields:
                custom: match3
              target: dynamic

inputs:
  - id: unique-logfile-id
    type: logfile
    enabled: true
    streams:
      - paths:
          - /var/log/${local_dynamic.key}
```

Then run `elastic-agent inspect --variables` to see the generated configuration. For example:
```shell
$ ./elastic-agent inspect --variables
inputs:
- enabled: true
  id: unique-logfile-id-local_dynamic-0
  original_id: unique-logfile-id
  processors:
  - add_fields:
      fields:
        custom: match1
      target: dynamic
  streams:
  - paths:
    - /var/log/value1
  type: logfile
- enabled: true
  id: unique-logfile-id-local_dynamic-1
  original_id: unique-logfile-id
  processors:
  - add_fields:
      fields:
        custom: match2
      target: dynamic
  streams:
  - paths:
    - /var/log/value2
  type: logfile
- enabled: true
  id: unique-logfile-id-local_dynamic-2
  original_id: unique-logfile-id
  processors:
  - add_fields:
      fields:
        custom: match3
      target: dynamic
  streams:
  - paths:
    - /var/log/value3
  type: logfile
outputs:
  default:
    apikey: <my-api-key>
    hosts:
    - 127.0.0.1:9200
    type: elasticsearch
providers:
  local_dynamic:
    items:
    - processors:
      - add_fields:
          fields:
            custom: match1
          target: dynamic
      vars:
        key: value1
    - processors:
      - add_fields:
          fields:
            custom: match2
          target: dynamic
      vars:
        key: value2
    - processors:
      - add_fields:
          fields:
            custom: match3
          target: dynamic
      vars:
        key: value3

---
```