# Tag Contact：给联系人打标签

给这个对话背后的联系人打标签 —— Contacts、细分人群和群发都会读取它，还能通过 pipeline 规则推动一笔交易。

## 快速上手

1. 进入 **Automate → Workflows** 打开一个工作流。点 **+**，选 **Tag Contact**。
2. 如果这个标签只和这一个对话有关，请改用 **Tag Conversation**。
3. 把 **Action** 留在 **Add Tag**，**On** 留在 **Contact**。
4. 从标签按钮里选一个或多个标签，或者输入一个新标签后按 Enter。
5. 在顶部工具栏把 **Status** 设成 **Published**，点 **Save**，再确认 **发布**。客服请找所有者或管理员。

## 注意

- 在 **Pipelines → 管理 Pipelines** 里配置过的标签，还可能推动或开启一笔交易 —— 在假设这一步只是打标签之前，先去那里检查一下。

## 在哪里找到它

**Automate → Workflows**，打开一个工作流，在画布上点 **+**，然后在 **Add Steps** 里选 **Tag Contact**。

## 开始之前

- **所有者**、**管理员** 或 **客服** 都可以添加这一步并保存工作流。发布这个工作流 —— 让它对真实对话生效的操作 —— 是 **所有者** 或 **管理员** 的权限。
- 能不能搭建和运行工作流取决于你的套餐，详见[价格](/pricing)。
- 不需要连接 Inchat 以外的任何东西。

## 设置步骤

1. 打开工作流，在需要打标签的位置点 **+**。
2. 选 **Tag Contact**。
3. 把 **Action** 留在 **Add Tag**，**On** 留在 **Contact** —— 改动其中任何一个，都会把这一步变成 Tag Conversation、Untag Conversation 或 Untag Contact，因为这四个步骤共用同一个编辑器。
4. 从这个工作区已经用过的标签按钮里选一个或多个，或者输入一个新标签后按 Enter。
5. 保存这一步。要发布：在编辑器顶部的工具栏把 **Status** 设成 **Published**，点 **Save**，再用 **发布** 确认。只改下拉框、不保存的话什么都不会生效。

## 字段

| 字段 | 含义 | 默认值 | 限制 |
| --- | --- | --- | --- |
| Action | Add Tag 或 Remove Tag。 | Add Tag | 选 **Remove Tag** 会把这一步保存成 Untag Contact 步骤。 |
| On | 标签是打在联系人身上，还是只打在这一个对话上。 | Contact | 选 **Conversation** 会把这一步保存成 Tag Conversation 步骤。 |
| Tags | 工作区里用过的每个标签都有一个按钮，另外还有一个可以输入新标签的框。一步可以选多个标签。 | — | 一步最多保留 20 个标签：超过第 20 个的会在保存时被丢弃，不会有任何提示。在这里输入的、工作区标签列表里还没有的名字会被自动加进去；超过 64 个字符的名字保存时会被拒绝。 |

## 它如何运作

- 这一步会找到这个对话背后的联系人，把标签写进他的记录里 —— 联系人侧边栏显示的、**Contacts** 用来筛选的、细分人群和群发定向的，都是这份记录。它不会动这个对话自己的标签；那是 **Tag Conversation** 的工作。
- 即使工作流前面没有任何步骤查过这位联系人，这一步照样能用。
- 给已经有这个标签的联系人再打一次，不会有任何效果：不会显示错误，因为什么都没改变，联系人的「动态」标签页里也不会多出任何记录。
- 一步里写了好几个标签时，即使前面某个写入失败，后面的每一个照样会尝试。
- 只要其中有一个失败，这一步就会在这次运行的 Activity 标签页里显示为失败。
- 每个标签名存进去之前都会被清理 —— 去除首尾空格、截断到 64 个字符，并且不区分大小写地去匹配工作区已有的标签列表。给已经有「Sale」标签的联系人写「sale」，不会多出第二个标签。
- 写入会合并到标签列表里已有的那个拼写上，不过这一步仍然会把它算作一次添加，并在联系人的「动态」标签页里记录「sale」这个名字。
- 真正添加成功的标签（不是无效操作）会记录到联系人的「动态」标签页里 —— 标注为由工作流添加，或者是 AI agent 在一轮 AI 对话里添加的。
- 在 **Pipelines → 管理 Pipelines** 里，可以给某个 pipeline 阶段配置 **“联系人被打上这些标签时，deal 自动移到这里（只往前移）”**。
- 给联系人打上那个阶段名单里的标签，会把他在这个 pipeline 里已经开着的交易往前推到这个阶段。如果联系人在这个 pipeline 里没有正在进行的交易，只有在他从来没有过这个 pipeline 的交易时，才会开一笔新的。已成交或已流失的交易也算「有过」。
- 这次移动会为任何监听它的工作流触发 **Deal Stage Changed**，**Moved by** 会设成 **A rule or import**。没有在任何阶段配置过的标签不会做这些事 —— 由工作流的作者在那里设置，来决定哪些标签有这个作用。

## 它在什么时候会失败

- 这个对话没有关联联系人：这一步会失败，提示 **this conversation has no contact to tag**，不会写入任何东西。
- Inchat 自己在读写联系人时出现的临时问题 —— 不是你做错了什么 —— 也会让这一步失败。这和上面那种情况不一样：没有设置具体原因，所以这次运行的 **Activity** 标签页会显示固定的一行 **failed without a reported reason**，而不是上面那条消息。
- 打标签失败不会让流程停下。这一步会在运行的 Activity 标签页里显示为失败，流程继续往下一步走，所以排在它后面的消息或结束操作，照样会发生在这个没打上标签的联系人身上。

## 它不会做什么

- 它从不会动这个对话自己的标签 —— 想让标签随对话一起消失的工作流，需要改用 **Tag Conversation**。
- 标签会应用到联系人的所有渠道上，而不只是这个对话的渠道 —— 一位在两个渠道都写过消息的联系人，两边都会带着同一个标签。
- 它不会为这个工作区的其他工作流触发 **Contact Tag Updated**。只有在 Contacts、收件箱侧边栏、应用或公开 API 里做的改动才会触发它 —— 想特意交接的话，请改用 **Trigger Another Workflow**。
- 不过有一个例外：某个 pipeline 阶段在监听的标签（见「它如何运作」），照样可以开启或推动一笔交易。
- 这依然会为其他工作流触发 **Deal Stage Changed** —— 即使这个特定的触发器从不会触发。

## 最佳做法

- 只要之后的群发或细分人群需要再找到同一批人，就用这一步，而不是 Tag Conversation。
- 在假设一个打标签的步骤只是打标签之前，先去 **Pipelines → 管理 Pipelines** 检查一下。看看有没有阶段在「联系人被打上这些标签时，deal 自动移到这里」下配置了标签 —— 这些标签里，有的也能推动一笔交易。

## 使用场景

- **Record Attendance** 把联系人标记为已出席之后，给他打上 `webinar-attendee` 标签，这样之后的群发就能精准定向这批人。
- 联系人的交易金额超过某个门槛后，给他打上 `vip` 标签，这样之后和他的每一次对话都能在一个 Contacts 筛选条件下看到。

## 相关文章

- [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`, `src/lib/workflows/condition-catalog.ts`
