> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rootly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Task Output Variables

> Reference previous workflow action outputs using Liquid template variables to chain Rootly actions together, pass data between steps, and build pipelines.

Every workflow action stores its output after it completes. Subsequent actions in the same workflow can reference those outputs using Liquid template syntax. This lets you chain actions together — for example, fetch data with an HTTP request and pass the response into an AI prompt or a second API call.

## Syntax

Reference a previous action's output using the `tasks` object and the action's **slug**:

```text theme={null}
{{ tasks.<action-slug>.<property> }}
```

The action slug is a URL-friendly identifier derived from the action's name when the action is **first created**: the name is lowercased and spaces become hyphens, so an action named "Get service" becomes `get-service`.

<Warning>
  An action's slug is locked in when the action is created and does **not** change if you rename the action later. An action first created as "Get service from Rootly" keeps the slug `get-service-from-rootly` even after it's renamed to "Get service". Slugs always use hyphens, never underscores — `get-service`, not `get_service`.
</Warning>

## Finding an Action's Slug

### While Authoring (Before The Workflow Has Run)

When you're building the workflow for the first time and don't yet have a completed run to copy from, derive the slug from the action's **original** name (the name set when the action was first created): lowercase it and replace spaces with hyphens. An action created as "Get service from Rootly" has the slug `get-service-from-rootly` — even if you later rename it to "Get service". Use this derived slug as your initial reference, then confirm it from the run results below as soon as the workflow runs once.

### After A Successful Run (Authoritative)

The slug isn't shown in the workflow editor or returned by the API, so the most reliable way to confirm it is from a completed run:

1. Run the workflow once, or open a previous run.
2. Open the action in the run results.
3. Select the **Output** tab. Rootly displays the exact `tasks.<slug>...` reference to copy, so you never have to read it off the action name.

<Frame>
  <img src="https://mintcdn.com/rootly/lK6NcDuETQTy4QWg/images/workflows-overview/task-output-slug-reference.png?fit=max&auto=format&n=lK6NcDuETQTy4QWg&q=85&s=5655b2ba30fcfcd00327313cf6c744bc" alt="The Output tab of a completed workflow action, showing the exact tasks dot slug Liquid reference to copy" width="1106" height="256" data-path="images/workflows-overview/task-output-slug-reference.png" />
</Frame>

## Available Properties

Each completed action exposes the following properties:

| Property                    | Description                                                               |
| --------------------------- | ------------------------------------------------------------------------- |
| `tasks.<slug>.name`         | Action name                                                               |
| `tasks.<slug>.slug`         | Action slug identifier                                                    |
| `tasks.<slug>.status`       | Execution status (`queued`, `started`, `completed`, `failed`, `canceled`) |
| `tasks.<slug>.output`       | Action output (structure varies by action type — see below)               |
| `tasks.<slug>.logs`         | Event logs from the action                                                |
| `tasks.<slug>.started_at`   | When the action started                                                   |
| `tasks.<slug>.completed_at` | When the action completed                                                 |
| `tasks.<slug>.failed_at`    | When the action failed (if applicable)                                    |

***

## HTTP Request Action Output

The **Fetch an HTTP endpoint** action stores the full HTTP response. Access it through `output.response`:

| Path                                   | Description                                    |
| -------------------------------------- | ---------------------------------------------- |
| `tasks.<slug>.output.response.status`  | HTTP status code                               |
| `tasks.<slug>.output.response.body`    | Response body (parsed as JSON when applicable) |
| `tasks.<slug>.output.response.headers` | Response headers                               |

### Accessing nested JSON

When the HTTP response returns JSON, you can traverse the parsed structure directly:

```text theme={null}
{{ tasks.my-http-request.output.response.body.data.id }}
{{ tasks.my-http-request.output.response.body.items[0].name }}
```

***

## AI Chat Completion Action Output

The **OpenAI**, **Anthropic**, **Google Gemini**, and **Mistral** chat completion actions store the AI model's response in `output.response`. The exact structure depends on the provider and model.

### OpenAI

OpenAI uses two different API formats depending on the model:

**GPT models** (`gpt-4o`, `gpt-4o-mini`, etc.) use the Chat Completions API:

```text theme={null}
{{ tasks.my-openai-task.output.response.choices[0].message.content }}
```

**Reasoning models** (`o1-*`, `o3-*`) use the Responses API, which returns a different structure:

```text theme={null}
{{ tasks.my-openai-task.output.response.output[0].content[0].text }}
```

<Note>
  If you switch between GPT and reasoning models, you must update the output path in any downstream actions that reference the task output.
</Note>

### Google Gemini

```text theme={null}
{{ tasks.my-gemini-task.output.response.candidates[0].content.parts[0].text }}
```

***

## Other Action Outputs

Most built-in actions (Create Jira Issue, Create Linear Issue, Send Slack Message, etc.) store their response in `output.response`. The structure matches the response from the underlying integration API.

Examples:

