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

# Relationship mapping and automation

> Build one workflow that reaches the right team, channel, and on-call person for every incident, instead of one per team.

Catalog entries link to each other through their attributes: a service has an owning team, and that team has a Slack channel, a Slack user group, and an escalation path. Workflows, alert routes, and custom fields can follow those links, so a single configuration finds the right people for whichever service is affected, instead of needing one workflow per team.

## Model the relationships

Relationships come from attributes whose type is another catalog type. When you [add an attribute](/catalog/catalog-setup) to a catalog type, the **Reference** types include your own catalog types and the ones incident.io provides, such as:

* **Slack Channel** and **Microsoft Teams Channel**, for where a team talks
* **Slack User Group**, for who to invite
* **Escalation Path** and **Schedule**, for who to page
* **User**, for a specific person

A common model is a **Service** type with an **Owning team** attribute, and a **Team** type with **Slack channel**, **Slack user group**, and **Escalation path** attributes. See [What data should I bring into Catalog?](/catalog/what-data) for more examples, and [How do I get data into Catalog?](/catalog/importing-data) to populate them.

Then add a Catalog-backed [custom field](/incidents/custom-fields), like **Affected services**, so each incident records which entries it affects.

## Follow relationships in workflows

When a workflow step or condition asks for a value, the variable picker lets you step through an entry's attributes. For example, to invite the teams that own the affected services, pick **Incident → Affected services → Owning team → Slack user group** in the **Invite user or group to the incident's channel** step. Use the arrow keys, or click an item, to move in and out.

The picker only lists variables that fit the field, so a path can seem to be missing:

* **Anything reached through a multi-value field is a list.** An incident can have several affected services, so **Affected services → Owning team → Slack channel** is a list of channels. It appears in steps that take several values, but not in a step that takes one channel, like **Send message to a channel**. For those, choose what you want to happen: a [loop](/workflows/loops) runs the step **For each value of** the list, like posting in every affected team's channel, and a Query ending in **First** picks one value, like a single channel to post in.
* **The picker goes a few levels deep.** For a longer path, use a Query expression, which can follow as many links as you need.
* **The trigger decides what's available.** An incident trigger can't see an alert's attributes. To use those, start the workflow from **an alert is attached to an incident** instead.

### Query expressions

When you need to do more than follow a link, add a **Query** expression. See [How to use Workflow Expressions](/workflows/expressions). A Query starts from a value and applies steps in order:

* **Navigate** follows an attribute to a related entry, like from a service to its team. From a list, it returns a list.
* **Filter** keeps the entries that match your conditions.
* **First**, **Maximum**, **Minimum**, and **Random** pick one entry from a list.
* **Count** and **Sum** turn a list into a number.
* **Merge** combines the result with another variable of the same type.

To fill a field that takes one value from a list, end the Query with **Filter** and then **First**. Don't rely on **First** alone when the order of the list doesn't mean anything, like the teams a person belongs to.

If a required field could end up with no value, set a default in the expression. Otherwise the step can't run for incidents where the path is empty. To skip those incidents altogether, add a condition to the workflow instead.

### Templates

Several workflow templates are built this way, including **Notify responders about new incidents**, **Invite the affected team to an incident**, and **Escalate via incident.io**. When you create one, it finds a path through your Catalog from the incident to the channel, user group, or escalation path it needs.

## Follow relationships in alert routes

When your alert attributes are Catalog-backed, an alert route can use them the same way. Under **How should alerts be escalated?**, choose to escalate **using the alert's attributes**, and the route suggests paths from the alert to an escalation path, like **Alert → Team → Escalation path**. See [Alerts and teams](/alerts/team-routing) for a walkthrough.

The route's incident template can set custom fields from the alert's attributes too, so incidents created from alerts arrive with their affected services and teams already filled in.

This depends on the alert's attribute matching a catalog entry:

* **The value must match exactly.** It's compared, case-sensitively, with each entry's ID, external ID, and aliases, and with its name if the catalog type has **Reference entries by name** turned on. If more than one entry matches, the external ID wins, then an alias, then the name.
* **If nothing matches, the attribute is left empty**, without an error. Anything the route derives from it is empty too, so no one is paged from that path.

Set a fallback escalation path on the route, so an alert that doesn't match still reaches someone.

## Derive one field from another

A custom field can fill itself in from another one. Set **Affected teams** to **Set automatically**, and use an expression that navigates from **Affected services** to each service's owning team. Responders pick the service, and the team follows. See [Set a custom field automatically](/incidents/custom-fields#set-a-custom-field-automatically).

## Connect people across tools

People have accounts in many tools, and the Catalog links them. Each external user type, like **Github User**, **PagerDuty User**, or **Sentry User**, has an **incident.io User** attribute that points at the person's incident.io account. Many integrations link accounts automatically when you connect them. GitHub and Jira accounts are never linked automatically: each person connects their own from their [connected accounts](/catalog/connected-users) settings, or an admin links them from the **User** catalog type.

A step that needs a person, like **Invite user or group to the incident's channel** or **Assign incident roles**, takes an incident.io user. To use someone from another tool, navigate to their **incident.io User**. For example, if your **Service** type has a **Code owner** attribute of type **Github User**, pick **Incident → Affected services → Code owner → incident.io User** in the invite step to invite the code owners of the affected services.

If someone isn't linked, their **incident.io User** is empty, so the step leaves them out and still runs for everyone else.

Slack users are the exception: a **Slack User** can fill a user parameter directly.
