xiantong 文档

自动化

通过在 xiantong 应用和 Agent 事件上触发操作来自动化工作流程

通过在 xiantong 的应用和 Agent 事件上触发操作来自动化工作流程

只需告诉 xiantong。 说诸如“创建一个在会话被标记时通知我的自动化”或“每天下午 9 点设置每日早报”之类的话。xiantong 会为你创建并验证配置。

自动化让你在 xiantong 中事件发生时自动触发操作。你可以运行 shell 命令、发送提示以启动新会话,或安排定期工作流——所有这些都在一个 JSON 文件中配置。

开始使用#

设置自动化最简单的方法就是用自然语言描述你的需求。你可以尝试以下提示:

你想要的你可以这样说
定时简报“设置一个每个工作日 9 点的每日例会简报”
桌面通知“当某个会话被标记为 urgent 时,用 macOS 通知提醒我”
审计日志“将所有权限模式更改记录到文件中”
自动打标签“会话启动时,运行一个命令检查工作目录并记录下来”
定期报告“每周五下午 5 点创建一个总结本周已完成任务的会话”
Webhook 集成“当我标记某个会话时,向我的 webhook URL 发送 curl 请求”

你的第一个自动化#

这里是最简单的自动化:每当会话添加标签时,它就记录一条消息:

{
"version": 2,
"automations": {
"LabelAdd": [
{
"actions": [
{ "type": "command", "command": "echo \"Label added: $XIANTONG_LABEL\" >> ~/xiantong-automations.log" }
]
}
]
}
}

将其保存为 ~/.xiantong/workspaces/{workspaceId}/automations.json,它会立即生效——无需重启。

安排提示#

想让 xiantong 按计划为你执行某些操作?使用带有 cron 表达式的提示操作:

{
"version": 2,
"automations": {
"SchedulerTick": [
{
"cron": "0 9 * * 1-5",
"timezone": "America/New_York",
"labels": ["Scheduled"],
"actions": [
{ "type": "prompt", "prompt": "检查 @github 是否有新的分配给我的 issue 并总结它们" }
]
}
]
}
}

这会在每个工作日的 上午 9 点创建一个新会话,激活 GitHub 源,并让 xiantong 检查你的 issue。该会话会自动标记为 “Scheduled” 以便快速过滤。

自动化如何工作#

当事件触发(例如添加了标签、工具运行或 cron 匹配)时,xiantong 会检查你的配置以匹配项并执行它们。有两种操作类型:

  • 命令操作 — 执行 shell 命令,事件数据作为环境变量提供
  • 提示操作 — 将提示发送给 xiantong,创建新会话(仅适用于应用事件)

配置文件#

每个工作区在 automations.json 中配置自动化:

~/.xiantong/workspaces/{workspaceId}/automations.json

基本结构#

{
"version": 2,
"automations": {
"EventName": [
{
"matcher": "regex-pattern",
"actions": [
{ "type": "command", "command": "echo 'Hello'" }
]
}
]
}
}

每种事件类型对应一个匹配器数组,每个匹配器包含事件值匹配时要执行的操作数组。

管理自动化#

在 UI 中#

自动化在侧边栏的 Automations 下列出。在这里你可以:

  • 启用 / 禁用 — 在不删除的情况下切换单个自动化的状态
  • 复制 — 创建已有自动化的副本,名称带 “Copy” 后缀
  • 删除 — 永久移除自动化
  • 测试 — 手动触发自动化,在等待实际事件前验证其是否有效。测试运行器会解析 @mentions、启用源并使用已配置的 llmConnection/model —— 与调度器走的是相同代码路径。
  • 执行历史 — 每条自动化记录成功与失败,可在详情页查看时间线。历史存储在 automations-history.jsonl 中,最多保留每条自动化最近 20 次运行(总共最多 1000 条记录)。

支持批量操作——选择多个自动化后可一起启用、禁用或删除。列表按最近执行时间排序,便于快速访问活跃自动化。

在配置文件中#

你也可以直接编辑 automations.json 管理自动化。更改立即生效——无需重新启动。启用与禁用: 在任意匹配器上设置 "enabled": false 可暂时禁用它而不删除配置。省略该字段或设为 true 即可重新启用。

{
"matcher": "^urgent$",
"enabled": false,
"actions": [
{ "type": "command", "command": "notify-send 'Urgent!'" }
]
}

删除:automations.json 中移除匹配器条目。如果某事件类型下不再有匹配器,可以移除整个事件键。

让你的 xiantong Agent 帮你管理自动化:“禁用我所有的定时自动化”或“移除紧急通知自动化”。xiantong 会直接读取并更新 automations.json

