---
title: "Syntax | Grafana Agent documentation"
description: "Learn about the River syntax"
---

# Syntax

The River syntax is easy to read and write. It has only two high-level elements, *Attributes* and *Blocks*.

River is a *declarative* language used to build programmable pipelines. The order of blocks and attributes within the River configuration file isn’t important. The language considers all direct and indirect dependencies between elements to determine their relationships.

## Comments

River configuration files support single-line `//` and block `/* */` comments.

## Identifiers

River considers an identifier as valid if it consists of one or more UTF-8 letters (A through Z, both upper- and lower-case), digits or underscores, but doesn’t start with a digit.

## Attributes and Blocks

### Attributes

You use *Attributes* to configure individual settings. They always take the form of `ATTRIBUTE_NAME = ATTRIBUTE_VALUE`. They can appear either as top-level elements or nested within blocks.

The following example sets the `log_level` attribute to `"debug"`.

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
log_level = "debug"
```

The `ATTRIBUTE_NAME` must be a valid River [identifier](#identifiers).

The `ATTRIBUTE_VALUE` can be either a constant value of a valid River [type](/docs/agent/v0.43/flow/concepts/config-language/expressions/types_and_values/) (for example, a string, boolean, number), or an [*expression*](/docs/agent/v0.43/flow/concepts/config-language/expressions/) to represent or compute more complex attribute values.

### Blocks

You use *Blocks* to configure the Grafana Agent’s behavior as well as Grafana Agent Flow components by grouping any number of attributes or nested blocks using curly braces. Blocks have a *name*, an optional *label* and a body that contains any number of arguments and nested unlabeled blocks.

Some blocks can be defined more than once.

#### Examples

You can use the following pattern to create an unlabeled block.

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
BLOCK_NAME {
  // Block body can contain attributes and nested unlabeled blocks
  IDENTIFIER = EXPRESSION // Attribute

  NESTED_BLOCK_NAME {
    // Nested block body
  }
}
```

You can use the following pattern to create a labeled block

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
// Pattern for creating a labeled block:
BLOCK_NAME "BLOCK_LABEL" {
  // Block body can contain attributes and nested unlabeled blocks
  IDENTIFIER = EXPRESSION // Attribute

  NESTED_BLOCK_NAME {
    // Nested block body
  }
}
```

#### Block naming rules

The `BLOCK_NAME` has to be recognized by Grafana Agent Flow as either a valid component name or a special block for configuring global settings. If the `BLOCK_LABEL` must be set, it must be a valid River [identifier](#identifiers) wrapped in double quotes. In these cases, you use the label to disambiguate between multiple top-level blocks of the same name.

The following snippet defines a block named `local.file` with its label set to “token”. The block’s body sets `filename` to the content of the `TOKEN_FILE_PATH` environment variable by using an expression, and the `is_secret` attribute is set to the boolean `true`, marking the file content as sensitive.

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
local.file "token" {
  filename  = env("TOKEN_FILE_PATH") // Use an expression to read from an env var.
  is_secret = true
}
```

## Terminators

All block and attribute definitions are followed by a newline, which River calls a *terminator*, as it terminates the current statement.

A newline is treated as a terminator when it follows any expression, `]`, `)`, or `}`. River ignores other newlines and you can can enter as many newlines as you want.
