> For the complete documentation index, see [llms.txt](https://docs.cortex.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cortex.io/streamline/workflows/blocks/states.md).

# Referencing a Workflow state in a block

Every Workflow run produces a state object that grows as the Workflow executes. Blocks can read from this state at any point, giving them access to both top-level context (such as who initiated the run) and the output of any preceding block. This is what makes blocks composable: each one can build on what came before.

The Workflow state object includes top-level `context`, `actions`, and `variables` keys:

* `context` is immutable, set at the beginning, and available to all blocks.
  * If an entity changes during Workflow execution, those changes will **not** be represented in `context.entity`.
  * If secrets change during a Workflow, those changes will **not** be represented in `context.secrets`.
  * You can examine the context object via the **Run context** tab when viewing a Workflow run.
  * [Learn more](#the-workflow-state-context-key) about the `context` key.
* `actions` is built up as actions execute via blocks.
  * Each block will have an `inputs` and `outputs` key, but their format differs based on the block type.
* `variables` contains the current values of any variables declared on the workflow. If a variable does not have a default value and hasn't been set yet, its value will be `null`.
  * **Note**: since variables are mutable, the variable values can change over time. Depending on the ordering of blocks in your workflow, different blocks may have access to different variable values.

The state object looks similar to the following:

```json
{
  "context": {
    "initiatedBy": {
      "name": "Henry Hippocampus",
      "email": "henry.hippocampus@cortex.io",
      "identityMappings": {
        "github": "hhippocampus"
      },
      "identityMappingsByAlias": {
        "github": {
          "cortex": "hhippocampus",
          "other-config": "hippo"
        }
      }
    },
    "workflowRunId":"a607c73f-b8e2-44b7-aa20-e23de7cf7af7",
    "initiatedAtIso8601Timestamp": "2025-05-16T21:42:37.642+00:00", // ISO8601 timestamp
    "secrets": {
      "secret-tag": "********"
    },
    "entity": { // only present for entity-scoped workflows
      "id": "en0123456789abcdef",
      "tag": "test-entity",
      "name": "Test Entity",
      "descriptor": { 
        "info": { ... }
      }
    }
  },
  "actions": {
    "action-slug-1": {
      "inputs": {},
      "outputs": {}
    }, 
    "action-slug-2": {
      "inputs": {},
      "outputs": {}
    }
    ...
  },
  "variables": {
    "variable1": true,
    "variable2": null,
    "variable3": { 
      "isObject": true
    }
  }
}
```

## The Workflow state `context` key

The context object always has the following keys:

* `{{context.workflowRunId}}` - The Workflow run ID
* `{{context.initiatedAtIso8601Timestamp}}` - The timestamp at which this block was initiated
* `{{context.initiatedBy}}` - The user object of the initiator
  * `email` - The user's email
  * `name` - The initiator's name
  * `identityMappings` - A mapping of the identity providers listed below to the initiating user's corresponding external ID. The external ID is pulled from identity provider's default configuration when there is more than one configuration.
    * `azure_devops`
    * `bitbucket`
    * `clickup`
    * `github`
    * `gitlab`
    * `jira`
    * `microsoft_teams`
    * `opsgenie`
    * `pagerduty`
    * `service_now`
    * `slack`
  * `identityMappingsByAlias` - Similar to `identityMappings`, but each provider maps to an object of configuration `alias` to external ID. This field is useful when users have different external IDs across an integration's configurations.
* `{{context.secrets}}` - An object of Cortex secret tags to their values

### **Accessing configured secrets**

You can access your configured secrets by tag: `{{context.secrets.SECRET_TAG}}`.

Note that Mustache syntax performs HTML escaping by default, so if your configured secret contains a reserved HTML character, use triple braces to use raw content: `{{{context.secrets.SECRET_TAG}}}`.

Secret values are redacted in inputs and outputs of the workflow state.

{% hint style="info" %}
Accessing a secret in the `context` object is not supported for Slack blocks.
{% endhint %}

### **Accessing entity data**

When the block runs in the context of a catalog entity, the template context includes data about that entity under the `{{context.entity}}` key:

* `id`
* `tag`
* `name`
* `descriptor` (this is the `cortex.yaml`, as an object)

These can be accessed under the `{{context.entity}}` key, for example `{{context.entity.tag}}` or `{{context.entity.descriptor.info.x-cortex-git.github.repository}}` .

## Referencing a block or workflow state

You can reference a previous block or a workflow state in several ways:

* Templated into block schemas via [Mustache](https://github.com/spullara/mustache.java) (`{{}}`)
* Accessed directly from JQ actions
* Referenced to define **User input** block overrides
* Referenced in **Branch** block path expressions using CEL syntax
* Accessed via JavaScript
  * For example, in a [JavaScript block](/streamline/workflows/blocks.md#javascript) you can reference Workflow variables using the syntax `const selected = variables['variable-slug']`.

### **Block and workflow state reference example**

Assume a Workflow was created where you gather names from an "HTTP request" block, a "data transformation" block parses the array of names, the names are surfaced to users in a "user input" block where they can select a name, then a "branch" block runs a different path based on which name was selected during the previous "user input" block. In one of the branch paths, there is a "Slack" block that sends a templated message based on the output of previous blocks.

The workflow contains the following blocks:

* HTTP request block called `users`
  * In this example, the block sends a `GET` request to gather user names from a URL containing sample data.
* Data transformation block called `names`
  * It contains a JQ query referencing the output of the `users` block:\
    `[.actions.users.outputs.body[] | .name]`
* User input block called `pick-name`
  * It contains an override that references the output of the `names` block:\
    `actions.names.outputs.result`
* Branch block called `create-services`
  * There are multiple paths in this branch, depending on which name you chose in the previous block. One of the name options is `Ervin`, and there is a conditional path called `Ervin` within this block that contains the following path expression. It references `Ervin` as the output of the `pick-names` block:\
    `actions['pick-name'].outputs.name == 'Ervin' && context.entity.descriptor.info['x-cortex-type'] == 'team'`.
  * The `Ervin` path contains a Slack block to send a templated message via Slack, referencing the output of the `pick-name` block and referencing the workflow state by including the email address of the user who initiated the workflow:\
    `We created a service for {{actions.pick-name.outputs.name}}. [message from workflow triggered by {{context.initiatedBy.email}}]`

When you run the workflow, the following chain of events occurs:

1. The HTTP request block gathers user names.
   * In the "Inputs" tab of this block, you can see where the data was pulled from.
   * In the "Outputs" tab of this block, you can see the list of names under the body.
2. The data transformation block parses an array of names from the HTTP request block.
   * In the "Outputs" tab of this block, you can see the list of names.
3. The Workflow is paused while awaiting user input. The user input block surfaces a `name` field where the user can select a name from the list. The names are from the array parsed in the previous block.
4. The user selects the name `Ervin`, and the Workflow continues to the next block.
5. The branch block runs a path depending on which name you chose in the previous block. In this example, the `Ervin` path runs because the CEL expression for that conditional path was configured to run when the `pick-name` block's output is `Ervin`.
   * In the "Outputs" tab of this block, you can see the conditions that were checked to verify which path to run.
6. The `Ervin` path contains a Slack block that sends a templated message referencing the output the previous block and the user who initiated the Workflow. The message is sent to the user with the templated references translated:\
   `We created a service for Ervin. [message from workflow triggered by jdoe@example.com]`


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.cortex.io/streamline/workflows/blocks/states.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