事件#

应用事件#

由 xiantong 自身触发。支持命令与提示操作。

事件触发条件匹配值
LabelAdd会话添加标签时标签 ID(例如 urgent
LabelRemove会话移除标签时标签 ID
LabelConfigChange标签配置更改时始终匹配
PermissionModeChange权限模式更改时新模式名称
FlagChange会话被标记或取消标记时truefalse
SessionStatusChange会话状态变更时新状态名称(例如 done
SchedulerTick每分钟运行一次使用 cron 匹配

重命名: TodoStateChange 已重命名为 SessionStatusChange。旧名称仍可用但会显示验证警告。建议将所有自动化更新为 SessionStatusChange

状态变更: 若想响应状态/工作流状态变化(例如会话转为 “done” 或 “in-progress”),可使用 SessionStatusChange 事件。匹配值是新状态名称,因此你可以使用 "^done$" 之类的匹配器仅在特定迁移触发时生效。

Agent 事件#

传递给 Claude SDK。仅支持命令操作(不支持提示操作)。

事件触发条件匹配值
PreToolUse工具执行前工具名称
PostToolUse工具成功后工具名称
PostToolUseFailure工具失败后工具名称
UserPromptSubmit用户提交提示时事件数据 JSON
SessionStart会话开始事件数据 JSON
SessionEnd会话结束事件数据 JSON
StopAgent 停止事件数据 JSON
SubagentStart子 Agent 启动事件数据 JSON
SubagentStop子 Agent 完成事件数据 JSON
Notification接收到通知事件数据 JSON
PreCompact上下文压缩前事件数据 JSON
PermissionRequest请求权限事件数据 JSON
SetupAgent 初始化事件数据 JSON

操作类型#

命令操作#

事件触发时执行 shell 命令。事件数据可通过环境变量访问。

{
"type": "command",
"command": "echo \"标签 $XIANTONG_LABEL 已添加\" >> ~/automation-log.txt",
"timeout": 60000
}
属性类型默认值说明
type"command"必需操作类型
commandstring必需要执行的 shell 命令
timeoutnumber60000超时时间(毫秒)

提示操作#

将提示发送给 xiantong,创建新会话。仅适用于应用事件。

{
"type": "prompt",
"prompt": "运行 @weather 技能并总结今天的天气预报"
}
属性类型默认值说明
type"prompt"必需操作类型
promptstring必需要发送的提示文本
llmConnectionstring工作区默认LLM 连接 slug(在 AI 设置中配置)
modelstring工作区默认为创建的会话指定的模型 ID

特点:

  • 使用 @mentions 引用源或技能(例如 @github@linear
  • 环境变量会展开(例如 $XIANTONG_LABEL${XIANTONG_SESSION_NAME}
  • 被提及的源会自动为新会话启用

LLM 连接与模型: 你可以指定提示操作创建的会话使用哪个 AI 提供商和模型。如果省略,则使用工作区默认连接与模型。

{
"type": "prompt",
"prompt": "对最近的更改进行快速代码审查",
"llmConnection": "my-copilot-connection",
"model": "gemini-3-pro-preview"
}

llmConnection 的值是 AI 设置中配置的 LLM 连接 slug。model 是该提供商支持的模型 ID。如果任一无效或找不到,系统会优雅地回退至工作区默认配置。

匹配器#

正则匹配#

大多数事件会针对事件的匹配值执行正则匹配:

{
"matcher": "^urgent$",
"actions": [
{ "type": "command", "command": "notify-send 'Urgent!'" }
]
}

省略 matcher 字段即可匹配该类型的所有事件。示例:

模式匹配内容
^urgent$与 “urgent” 完全匹配
bug|feature匹配 “bug” 或 “feature”
^prod-匹配以 “prod-” 开头的任意值
(省略)匹配该类型的所有事件

Cron 匹配#

对于 SchedulerTick 事件,请使用 cron 表达式而非正则:

{
"cron": "0 9 * * 1-5",
"timezone": "Europe/Budapest",
"actions": [
{ "type": "prompt", "prompt": "给我一个早间简报" }
]
}

Cron 格式: 分钟 小时 月内日 月 星期

字段范围示例
分钟0–590*/15
小时0–23914
月内日1–31115
1–121*/3
星期0–6(0 = 周日)1-50,6

常见模式:

Cron计划
*/15 * * * *每 15 分钟一次
0 9 * * *每天 9:00
0 9 * * 1-5工作日 9:00
30 14 1 * *每月 1 日 14:30
0 */6 * * *每 6 小时一次

时区: 使用 IANA 时区名称(例如 Europe/BudapestAmerica/New_York)。如果未指定,则默认使用系统时区。可通过 crontab.guru 进行验证。

条件#

条件是可选的筛选器,在匹配器/cron 匹配后但在执行操作前运行。数组中的所有条件必须通过(隐含的 AND)。如果数组为空或省略,则无条件地执行操作。

条件可组合——你可以结合时间窗口、星期过滤和状态检查,从而在无需复杂 cron 的情况下构建精确的自动化触发逻辑。

{
"cron": "0 9 * * *",
"timezone": "Europe/Budapest",
"conditions": [
{
"condition": "time",
"weekday": ["mon", "tue", "wed", "thu", "fri"]
}
],
"actions": [
{ "type": "prompt", "prompt": "早安!这是你的每日简报。" }
]
}

时间条件#

检查指定时区中的时间和星期:

{
"condition": "time",
"after": "09:00",
"before": "17:00",
"weekday": ["mon", "tue", "wed", "thu", "fri"],
"timezone": "Europe/Budapest"
}
属性类型说明
after"HH:MM"时间窗口开始(包含)
before"HH:MM"时间窗口结束(排除)
weekdaystring[]允许的星期:montuewedthufrisatsun
timezonestringIANA 时区。若未设置,则依次回退至匹配器时区,再回退至系统本地时区

过夜范围: 如果 after 晚于 before(例如 "after": "22:00", "before": "06:00"),则时间段会跨越午夜。

状态条件#

检查事件载荷中的字段,用于筛选特定的迁移或值:

{
"condition": "state",
"field": "permissionMode",
"from": "safe",
"to": "allow-all"
}
属性类型说明
fieldstring载荷字段名(例如 permissionModesessionStatuslabelsisFlagged
valueany精确匹配
fromany旧值(用于迁移事件)
toany新值(用于迁移事件)
containsstring数组成员检查(例如判断标签是否存在)
not_valueany匹配除该值以外的任意值

迁移字段: 对于 permissionModesessionStatusfrom/to 会自动解析为正确的载荷键(分别为 oldMode/newModeoldState/newState)。

逻辑组合#

使用 andornot 组合条件:

{
"condition": "and",
"conditions": [
{ "condition": "time", "weekday": ["mon", "tue", "wed", "thu", "fri"] },
{ "condition": "time", "after": "09:00", "before": "17:00" }
]
}
{
"condition": "or",
"conditions": [
{ "condition": "state", "field": "permissionMode", "value": "allow-all" },
{ "condition": "state", "field": "isFlagged", "value": true }
]
}
{
"condition": "not",
"conditions": [
{ "condition": "time", "weekday": ["sat", "sun"] }
]
}
类型行为
and所有子条件必须通过
or至少一个子条件通过
not所有子条件都必须不通过

条件最多可嵌套 8 层。达到第 4 层时会发出简化警告。请尽量保持结构扁平。未知的条件类型会闭合失败(结果为 false)。

匹配器选项#

每个匹配器条目都支持以下可选字段:

属性类型默认值说明
matcherstring匹配所有事件过滤的正则模式
cronstringCron 表达式(仅限 SchedulerTick)
timezonestring系统时区Cron 的 IANA 时区
conditionsarray[]所有条件必须在执行操作前通过(参见 条件
permissionModestring"safe"命令的安全模式
labelsstring[][]为提示创建的会话附加的标签
enabledbooleantrue设置为 false 可在不删除的情况下禁用
actionsarray必需命令/提示操作数组

环境变量#

通用变量#

所有命令操作都可访问:

变量说明
XIANTONG_EVENT事件名称(例如 LabelAddPreToolUse
XIANTONG_EVENT_DATA完整事件载荷(JSON)
XIANTONG_SESSION_ID当前会话 ID
XIANTONG_SESSION_NAME当前会话名称
XIANTONG_WORKSPACE_ID当前工作区 ID

应用事件变量#

从事件载荷动态生成:

标签事件LabelAddLabelRemove):

  • XIANTONG_LABEL — 被添加/移除的标签 ID

PermissionModeChange:

  • XIANTONG_OLD_MODE — 之前的权限模式
  • XIANTONG_NEW_MODE — 新的权限模式

FlagChange:

  • XIANTONG_IS_FLAGGEDtruefalse

SessionStatusChange:

  • XIANTONG_OLD_STATE — 之前的会话状态
  • XIANTONG_NEW_STATE — 新的会话状态

SchedulerTick:

  • XIANTONG_LOCAL_TIME — 当前时间(HH:MM)
  • XIANTONG_LOCAL_DATE — 当前日期(YYYY-MM-DD)

Agent 事件变量#

工具事件PreToolUsePostToolUsePostToolUseFailure):

  • XIANTONG_TOOL_NAME — 正在使用的工具
  • XIANTONG_TOOL_INPUT — 工具参数(JSON)
  • XIANTONG_TOOL_RESPONSE — 工具输出(仅限 PostToolUse)
  • XIANTONG_ERROR — 错误信息(仅限 PostToolUseFailure)

会话事件SessionStart):

  • XIANTONG_SOURCE — 会话来源(例如 startupresume
  • XIANTONG_MODEL — 模型名称

子 Agent 事件SubagentStartSubagentStop):

  • XIANTONG_AGENT_ID — 子 Agent ID
  • XIANTONG_AGENT_TYPE — 子 Agent 类型

权限模式#

命令操作默认经过安全检查。可在每个匹配器中调整:

模式行为使用场景
safe命令基于白名单进行检查默认推荐
allow-all绕过安全检查仅限受信任的自动化

仅在完全信任命令时使用 allow-all,它允许执行任意 shell 命令。

{
"matcher": "^urgent$",
"permissionMode": "allow-all",
"actions": [
{ "type": "command", "command": "osascript -e 'display notification \"紧急会话已标记\" with title \"xiantong\"'" }
]
}

提示操作的标签#

提示操作可以为它们创建的会话附带标签,方便过滤与整理定时会话:

{
"cron": "0 9 * * *",
"labels": ["Scheduled", "morning-briefing"],
"actions": [
{ "type": "prompt", "prompt": "告诉我今天的重点事项" }
]
}

标签也支持环境变量展开:"priority::${XIANTONG_LABEL}"

速率限制#

为防止自动化之间形成死循环(例如一个自动化间接触发自身),事件总线实施了速率限制:

事件最大每分钟触发次数
SchedulerTick60(每秒 1 次)
其他所有事件10

超出限制的事件在剩余 60 秒窗口中会被静默丢弃。

示例#

每日早间简报#

在每个工作日的上午 9 点安排一个提示:

{
"version": 2,
"automations": {
"SchedulerTick": [
{
"cron": "0 9 * * 1-5",
"timezone": "Europe/Budapest",
"labels": ["Scheduled", "briefing"],
"actions": [
{ "type": "prompt", "prompt": "运行 @daily-standup 技能" }
]
}
]
}
}

仅限工作日的 AI 新闻(含条件)#

使用 time 条件把每日计划限定为工作日:

{
"version": 2,
"automations": {
"SchedulerTick": [
{
"name": "早间 AI 新闻",
"cron": "0 9 * * *",
"timezone": "Europe/Budapest",
"conditions": [
{
"condition": "time",
"weekday": ["mon", "tue", "wed", "thu", "fri"],
"timezone": "Europe/Budapest"
}
],
"labels": ["Scheduled", "ai-news"],
"actions": [
{ "type": "prompt", "prompt": "运行 @ai-news 技能并总结当天的 AI 发展" }
]
}
]
}
}

权限模式闸门(含条件)#

仅在权限模式从 safe 变为 allow-all 时通知:

{
"version": 2,
"automations": {
"PermissionModeChange": [
{
"conditions": [
{
"condition": "state",
"field": "permissionMode",
"from": "safe",
"to": "allow-all"
}
],
"actions": [
{ "type": "command", "command": "osascript -e 'display notification \"权限已升级至 allow-all\" with title \"xiantong\"'" }
]
}
]
}
}

记录标签变化#

追踪标签的添加与移除:

{
"version": 2,
"automations": {
"LabelAdd": [
{
"permissionMode": "allow-all",
"actions": [
{ "type": "command", "command": "echo \"[$(date)] 添加: $XIANTONG_LABEL\" >> ~/label-log.txt" }
]
}
],
"LabelRemove": [
{
"permissionMode": "allow-all",
"actions": [
{ "type": "command", "command": "echo \"[$(date)] 移除: $XIANTONG_LABEL\" >> ~/label-log.txt" }
]
}
]
}
}

标记为 urgent 时的 macOS 通知#

{
"version": 2,
"automations": {
"LabelAdd": [
{
"matcher": "^urgent$",
"permissionMode": "allow-all",
"actions": [
{
"type": "command",
"command": "osascript -e 'display notification \"紧急会话被标记\" with title \"xiantong\"'"
}
]
}
]
}
}

审计权限模式变化#

{
"version": 2,
"automations": {
"PermissionModeChange": [
{
"permissionMode": "allow-all",
"actions": [
{
"type": "command",
"command": "echo \"$(date): $XIANTONG_OLD_MODE -> $XIANTONG_NEW_MODE\" >> ~/mode-audit.log"
}
]
}
]
}
}

不同时间段的多个计划并开启/关闭控制#

在不同时间运行多个自动化,并可在不删除的情况下禁用某些项:

{
"version": 2,
"automations": {
"SchedulerTick": [
{
"cron": "0 9 * * 1-5",
"timezone": "Europe/Budapest",
"labels": ["Scheduled"],
"actions": [
{ "type": "prompt", "prompt": "给我一个早间简报" }
]
},
{
"cron": "0 17 * * 5",
"timezone": "Europe/Budapest",
"enabled": false,
"labels": ["Scheduled"],
"actions": [
{ "type": "prompt", "prompt": "总结本周已完成的任务" }
]
}
]
}
}

第二条自动化(周五总结)被禁用,直到将 "enabled" 设置为 true 或移除它。

使用特定 LLM 连接的提示#

为某个自动化指定不同的 AI 提供商:

{
"version": 2,
"automations": {
"SchedulerTick": [
{
"cron": "0 8 * * 1-5",
"timezone": "Europe/Budapest",
"labels": ["Scheduled"],
"actions": [
{
"type": "prompt",
"prompt": "回顾夜间 @github 的拉取请求",
"llmConnection": "openrouter",
"model": "anthropic/claude-sonnet-4.6"
}
]
}
]
}
}

验证#

让 xiantong 验证你的自动化:

Validate my automations configuration

或使用 config_validate 工具,target: "all"。验证器检查以下内容:

  • 无效的 JSON 语法
  • 未知的事件名称
  • 空的操作数组
  • 无效的 cron 表达式或时区
  • 无效或不安全的正则模式(防范 ReDoS)
  • 引用不存在的标签
  • 无效的条件类型、字段名或星期值
  • 条件嵌套层数超过限制
  • 缺失的 llmConnection slug(错误 —— 运行时会失败)
  • 同时指定了 llmConnectionmodel 时,模型/提供商不匹配(警告)

安全#

自动化包含多个内置安全措施:

  • 防止 shell 注入 —— 环境变量中的用户可控值(会话名、标签、提示文本)会自动进行转义
  • 防范 ReDoS —— 正则长度限制为 500 字符,并检测灾难性回溯模式
  • 速率限制 —— 防止自动化触发其他自动化导致无限循环
  • 权限模式 —— 默认情况下命令会经过白名单检查
  • 超时 —— 命令在超时后终止(若需要会发送 SIGKILL)

最佳实践#

  • 从简单开始 —— 用 echo 命令测试,再编写复杂脚本
  • 使用标签 —— 为定时会话打标以便快速过滤
  • 设置超时 —— 用 timeout 字段避免命令失控
  • 记录失败 —— 将 stderr 重定向用于追踪问题:command 2>> ~/automation-errors.log
  • 精确匹配 —— 使用匹配器避免每个事件都触发
  • 验证 cron —— 用 crontab.guru 确认表达式
  • 使用 enabled: false —— 调试时可暂时禁用自动化而不是删除

故障排查:自动化未触发#

  1. 检查事件名称 —— 必须完全匹配(例如 LabelAdd,不要写成 labeladd
  2. 检查匹配器 —— 正则必须与事件的匹配值匹配
  3. 检查 cron —— SchedulerTick 时确认 cron 表达式是否正确
  4. 检查启用状态 —— 确认匹配器没有 "enabled": false
  5. 检查日志 —— 查看应用日志中带有 [automations] 的记录

故障排查:命令被阻止#

如果看到 “Bash command blocked” 错误:

  1. 在匹配器中添加 "permissionMode": "allow-all"
  2. 或简化命令,避免使用如 $() 的复杂 shell 构造

故障排查:提示未创建会话#

  1. 确保事件属于 应用事件(提示操作不适用于 Agent 事件)
  2. 检查提示文本非空
  3. 确认 @mentions 引用了有效的源或技能

故障排查:条件未匹配#

  1. 检查星期拼写 —— 必须是 3 个字母的小写:montuewedthufrisatsun
  2. 检查时区 —— 使用 IANA 名称(例如 Europe/Budapest)。无效时区会静默回退到系统本地时区
  3. 检查时间格式 —— 必须是 24 小时制的 HH:MM(例如 09:00,不要写成 9:00 AM
  4. 检查状态字段名 —— 使用 permissionModesessionStatuslabelsisFlagged
  5. 检查嵌套深度 —— 嵌套超过 8 层的条件总是评估为 false
  6. 检查日志 —— 查看带有 [automations] 的日志条目,了解条件评估情况