```text theme={null}
{{ tasks.create-a-jira-issue.output.response.key }}
{{ tasks.create-a-linear-issue.output.response.data.issueCreate.issue.url }}
{{ tasks.create-a-linear-issue.output.response.data.issueCreate.issue.identifier }}
```

***

## Examples

### Chain two HTTP requests

Fetch a service catalog entry, then use part of the response in a follow-up API call.

**Action 1** — "get-service-info" (HTTP GET):

```text theme={null}
URL: https://api.example.com/v1/catalog/{{ incident.services.first }}
```

**Action 2** — "get-owner" (HTTP GET) referencing Action 1's output:

```text theme={null}
URL: https://api.example.com/v1/catalog/{{ tasks.get-service-info.output.response.body.hierarchy.parents[0].tag }}
```

### Use HTTP response in action URL parameters

Look up a user by email from a previous action's response:

```text theme={null}
https://api.rootly.com/v1/users?filter[email]={{ tasks.get-on-call-from-opsgenie.output.response.body.data.onCallRecipients[0] | default: 'fallback@example.com' }}
```

### Feed HTTP response into an OpenAI prompt

Fetch logs from an observability tool, then have AI analyze them.

**Action 1** — "get-logs" (HTTP GET to your logging API)

**Action 2** — "analyze-logs" (OpenAI Chat Completion) with prompt:

```text theme={null}
Analyze the following service logs for errors and anomalies.
Format your response for Slack using mrkdwn.

{{ tasks.get-logs.output.response.body.data.result }}
```

### Pass AI output into a subsequent HTTP request

Generate a postmortem with AI, then post it to the incident timeline.

**Action 1** — "generate-postmortem" (OpenAI Chat Completion)

**Action 2** — "post-to-timeline" (HTTP POST):

```text theme={null}
URL: https://api.rootly.com/v1/incidents/{{ incident.id }}/events
Body:
{
  "data": {
    "attributes": {
      "visibility": "internal",
      "event": {{ tasks.generate-postmortem.output.response.choices[0].message.content | to_json }}
    },
    "type": "incident_events"
  }
}
```

<Note>
  Use the `to_json` filter when inserting task output into a JSON body. AI-generated text often contains quotes and newlines that break JSON syntax without proper escaping.
</Note>

### Use Jira/Linear issue output to update an alert

Create a ticket, then write the ticket URL back to a custom alert field.

**Action 1** — "create-a-linear-issue" (Create Linear Issue)

**Action 2** — "update-alert-with-ticket" (HTTP PATCH):

```text theme={null}
URL: https://api.rootly.com/v1/alerts/{{ alert.id }}
Body:
{
  "data": {
    "attributes": {
      "alert_field_values_attributes": [
        {
          "alert_field_id": "<your-field-id>",
          "value": "{{ tasks.create-a-linear-issue.output.response.data.issueCreate.issue.url }}"
        }
      ]
    },
    "type": "alerts"
  }
}
```

### Assign a role based on an on-call lookup

Look up who is on-call, find them in Rootly, then assign them to an incident role.

**Action 1** — "get-on-call" (HTTP GET to your paging provider)

**Action 2** — "find-rootly-user" (HTTP GET):

```text theme={null}
https://api.rootly.com/v1/users?filter[email]={{ tasks.get-on-call.output.response.body.data.onCallRecipients[0] }}
```

**Action 3** — "assign-role" (HTTP POST):

```text theme={null}
URL: https://api.rootly.com/v1/incidents/{{ incident.id }}/assign_role_to_user
Body:
{
  "data": {
    "type": "incidents",
    "attributes": {
      "user_id": "{{ tasks.find-rootly-user.output.response.body.data[0].id }}",
      "incident_role_id": "<your-role-id>"
    }
  }
}
```

***

## Using Liquid Filters with Task Outputs

You can apply any [Liquid filter](/liquid/filters) to task output values. Common patterns:

```text theme={null}
{{ tasks.my-task.output.response.body.name | upcase }}

{{ tasks.my-task.output.response.body.email | default: 'fallback@example.com' }}

{{ tasks.my-task.output.response.body.query | replace: '+', '' }}

{{ tasks.my-task.output.response.body.items | size }}
```

***

## Troubleshooting

### Action output is empty

* Verify the referenced action ran successfully. Check the workflow run log for errors.
* Check that the action slug matches exactly — slugs are case-sensitive and use hyphens, not underscores (e.g., `my-http-request`, not `my_http_request`).

### JSON path returns nothing

* The HTTP response body is only parsed as JSON when the response `Content-Type` is `application/json`. If the API returns a different content type, `body` may be a raw string.
* Use the workflow run log to inspect the actual response structure and verify your path.

### Subsequent action does not see the previous output

* Actions run sequentially in order. An action can only reference outputs from actions that appear **above** it in the workflow editor.
* If the previous action has **Skip on Failure** enabled and failed, its output may be incomplete or missing.

### Variable is undefined after renaming an action

* A reference that broke after you renamed an action is using the new name. The slug is fixed at creation and doesn't change on rename, use the original slug, or copy the exact reference from the **Output** tab of a completed run (see [Finding an action's slug](#finding-an-actions-slug)).
