# Tag Contact

Add one or more tags to the person behind this conversation — what the contact sidebar, Contacts filters, segments and broadcasts all read, and what a pipeline stage can watch for to move a deal.

## Getting here

**Automate → Workflows**, open a workflow, click **+** on the canvas, then pick **Tag Contact** under **Add Steps**.

## Before you start

- An **owner**, **admin** or **agent** can add this step and save the workflow. Publishing that workflow — the thing that makes it run on live conversations — is an **owner** or **admin** action.
- Building and running workflows depends on your plan; see [pricing](/pricing).
- Nothing outside Inchat has to be connected.

## Set up

1. Open the workflow and click **+** where the tag belongs.
2. Pick **Tag Contact**.
3. Leave **Action** on **Add Tag** and **On** on **Contact** — switching either turns this into Tag Conversation, Untag Conversation or Untag Contact instead, since all four share one editor.
4. Pick one or more tags from the chips already used in this workspace, or type a new one and press Enter.
5. Save the step, then publish the workflow. A saved but unpublished workflow tags nobody.

## Fields

| Field | What it means | Default | Limits |
| --- | --- | --- | --- |
| Action | Add Tag or Remove Tag. | Add Tag | Choosing **Remove Tag** saves this as the Untag Contact step instead. |
| On | Whether the tag goes on the contact or on this one conversation. | Contact | Choosing **Conversation** saves this as the Tag Conversation step instead. |
| Tags | Chips for every tag already used somewhere in the workspace, plus a box to type a new one. Several may be picked on one step. | — | A step keeps at most 20 tags: any past the 20th are dropped when you save, with no warning. A name typed here that is not already in the workspace's tag list is added to it automatically; a name over 64 characters is refused when you save. |

## How it works

- The step resolves the contact behind this conversation and writes the tag onto `contacts.tags` — what the contact sidebar shows, what **Contacts** filters by, and what segments and broadcasts target. It does not touch the conversation's own tags; that is **Tag Conversation**'s job.
- It reads the contact through the conversation record rather than through the run's own field bag, so the tag is applied even on a run where nothing earlier happened to load the contact's fields.
- Adding a tag the contact already carries is a no-op success: nothing is written, and because nothing changed, nothing new is logged to the Activity tab either.
- Naming several tags on one step tries every one of them, even if an earlier one in the list failed to write, and the step is recorded failed if any of them did.
- Every tag name is normalised before it is stored — trimmed, capped at 64 characters, and matched to the workspace's existing tag list without regard to case. Writing “sale” onto a contact who already carries “Sale” does not create a second tag: the write is folded onto the catalogue's existing spelling — though the step still counts it as an add and logs “sale” on the Activity tab.
- A tag actually added (not a no-op) is logged to the contact's Activity tab, marked as added by a workflow (or by the AI agent, when the step runs inside an AI turn).
- A pipeline stage can be configured, under **Pipelines → Manage pipelines**, with **“Tagging a contact with these moves its deal here (forward only)”**. Adding a tag on that stage's list moves this contact's already-open deal in that pipeline forward to it, or opens a new deal there if the contact has never had one in that pipeline (a won or lost deal blocks it) — and that move fires **Deal Stage Changed** for any workflow listening on it, writer **system**. A tag not configured on any stage does none of this; the workflow author decides which tags matter by setting them up there.

## When it fails

- This conversation has no linked contact: the step fails with **this conversation has no contact to tag**, and nothing is written.
- A database error reading or writing the contact — rare and transient — also fails the step. This is a different case from the one above: no specific reason is set for it, so the run's **Activity** tab shows the fixed line **failed without a reported reason** instead of the message above.
- A failed tag write does not stop the run: the step is recorded failed and the flow moves straight to the next one, so a message or close placed after it still happens on the untagged contact.

## Limits

- It never touches this conversation's own tags — a workflow that wants the tag to disappear with the thread needs **Tag Conversation** instead.
- The tag applies to the contact everywhere, not to this conversation's channel alone — a contact who writes in on two channels carries the same tag on both.
- It does not fire this workspace's **Contact Tag Updated** trigger for other workflows — only a change made in (Contacts, the inbox sidebar, the app, or the public API) does; use **Trigger Another Workflow** to hand off on purpose instead. This is narrower than "cannot start a chain": a tag that a pipeline stage watches for (see How it works) can still open or move a deal and fire **Deal Stage Changed** for other workflows, even though this specific trigger never fires.

## Best practices

- Reach for this step, not Tag Conversation, whenever a later broadcast or segment needs to find the same people again.
- Check **Pipelines → Manage pipelines** for stages with tags configured under "Tagging a contact with these moves its deal here" before assuming a tag step only tags — one of these tags can also move a deal.

## Use cases

- Tag a contact `webinar-attendee` after **Record Attendance** marks them attended, so a later broadcast can target exactly that segment.
- Tag a contact `vip` once their deal crosses a value threshold, so every future conversation with them is visible in one Contacts filter.

## Related

- [Untag Contact](https://inchat.inseller.my/help/workflows/untag-contact)
- [Tag Conversation](https://inchat.inseller.my/help/workflows/tag-conversation)
- [Untag Conversation](https://inchat.inseller.my/help/workflows/untag-conversation)
- [Move Deal to Stage](https://inchat.inseller.my/help/workflows/move-deal-to-stage)
- [Conditions and variables](https://inchat.inseller.my/help/workflows/conditions-and-variables)
- [Workflows: how a flow runs](https://inchat.inseller.my/help/workflows/workflows-overview)

---

Source files: `src/lib/workflows/ai-builder/spec.ts`, `src/lib/workflows/canvas-model.ts`, `src/components/workflows/WorkflowStepConfigDrawer.tsx`, `src/lib/workflows/engine-record-actions.ts`, `src/lib/workflows/engine.ts`, `src/lib/workflows/form-payload.ts`, `src/lib/workflows/workflow-input-schema.ts`, `src/lib/activity/record.ts`, `src/lib/workflows/contact-triggers.ts`, `supabase/migrations/20260911210000_tags_catalog.sql`, `supabase/migrations/20260917190000_pipeline_stage_auto_tags.sql`, `supabase/migrations/20260920150000_opportunity_stage_events.sql`, `src/lib/pipelines/stage-events.ts`, `src/lib/i18n/messages/pipelines.ts`, `src/lib/conversations/upsert.ts`
