mcpField
W
wayai

wayai

github.com/wayai-proAgent 工作流0162 次安装今天更新
代码仓库

关于 wayai

通过工作区文件和 `wayai` CLI 配置及运维 WayAI hub 的 skill。它涵盖 Agent、工具、评估、旅程、分析和平台同步,适用于构建客户服务或后台运营的团队。

主要功能

  1. 01以工作区文件管理 hub
  2. 02拉取和推送 hub 配置
  3. 03配置 Agent、工具与技能
  4. 04运行评估并查看结果
  5. 05测试对话并查看分析

适用场景

  1. 01配置客户支持或销售 hub
  2. 02以代码方式维护 hub 配置
  3. 03测试对话和 Agent 行为
  4. 04查看 hub 分析与评估结果

MCP 相关

WayAI 支持将 MCP 连接作为一种连接类型:非 OAuth 的 MCP Bearer Token 连接通过 CLI 管理,MCP OAuth 连接则在平台 UI 中配置。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wayai-pro/wayai-skill --skill wayai

安装后在 Claude Code 中输入/wayai确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
agents-md-template.md
analytics.md
automations.md
calls.md
communities.md
connections.md
references/agents/
custom-tools.md
instructions.md
native-tools.md
prompt-principles.md
roles-and-settings.md
tool-principles.md
references/bases/
config-as-code.md
executors.md
files.md
integrations.md
querying.md
README.md
records.md
toolsets.md
references/canonical-example/
hub.yaml
README.md
references/canonical-example/agents/
support-pilot.md
support-pilot.yaml
references/canonical-example/company-faq/
billing.md
refunds.md
references/canonical-example/evals/
refund-eligible.yaml
references/canonical-example/journeys/
refund-flow.yaml
references/canonical-example/knowledge-base/file-types/
company-faq.yaml
references/canonical-example/knowledge-base/toolsets/
support-faq.yaml

详细介绍

WayAI Skill

WayAI 是 AI Agent 与人们协作的地方,帮助你服务客户并运营业务。每个中心都由 AI Agent 和人工团队组成,涵盖以人为本、跨渠道的支持和销售,以及以任务为中心的后台工作(中心类型)。此工作区以代码形式存储中心——每个中心一个文件夹(hub.yaml + agents/*.{yaml,md} + evals/、journeys/、skills/),并通过 wayai CLI 与平台进行双向同步。

平台是唯一可信来源。 工作区文件是编辑入口——更改通过文件 → wayai push → 平台流转。编辑前务必执行 wayai pull,以获取工作区之外的更改。

如何使用此技能: 本文件是完整的概念地图——此处对 WayAI 的每个基本构件都有足够详细的说明,帮助你决定要构建什么以及要修改哪些文件。字段级架构、各提供商的具体细节和运行机制位于 references/;下方每个领域章节的末尾都有对应深入说明文件的链接——着手编写或调试该领域时,请打开查看。从头开始生成完整中心前,请先阅读一次 references/canonical-example/README.md——其中展示了各部分如何组合。完整的路由表位于文末(参考文档)。

Agent 指南

  • 每次会话开始时,先获取最新版本,再做其他事情——每次都要执行,即使只是处理快速任务:更新 CLI,然后检查此技能是否过时,并在过时时刷新。CLI 或技能过时是导致下方某个步骤无法运行的最常见原因。按 工作流 → 现有中心中的步骤 1–2 执行(冷启动:状态机第 1–1c 行),并从第 1b 行复制技能安装命令,不要重新输入——其中的 mkdir -p .claude 前缀对 Claude Code 至关重要;第 1c 行说明了安装失败时该怎么做
  • 像人一样交流,不要像手册:用户可能刚接触 WayAI——用通俗语言,不要使用行话。回答简短直切重点;不要解释用户没问的内容。如果用户似乎卡住了,或询问某个概念的含义,用一句话回答后继续——不要把回复变成教程
  • 操作界面:设置通过 wayai CLI 和工作区文件完成——这是唯一的自动化入口,且需要文件系统/shell 访问权限(代码环境 Agent——Claude Code、Codex、Cursor、OpenCode)。通过该方式完成下方所有操作。如果你没有 shell 访问权限(应用环境 Agent——Claude Desktop、ChatGPT 等),就无法自行配置 WayAI——请将操作交给用户,使用与下方 OAuth 连接交接相同的形式(一条 URL、一个操作、一条完成确认):“打开 https://app.wayai.pro。在那里完成设置,或使用具备 shell 访问权限的 Agent 运行命令——一键提示词安装方式位于 https://wayai.pro。完成后告诉我。”之后继续依据此技能回答,绝不要声称自己完成了并未执行的配置
  • 只提供来自此技能、工具说明或参考文档的信息
  • 不要编造 URL、路径或步骤
  • 中心配置通过文件和 wayai CLI 流转;一次性设置(组织、OAuth)通过平台 UI 完成。预览版发布至正式版现在既可通过 CLI(wayai publish)完成,也可通过 UI 完成
  • 编辑前务必执行 wayai pull -y——以获取工作区之外的更改
  • 编辑后务必立即执行 wayai push -y——编辑和推送是一个整体操作。社区除外:推送会直接修改线上社区(没有预览),因此应先展示更改(wayai push communities/<folder> --dry-run),并且仅在用户明确同意后推送
  • 绝不自动提交——展示 git diff,等待用户批准

快速判断:我能做什么?

实体操作方式
Hub 设置、Agent、Agent 指令、工具、看板、状态、技能、评测、旅程、自动化、自定义工具CLI(wayai push);自动化可在应用中暂停
联系人和组织列表(组织的通讯录,自动化以此为目标)UI(组织设置 → 联系人)或 API(/api/contact-book)——绝不使用 hub.yaml。请参阅自动化
联系人在某个基础中的客户记录(对话提及该联系人时,客户范围的工具集所服务的记录)CLI(wayai contacts link-customer / unlink-customer,仅限浏览器登录)或 API(/api/contact-book/contacts/:id/customer)——请参阅将联系人关联到其客户记录
Hub 列表(Hub 对通讯录设置的自有筛选条件,自动化以此为目标)CLI(hub.yaml 中的 contact_lists:、wayai push)或 UI(Hub → 自动化 → 列表)
评测旅程(hub-as-code)——扁平文件夹中的 journeys/<slug>.yamlCLI(wayai push / wayai pull;首次创建后执行 pull 以同步步骤 ID)
连接——非 OAuth(Agent 提供方、STT/TTS、工具 API 密钥、MCP Bearer Token)CLI(根据组织凭据自动创建)
连接——OAuth(WhatsApp、Instagram、MCP OAuth)平台 UI
直接设置/轮换连接的凭据(包括生产环境)CLI(wayai set-connection-credential)或 UI
组织凭据——创建 / 轮换 / 编辑CLI(wayai create-credential / wayai update-credential)或 UI
组织级共享技能(org-as-code)CLI(wayai org pull / push / diff)
基础——架构、记录、关系、文件、工具集(数据界面)CLI(wayai bases、wayai records、wayai record-types 等;通过 wayai pull/push bases/<base> 进行配置即代码)——请先打开 references/bases/README.md
将技能同步到提供方CLI(wayai sync-skills)
对话测试CLI(wayai send-message、wayai conversations、wayai delete-history)
诊断 Hub 异常的原因(音频/TTS 未送达、Agent 无响应、工具故障)——首先检查连接/凭据的运行状况CLI(wayai alerts)——显示活跃的状态与通知警报(例如,无效的提供方密钥会显示为 connection_auth,通常对应 401)。请先运行此命令,再阅读代码或提交报告
诊断无法解释的 Agent 回复(日期错误、忽略规则、虚构值)——不要根据对话记录推断;请查看 Agent 实际收到的内容(解析后的提示词、渲染后的上下文、注入的时间戳、工具调用)CLI(wayai conversations <id> observability [--message-id <id>])——请先运行此命令,再编辑指令
在已结束的对话中记录事后业务结果(例如客户已购买),作为分析维度CLI(wayai conversations <id> annotate --set key=value [--type ...])
分析CLI(wayai analytics、wayai analytics query)
成本 / Token 消耗分析(按消息、模型、Agent、角色或凭据)CLI(对 message 表运行 wayai analytics sql)——请参阅 references/analytics.md——data.* 路径必须显式转换类型才能运行,且还需遵循确保求和结果正确的规则
评测运行和结果CLI(wayai run-eval、wayai eval-results)
语音通话——Realtime 连接、pilot_voice Agent、call_utterance 引导监控器CLI(wayai push)或 UI——请参阅 references/calls.md
通话评测——通话模式文本运行、评分后的机器通话CLI(wayai run-eval --call-mode、wayai eval call)——请参阅 references/evals.md
列出评测场景 / 对评测结果运行原始 SQLCLI(wayai evals、wayai evals sql)
将生产对话捕获为评测CLI(wayai eval capture <conversation_id>)
将生产对话捕获为旅程(完整的多轮对话记录)CLI(wayai eval journey capture <conversation_id>)
停止正在运行的评测会话CLI(wayai eval session stop <session_id>)
删除评测会话 / 运行历史记录CLI(wayai eval session delete <session_id>,或使用 --all 删除 Hub 上的所有会话)
报告 BugCLI(wayai report create)
工作区发现CLI(wayai list)
社区——列出组织的社区、读取 / 轮换 / 关闭加入链接、读取统计信息和仅限邀请社区的访问列表CLI(wayai communities,仅限浏览器登录)或 UI——请参阅 references/communities.md
社区——名称、设置(谁可以加入:admission)、规则、加入链接的启用/关闭状态、聊天室、课程(模块、课程)CLI(wayai-ws/communities/<folder>/、wayai pull/push communities/<folder>;push 会编辑线上社区)或 UI——请参阅 references/communities.md。审核:UI
组织——创建CLI(wayai org create)或 UI
组织——更新、删除UI
将预览发布/同步到生产环境CLI(wayai publish,别名为 wayai sync)或 UI
删除 HubUI
复制预览、设置/清除预览标签CLI(wayai replicate / wayai relabel)或 UI
团队、团队用户、Hub 用户、管理员、联系人审批UI(Hub → 用户选项卡)
组织标签(创建;编辑显示名称/颜色——slug 永久不变)UI(在 hub.yaml 的 tags: 中通过 slug 引用)

实体层级

Organization                ← CLI (`wayai org create`) or UI
├── Org Credentials         ← CLI (`wayai create-credential`/`update-credential`) or UI — API keys stored once, reused across hubs
├── Org Tags                ← UI — gate which credentials each hub can resolve and which contacts it sees
├── Org Skills              ← CLI (`wayai org pull/push`) — shared skills, fan out to linked hubs
├── Bases                   ← CLI (`wayai bases`) — the Data surface. Org-level, NOT inside a hub (see Bases)
├── Contact book            ← UI (Contacts) or API — contacts + org lists that automations target. Org-level, NOT in `hub.yaml`
└── Hub                     ← CLI (`wayai create`, or auto-creates on push) or UI; publish/sync via CLI (`wayai publish`) or UI
    ├── Connections         ← auto-created from org credentials on push (non-OAuth); OAuth via UI
    ├── Channels            ← auto-provisioned, never authored (see Channels)
    ├── Agents              ← CLI — `agents/<slug>.yaml` + `<slug>.md`
    │   ├── Tools           ← CLI — native, custom HTTP, MCP, delegation
    │   └── Skill links     ← CLI — `skills:` block in agent YAML
    ├── Kanban statuses     ← CLI — `hub.yaml` (workflow stages for conversations)
    ├── States              ← CLI — `hub.yaml` (JSON-schema data agents read/write)
    ├── Skills              ← CLI — `hub.yaml` `skills:` + `skills/` folder
    ├── Evals + Journeys    ← CLI — `evals/`, `journeys/`
    ├── Hub lists           ← CLI — `hub.yaml` `contact_lists:`; filters over the contact book (labels, scope tags)
    ├── Automations         ← CLI — `hub.yaml`; paused in the app; each targets a hub list or an org list by name
    └── Teams + Users       ← UI (Hub → Users) — teams, admins, team users, hub users

设置顺序:组织(CLI wayai org create 或 UI)→ 组织凭证(CLI 或 UI)→ Hub(CLI wayai create,或推送时自动创建,或 UI)→ 通过 CLI 配置 Agent、工具和连接。

创建 Hub 时会自动创建 wayai 连接(原生工具),无需设置。

Hub 类型

类型对话渠道用例
chat每位最终用户一个WhatsApp、Instagram、Email、Telegram、App以人为中心:支持、销售、服务台
task每位用户多个仅限 App以任务为中心:发票、库存、审批

判断方式:需要外部渠道(WhatsApp/Instagram/Email/Telegram)→ chat。处理对象/任务 → task。

AI 模式与对话模型

Hub 级别的 ai_mode 用于设置 AI 的行为:

模式行为
pilotAI 自主处理最终用户
copilotAI 为支持团队建议回复(不向渠道发送)
pilot+copilot根据当前回复者动态切换
turned_off禁用 AI;仅由人工处理

对话是最终用户与 Hub 之间的运行时会话(配置实体定义行为;对话和消息是它们作用的对象):

  • conversation_status:agent(由 AI 处理)| team(由人工团队处理)| ended(已关闭并归档)
  • 状态决定当前生效的 Agent 轨道:状态为 agent → Pilot 轨道通过渠道向最终用户回复;状态为 team(且模式为 copilot/pilot+copilot)→ Copilot 轨道起草建议,供团队在 /support 中查看
  • 轨道切换:使用 transfer_to_team 工具(agent → team),或由团队在支持 UI 中交回处理权(team → agent)。transfer_to_agent/consult_agent 用于在同一轨道内的 Agent 之间切换
  • 关闭方式:Agent 的 close_conversation 工具;转换为 isTerminalStatus 看板状态(通过任何界面——Agent 或 harness 工具、团队拖放操作、REST);团队 UI;或 Hub 的 auto_close_inactive_days。已结束的对话会归档并显示在“已结束”标签页中;在 conversation_retention_days 期限内,仍可使用 wayai conversations <id> annotate 进行事后标注
  • Agent 的回复文本会自动发送——没有发送消息工具;工具用于执行回复以外的操作

看板状态与上述内容相互独立:它跟踪工作流阶段(如 qualified 这样的自定义 slug),而非由谁回复。

Agent 角色

角色轨道每个 Hub 的数量描述
pilotPilot1自主响应最终用户
copilotCopilot1为支持团队提供回复建议
pilot_specialist / copilot_specialistBoth多个委派目标 — 通过 transfer_to_agent 完整转交
pilot_advisor / copilot_advisorBoth各 1 个通过 consult_agent 提供建议;随后归还控制权。仅在模型连接上运行,绝不在托管 Agent 连接上运行
monitorBackground每个触发器触发时 1 个静默观察;在 user_message 上,其规则可以采取行动 — 向负责回复的 Agent 提供你编写的备注、运行另一个 monitor 以进一步查看,或将对话移交给另一个 Agent 或人工团队;这些操作均对同一条消息生效。在 assistant_reply 上,它是回复关卡:在发送任何内容之前读取已拟好的回复,并可将其暂缓供团队处理,或让 Agent 重写一次。在 call_utterance 上,它会监控实时语音通话,并可通过你编写的备注引导语音。在 automation_fire 上,它是自动化的关卡:每次运行前决定运行、使用另一个 Agent 运行或跳过;在 automation_item 上,对于列表运行中的每个联系人,决定启动、使用另一个 Agent 启动或跳过。每个触发器最多只能启用一个 monitor,但 manual 除外(可启用任意数量 — 只有在另一个 monitor 调用它们时才会运行),两个自动化关卡也除外(可启用任意数量 — 每个自动化都会指定自己的关卡)
conversation_evaluator / message_evaluatorBackground各 1 个异步质量评估;不参与常规路由。其 evaluation_variables 会提供给 Analytics;message_evaluator 还会为评估运行打分
summarizerBackground1首个 pilot/copilot 创建时自动配置,使用其连接;但如果该连接是托管 Agent 连接,则不会如此(summarizer 仅在模型连接上运行)。将较早的消息汇总为滚动 JSON 摘要,并以保留的 slug conversation_summary 存储为对话状态。当有效输入令牌数超过 summarizer Agent 的 summarization_threshold_tokens 时,在轮次结束后异步触发(默认值为 120000;见下文)。非后台 Agent 会将摘要作为 <conversation_summary> 块查看,并可调用 expand_summary(section_id) 获取原始消息。架构可由用户编辑,但必须满足锚点不变量(sections[].id、message_id_start、message_id_end)
pilot_voicePilot(实时通话语音)多个(一个负责接听通话)Hub 实时 AI 语音通话所用的语音:与来电者交谈,并根据其指令将问题交给 pilot 回答。仅绑定 Realtime 连接;文本轮次、评估运行或转交操作均不会运行它 — 参见语音通话
consultant与轨道无关(按需)多个由人(和 Agent)在可见的咨询线程中咨询。绝不作为 pilot/copilot 响应者,不会自动触发,也不是转交或顾问目标。顾问在 AI 的轮次中提供建议且不可见;consultant 则由人(和 Agent)在可见线程中咨询。 咨询轮次按常规前台操作计费。支持团队在支持撰写框中标记它即可进行咨询(support-inbox.md)

transfer_to_agent 可将任务交给任何同轨道 Agent — *_specialist 或入口 pilot/copilot,因此 pilot 可充当集线器-辐射式路由器(specialist 可将跨领域请求转交回 pilot,以便重新分派)。跨轨道、advisor、consultant 和后台角色均不能作为转交目标。

有关角色流程、委派和设置详情,请参见 references/agents/roles-and-settings.md。

交接上下文工程

当对话更换负责方时(transfer_to_agent 或 transfer_to_team),接手者会从头重建历史记录,其中之前每个 Agent 的发言都会显示为无法区分的 assistant 消息,而人工团队的发言则没有署名(模型无法分辨哪些发言是它自己写的,哪些是继承来的)。运行时会自动弥合这一差距——请编写 Agent,使其能够与运行时协作:

  • 运行时会在每次 transfer_to_agent 和 transfer_to_team 时持久保存一条交接标记(This conversation was handed off from X to Y.),并在接收方 Agent 的首轮发言中提供一条一次性续接说明(仅适用于 Agent→Agent——团队交接没有可接收说明的 AI 接收方)。这些内容不需要你编写,因此不要在 Agent 的指令中加入“你刚刚接手了此对话”之类的措辞;运行时会处理,而且重复添加会造成冗余。
  • 每个 Agent 的指令都应以其身份介绍开头——You are <Agent Name>, the <role/purpose>…。运行时会在交接时强化身份信息,但系统提示词是最强的信号,也是每个常规轮次中唯一始终存在的身份信息;只有当 Agent 知道自己就是 Y 时,交接标记中的“……交给 Y”才有意义。
  • 专家 Agent 必须实际完成工作,不能把任务推回去。运行时会阻止将任务委派给本轮中之前已经接手过该对话的 Agent(包括 A→B→A 及更长的重复交接链);交接会被拒绝,并返回错误,提示 Agent 完成任务、转交给其他 Agent,或将控制权交还给用户。因此,不要编写会本能地把对话交还给委派方的 *_specialist 指令,否则只会触发防护机制。(每个用户轮次都会重置交接链,因此在后续轮次中将任务重新转交给之前接手过的 Agent 没问题。)
Summarizer Agent 配置

Summarizer Agent 在 agents/summarizer.yaml 中以顶层键 summarization_threshold_tokens 暴露摘要阈值(默认值为 120000,最小值为 1000,最大值为 1000000)。测试时可调低该值;对话很长时可调高。Summarizer 的 connection 默认使用 pilot 的连接(如果 pilot 使用托管 Agent 连接,则默认没有连接;请在模型连接上添加 summarizer);编辑 agents/summarizer.yaml 可更改其模型或系统提示词。conversation_summary 状态的架构与其他状态一样支持往返转换——允许添加锚点之外的字段,但锚点不可缺少。(此前这是 hub 级别的 hub.yaml 设置,现已迁移至 summarizer Agent。)

连接与凭据

连接是已配置的连接器实例(目录条目:大模型提供商、渠道 API、工具 API、语音服务),附带凭据并限定在一个 hub 内。组织凭据在组织级别存储一次密钥;连接通过名称引用它——原始密钥绝不会进入 YAML。

类别示例
AgentOpenAI、Anthropic、Google AI Studio、OpenRouter、xAI(AI 必需)
渠道WhatsApp、Instagram(OAuth — 仅限 UI);Resend(电子邮件)、Telegram(API Key — 自动创建)
工具 — 原生Wayai(自动创建)、External Resources(API Key)、Base Toolset(Bearer Token — 绑定到某个基础工具集的令牌)
工具 — 自定义用户定义的 HTTP 端点(API Key、Bearer Token、Basic Auth)
工具 — MCP外部 MCP 服务(Streamable HTTP)— 通过 CLI 使用 Bearer Token;通过 UI 使用 OAuth
语音STT 转写收到的语音消息(Groq、OpenAI、ElevenLabs)— 只有在启用了 STT 连接的 hub 上,应用的消息编辑器才会向最终用户和团队成员提供语音消息按钮;TTS 合成语音回复(OpenAI、Groq、ElevenLabs、Google),各语音响度相同
实时OpenAI GPT-Live — 实时 AI 语音通话使用的语音,仅供 pilot_voice Agent 使用

自动创建规则: 推送 hub.yaml 时,系统会根据匹配的组织凭据自动创建非 OAuth 连接(Agent、STT、TTS、Realtime、工具 — 自定义、通过 Bearer Token 连接的工具 — MCP)。匹配会遵循组织标签(无标签的凭据是全局凭据——每个 hub 都能使用;带标签的凭据仅对至少共享其中一个标签的 hub 可见)和凭据 environment。OAuth 连接必须先在 UI 中设置。

OAuth 连接交接(随时可进行,不限于引导设置期间): OAuth 连接(WhatsApp、Instagram、MCP OAuth)无法通过 CLI 创建——需要一次性 UI 流程。任何时候需要 OAuth 连接时——无论是首次设置,还是之后(新增渠道、OAuth MCP 服务)——都应将完整路径的连接选项卡深层链接 https://app.wayai.pro/settings/organizations/<orgId>/hubs/<hubId>/connections?connector=<slug>(<orgId>/<hubId> 来自 wayai status --json;<slug> ∈ whatsapp、instagram、mcp-server)提供给用户,然后等用户完成后运行 wayai pull -y。该深层链接会打开连接选项卡(如果连接已存在,例如需要重新授权,还会突出显示相应连接器);要创建连接,用户需点击添加连接,选择 <Connector> 卡片,选择 OAuth,然后完成提供商的授权流程。请使用此选项卡链接形式——不要使用 /connections/new?connector=…,因为它需要 connector_id UUID,且默认选择第一种认证类型(MCP → Bearer Token),因此无法使用 MCP OAuth(参见 navigation.md)。

有关各提供商的设置、凭据绑定(credential:、no_auth:)、标签以及生产凭据解耦,请参见 references/connections.md。

渠道

hub 上的通信端点——消息抵达和回复送达的位置。渠道绝不会在 YAML 中编写:

  • hub 创建时会自动创建 app(应用内聊天)和 system(内部)渠道
  • 创建渠道连接时,会自动配置 WhatsApp / Instagram / Email(Resend)/ Telegram 渠道

渠道唯一性(电话号码 / 页面 / 收件地址)仅在生产 hub 之间强制执行——预览环境可以与对应的生产环境共用端点;外部渠道可通过 #test CODE 测试人员注册功能在预览环境中进行测试(参见 Hub Environments)。

语音通话

chat hub 可以在 Web 应用的聊天视图中接听实时 AI 语音通话:来电者按下开始语音通话,听到一段提示,告知他们正在与 AI 对话(WayAI 的提示,或语音 Agent 用该语言自行说出的开场白),然后开始语音交流。任何 hub 都可以为他们配置。WayAI 可以在整个平台注册范围内关闭语音通话;关闭期间,wayai push 会拒绝创建 Realtime 连接或 pilot_voice Agent,也会拒绝启用下方列出的任何组件,并显示 Voice calls are not enabled for this platform, so …——看到此提示时,请停止操作并告知用户。

  • 语音由使用 Realtime 连接(基于组织自己的 OpenAI 项目密钥)的 pilot_voice Agent 提供。其设置包括语音、语言、通话限制、是否录音(默认关闭)、等待答案时是否播报进度提示,以及固定话术(问候语、提示、重复内容、道歉语、超时提示)的措辞;它遵循的唯一规则是自身指令:如何交谈,以及如何将每个问题交给 pilot(请从示例开始)
  • 答案由 hub 的 pilot 提供:语音将问题转交给 pilot,正如其指令应当要求的那样;pilot 会针对语音转交的每个问题执行一次常规轮次——包括工具、监视器和回复门控。是否允许 AI 回答,遵循与文本相同的规则;当这些规则不再允许回答时,通话就会结束(转接给团队、接管、关闭等)
  • 具有副作用的操作须等来电者口头确认;call_utterance 监视器可以在通话过程中引导语音;wayai run-eval --call-mode 和 wayai eval call 可用于评估通话
  • **计费:**语音转交的每个问题计为 1 次操作,此外还会按通话连接时长按分钟计费

设置、通话结束方式、团队可见的信息、录音、计费和限制:references/calls.md。

工具

在 agents/<slug>.yaml 中为每个 Agent 分配能力。请记住:回复文本不需要工具——工具用于其他所有操作。

类型来源方式
原生平台内置工具(例如 update_kanban_status、get_state、send_files、close_conversation、read_file)在 tools.native 下按名称列出
自定义由你定义的 HTTP 端点在 tools.custom 下使用 connection、method、path、config 定义
MCP来自已连接 MCP 服务的工具双来源——在每个 Agent 的 tools.mcp 下声明,和/或在平台 UI 中分配。wayai push 会在一次运行中发现并分配工具;存在 mcp 键(即使值为 [])时,以该键为准;省略该键则保留在 UI 中分配的工具。参见 native-tools.md
委派Agent 间委派(transfer_to_agent、consult_agent、start_consult_thread)、Agent 到团队(transfer_to_team),或 Agent 到 hub(delegate_to_hub、start_consult_thread)在 tools.delegation 下使用 target 定义(Agent 显示名称、团队名称或 hub 名称)

元工具(get_tool_schema、execute_tool)使 Agent 能够调用其架构未包含在内联列表中的工具。完整的原生工具目录和参数:references/agents/native-tools.md;自定义工具架构:references/agents/custom-tools.md;有关设计要公开的工具和参数:references/agents/tool-principles.md。

Hub 委派(delegate_to_hub)

将另一个 hub 视为顾问。该工具会在目标 hub 中创建一个任务对话,目标 hub 的答复会以消息形式异步返回到发起请求的咨询线程中,因此标记 Agent 的轮次会立即结束,不能等待结果。

- type: hub
  tool: delegate_to_hub
  target: Billing Hub        # a PRODUCTION (published) hub in the same organization
  context_boundary: summary  # instruction | summary | transcript
  • target 必须是同一组织内已发布(生产环境)的 hub_type: task hub。 选择生产环境是为了与分支语义保持一致;选择 task 是因为任务 hub 会为每个请求创建独立对话,而 chat hub 会为每位用户保留一个对话,因此每次委派都会堆积在同一个线程中,导致客户之间的信息混杂。跨组织、未发布或 chat 类型的目标会导致推送失败(运行时调用该工具也会失败)。
  • 目标 hub 必须关闭创建的对话——关闭就是完成信号。请求文本会指示它关闭对话,但如果目标 hub 的 Agent 永远无法关闭对话(没有 close_conversation 工具,也没有终结状态的看板状态),请求方就会一直等待。(由 Agent 发起的咨询会带有过期时间——参见 start_consult_thread;由团队发起的 hub 委派没有过期时间,因此要确保目标 hub 有办法完成任务。)
  • context_boundary 是数据敏感性决策,不是调优参数。 各 hub 的团队成员及其可查看的信息可能不同,因此请谨慎选择——不存在适用于任意 hub 对的安全默认值:
值传递到目标 hub 的内容
instruction仅 Agent 自身的请求。不包含对话中的任何内容。
summary(默认)请求 + 滚动更新的对话摘要。
transcript请求 + 完整的客户对话记录。

在任何设置下,内部咨询消息都不会传递;模型既不能选择目标,也不能扩大边界——这两项均由管理员配置。

  • 仅可在咨询线程中使用,结果也会在该线程中送达,因此请将它分配给 consultant 角色的 Agent。如果结果在对话关闭后到达,则会被丢弃(线程会记录为 cancelled_at_close)。
  • v1 中只能通过 CI/YAML 配置——在 hub 选择器和边界控制功能上线之前,平台 UI 的工具“添加”网格不会显示它,因为配置时需要同时做出上述两项选择。
Agent 发起咨询(start_consult_thread)

允许非后台 Agent在支持团队可见的咨询线程中向配置好的顾问(或合作方中心)提问——这是这套统一咨询机制的第三种发起方式,另外两种分别是人工标记顾问,以及 Agent 委派给中心。

- type: agent
  tool: start_consult_thread
  target: Billing Expert     # a `consultant`-role agent on this hub
  • 模式取决于目标对象。 同一中心的顾问会在工具调用中作答;合作方中心则会异步作答——提问的 Agent 会结束当前轮次(“我去确认后再回复你”),答案送达后会自动恢复。同步咨询耗时过长时会自行转为异步,因此 Agent 指令必须针对任何目标对象处理“答案稍后送达”的情况。顾问与除试点人员、副驾驶及其专家以外的所有角色一样,只能使用模型连接,不能使用托管 Agent 连接(Claude Agent (Managed)):不允许在此类连接上保存顾问;若向使用此类连接的顾问发起咨询,或顾问没有连接,则会在发送任何内容前拒绝请求。
  • 默认关闭顾问→顾问链式咨询;启用后仅支持同步模式——在工具上设置 allow_consultant_chain: true 即可允许此类咨询,但目标必须是同一中心的顾问。monitor、评估器和 summarizer 永远不能发起咨询。
  • 预算限制会强制执行:包括咨询链深度、双向循环拒绝(中心内 Agent A → B → A、跨中心中心 A → B → A)、每次 LLM 调用的上限,以及会话级持久上限。每个咨询轮次都会计入前台操作,因此这些上限可防止 Agent 在无人看管时不断增加成本。
  • 不会让任何请求永远处于待处理状态:未获答复的咨询会过期,并向提问者返回超时通知;会话关闭时仍未完成的咨询会记录为 cancelled_at_close。
  • 团队成员在 Agent 发起的线程中发帖后,会永久接管该线程——该线程不再自动唤回 AI,后续对该线程发起的咨询会收到固定通知:“已由团队接管”。
  • v1 中仅通过 CI/YAML 配置,与 delegate_to_hub 一样。

完整参数和 YAML 格式:references/agents/native-tools.md。

看板与状态

看板状态是对话的工作流阶段(显示在支持/任务视图中),在每个 hub 的 hub.yaml 中定义:

  • 标识:不可变的小写 slug(存储在对话、分析数据和工具参数中;永远不能重命名)+ 可自由编辑的显示 name。工具只接受 slug(显示名称会作为标签一并传递)——指令必须通过 slug 引用状态
  • 行为标志:isInitialStatus(每个 hub 必须且只能有一个)、triggersAgentResponse(状态转换会触发一轮 Agent 响应)、allowsAgentUpdate、isTerminalStatus(进入该状态会关闭对话;每个 hub 至多一个)、isSchedulingStatus(以及 eventName)。某些组合互斥——每次写入时都会在服务端验证
  • allowed_next_statuses — 可选的状态转换允许列表,在运行时的所有界面上强制执行,但有两种例外:非 Agent 调用方进入终止状态(REST 界面,无论是看板还是程序化调用;Agent 仍受限制),以及对已处于终止状态但仍未关闭的对话执行重新关闭——任何非 Agent REST 调用方均可执行,包括程序化调用;但 Agent 只有在复用已存储的结果、该状态未声明任何结果,或其所选结果不受限制时才能执行。省略 = 不受限制;拒绝 [](请使用 isTerminalStatus)
  • 结果 — 只有终止状态可以声明 outcomes: [{slug, name, color?, from_statuses?}](关闭处置结果,例如已解决/已取消)。from_statuses 是非空的来源 slug 允许列表;省略表示接受来自任何来源的结果。真正的看板终止状态转换必须有符合条件的结果,并会将其 slug 存储为分析数据,路径为 data.meta.outcome。Agent 关闭操作(close_conversation、harness end_conversation)会通过该转换处理,并受相同限制。团队关闭按钮(网页端和移动端)也会通过该转换处理,并先询问结果;但作为非 Agent 调用方,它仍适用上述 allowed_next_statuses 的终止状态例外;如果当前对话状态没有符合条件的结果,则会改为直接关闭,以免对话无法关闭。闲置自动关闭和 POST /:id/close 不使用结果
  • 后续跟进 — 每个状态可配置定时消息:inactivity(静默一段时间后)、before_event(活动开始前的倒计时)、inactivity_after_event(访问后的跟进——第一步从活动时间开始计时,之后每一步从上一次提醒开始计时),或 inactivity_after_before_event(相同的跟进方式,但从某个特定的 before_event 触发时开始,由 after_followup_id 指定)。后三种要求设置 isSchedulingStatus;只有对话中包含 scheduled_event_date 才会启用这些跟进,该字段须在状态转换时提供,不能在状态配置中提供。支持阈值/时间单位、静默时段和排除节假日
  • 状态转换时的附加上下文 — triggersAgentResponse 状态可以声明 additional_context_schema(团队在状态转换时填写的 JSON-Schema 格式)+ additional_instructions(包含 {{path.to.field}} / {{additional_data}} 占位符的文本模板,会注入触发的轮次)
  • 泳道 — 可选的看板展示分组;不影响行为

完整的字段规范、约束矩阵、警告和示例:references/kanban.md。

状态数据是 Agent 在对话期间读写的 JSON Schema 数据——通过原生工具(get_state、update_state、set_state_path、reset_state,均通过其 slug 指定状态)以及 {{state(scope, slug)}} 指令占位符访问。每个状态都有 conversation 或 user 范围、一个 json_schema,以及可选的 initial_value(预填充的虚拟记录,会一直显示到首次实际写入;省略则在写入前保持静默)。

**看板与状态数据:**看板用于追踪工作流进度;状态数据用于追踪结构化数据。两者可以共存。Schema 和模式:references/states.md。

技能

附加到 Agent 的技能。内容以真实文件的形式存放在 skills/<skill_name>/ 下(对于技能内容,文件系统是事实来源);hub.yaml 中的 skills: 只声明名称、skill_name 和描述。

类型内容运行时行为
skill版本化能力包——SKILL.md(frontmatter 中包含 name + description)+ 可选的 references/Agent 通过 skills/<skill_name>/… 读取其文件(list_files、read_file、{{file_content(skills/…)}});在 Agent 操作的任何文本(指令、设置、监控备注、自动化、看板后续事项、自定义工具、技能描述)中,凡是在 resources/ 下引用的技能,保存和推送时都会被拒绝。以可调用工具的形式注入(默认,适用于所有提供商),或在提供商容器中原生运行(use_native_integration: true,仅支持 Anthropic/OpenAI;在 wayai push 时自动同步到提供商,连接失败或较晚添加连接后可通过 wayai sync-skills 重新同步)

知识资源已停用:文档(常见问题、目录、政策)存放在组织的知识库中,Agent 通过 Base Toolset 连接读取 data/<file type>/… 下的内容(知识库)。技能不需要 type。

Agent 在 agents/<slug>.yaml 的 skills: 块中关联技能(按名称和 skill_id,并指定 priority)。跨 Hub 共享的组织级技能存放在 wayai-ws/org/(skills.yaml + skills/<skill_name>/),通过 wayai org pull/push 管理(推送会分发到已关联的 Hub)。推送采用声明式方式:从 hub.yaml 中移除某项技能(包括最后一项)会将其删除。

在技能之前拉取的文件夹包含 resources:(位于 hub.yaml 和 Agent 文件中)以及 resources/ 文件夹(组织级配置为 org/resources.yaml)。wayai push、diff 和 publish(以及 org push/org diff)会在发送任何内容前拒绝处理这些文件夹;wayai pull(wayai org pull)会转换它们,并在遇到 resources/ 中不是其写入的技能文件夹或不在其 skills/ 中的内容时停止并指出该内容(知识备份:请将其移出工作区)。这需要 @wayai/cli 0.3.234 或更高版本(wayai update):较旧 CLI 推送旧布局文件夹时会被拒绝,并返回指出该文件夹的 400;推送已转换的文件夹时不会更改任何技能;对旧布局文件夹执行 wayai pull 时,在比较阶段会遇到相同的 400,无法列出变更(请在拉取前更新);执行 wayai org pull/push/diff 和 sync-skills 时会收到 404(旧路径已不存在)。详情:references/skills.md。

文件处理(文本与二进制、10 MB 上限)、技能编写和执行模式:references/skills.md。

Base(数据层)

Base 是组织级的数据容器,是各个 Hub 背后的事实来源。Hub 保存对话;Base 保存这些对话所作用的结构化数据。使用相同的 CLI、相同的登录和相同的工作区;Base 是独立实体,有自己的子树和 promote 命令。

  • **基本元素:**记录类型 → 记录、关系类型 → 关系、文件类型 → 文件,此外还有 Actions 和 toolset(Agent 调用的精选 MCP 工具)、触发器和入站 Webhook(接收和发送变更)、外部数据源(通过外部 API 为记录类型提供数据),以及种子测试数据(隔离的评估数据)
  • **唯一规则:**配置写入(记录类型、关系类型、文件类型、触发器、入站 Webhook、Actions、toolset、种子数据)只能写入 preview Base;数据写入则在任何 Base 上都可用。晋升由人工执行——运行 wayai bases promote <prod> --from <preview> --dry-run,然后等待
  • **ID 不可变。**Base、记录类型、关系类型、Action 或 toolset 的 id 就是其标识;不能重命名,只能新建并迁移。请预先选择稳定的小写 slug
  • 工作区:wayai-ws/bases/<base>/(包含 base.yaml 和每个实体对应的文件),通过 wayai pull bases/<base> / wayai push bases/<base> 操作。如果 pull / push 同时指定 hubs/ 和 bases/ 中的目标,将被拒绝,绝不合并
  • 命令:wayai bases,以及顶层的 records、record-types、relationships、relationship-types、query-relationships、files、file-types、attachments、toolsets、actions、triggers、inbound-webhooks、seed(每个命令都接受 --base),以及 wayai bases tokens|secrets|sql|import|batch|providers
  • **连接 Hub:**通过 Base Toolset 连接,原生 Agent 可使用 toolset 中的工具,并可在 list_files 和 read_file 中访问其位于 data/<file-type>/ 下的文档;使用 write_file 和 edit_file 写入文档(references/connections.md);由 harness 支持的 Agent 使用指向该 toolset 的普通 MCP Server 连接(不带 get_url 或 put_url 的连接: URL tools and hub agents);评估则指定 target_base:。组织的文档存放在这里,也就是其知识库(references/bases/files.md);技能仍保留在 Hub 中(技能)

在进行任何 Base 操作前,请先阅读 references/bases/README.md——其中包含完整的对象模型,并指向下面各领域对应的文件。本节内容不足以用于编写架构。

评测

运行真实 Agent 及其真实工具并为结果评分的测试场景。基本要素:

  • 场景(evals/<name>.yaml 或 evals/<set>/<name>.yaml)——可选的多轮 history、一条 input、一个 expected 响应(文本和/或 tool_calls),以及可选的 evaluator_instructions。由 hub 的 message_evaluator Agent 评分;如果某个必需的工具调用被跳过,即使回复文本看起来没问题,评测也会失败
  • 场景集——第一级子文件夹(仅一层)。wayai run-eval 每个会话恰好运行一个场景集,可以运行整个场景集,也可以通过可重复使用的 --eval 缩小到选定场景(并通过 --runs 指定选定场景的运行次数)——当改动只涉及大型场景集中的少数场景时,这是成本较低的循环
  • 历程(journeys/<slug>.yaml,平铺文件夹)——保存的成功路径对话记录,每个 Agent 回合都会生成一个衍生评测。构建广泛回归覆盖的默认方式:wayai eval journey capture <conversation_id>,然后运行 wayai pull(同步服务器生成的步骤 ID)
  • 每次运行的 variables + runs: N——可靠性是一种分布,而非单次 1/1 样本;每次运行都会根据各自独立的行解析 {{var(name)}}
  • 种子 fixture:——适用于任何会执行写入的评测:指定一个基础设施 fixture,平台会在会话期间租用该 fixture——获取时重置,释放时清理——让每次运行都从已知的基线开始,而不是沿用上一次运行的残留状态。一个预览基础设施一次只允许一个评测会话:第二次启动会以 fixture_target_in_use(409)被拒绝,而不会获准破坏第一个会话;默认情况下,run-eval 会等待此情况解除——对于 fixture_seed_unavailable(409)也会如此,此时基础设施因自身写入背压而暂时拒绝租用
  • 种子 initial_state:——在运行 input 之前,预先填充用户范围的 WayAI 状态(例如回头客记录、已保存的个人资料),以便测试依赖过往对话记忆的行为;与 fixture: 一样,每个会话相互隔离,并在会话结束后清理
  • 指定客户 customer_contact_id:——指定场景的各次运行或历程的各个步骤所服务的联系人,让客户范围的工具集在评测中仅读取该客户的记录;仅在预览 hub 上受支持(references/evals.md)
  • 捕获——wayai eval capture <conversation_id> 会将生产环境对话的最后一轮冻结为场景 YAML
  • 呼叫评测(语音通话)——wayai run-eval --call-mode 和 wayai eval call:references/evals.md

工具依赖型评测的良好实践:组合使用历程 + fixture: + variables,以便重复运行和并行运行;将 evaluator_instructions 表述为功能结果,而非原始调用次数(“成功预订一次”,而非“恰好调用一次 book_appointment”)——工具可能会暂时失败,而正确的 Agent 会重试。完整的 YAML 格式、种子连接设置、运行间隔,以及编写和解读原则:references/evals.md。

自动化

自动化会自行在中心启动工作:包含一个 触发器(schedule — 5 字段 cron 表达式 + 时区;在任务中心上也可以是 event — conversation.flagged 或 conversation.closed,每个事件创建一个任务,并将对话作为带围栏的数据交给任务;不会触发自动化自身的任务;且最多嵌套三层,避免自动化循环:references/automations.md — 属于此中心,或通过 source_hub 指定组织中的另一个生产中心,仅限生产环境,且其发布者必须能读取该中心的对话:references/automations.md — 或 webhook — 外部系统向自动化专属 URL 发送的签名请求:references/automations.md)、一个 目标(contact_list — 通过 list 指定的中心自有列表,或通过 org_list 指定的组织列表;在任务中心上也可以是 none),以及针对触发器触达的每个联系人的一个 操作:

  • send_message(仅限聊天中心)— 在 whatsapp 上发送 WhatsApp 消息模板,在 email 上发送 text 邮件(使用其连接;营销邮件会附带退订链接),或在 app 上发送 text
  • run_agent — 一个 agent(pilot 或 pilot_specialist)和由管理员编写的 instructions。在聊天中心上,针对某个 channel(whatsapp / instagram / email / app;除 app 外,每个渠道都需指定连接;whatsapp 还需指定一个已获批准的模板,用于开启已关闭 24 小时窗口的对话):指定的 Agent 会在每个联系人的该渠道专属对话中,按照说明执行一轮并在对话中回复。在任务中心上,这是唯一可保存的操作,且不指定渠道:每次运行都会创建任务,每次运行一个任务(target: { type: none })或每个联系人一个任务;每个任务都没有关联人员,由指定的 Agent(pilot 或 pilot_specialist)按说明执行;联系人的记录会作为带围栏的数据传递给任务,不会放入说明中。references/automations.md
  • instructions 会按原文发送:其中的 {{…}} 占位符不会被填充(但它们在 Agent 自身的说明中有效)
  • Webhook 触发器(仅限任务中心):trigger: { type: webhook, auth: hmac } — 每次请求都按基础的入站 webhook 签名方式签名(X-Data-Signature / -Timestamp / -Id,因此发布的 SDK 的 signRequest 可以为其签名);也可以使用 auth: static_header,并通过 header 指定承载密钥的标头。每个获接受的请求都会创建一个任务,任务开头包含请求正文,并将其作为带围栏的数据置于说明之外。创建自动化时(通过应用或 API,在生产环境中由中心管理员操作)以及每次轮换时,密钥只会显示一次;推送或发布不会创建密钥。references/automations.md

联系人和组织列表是组织数据,而非中心配置:它们存放在组织的联系人簿中,由组织设置(Contacts 标签页)和组织 API(/api/contact-book)管理,绝不会放在 hub.yaml 中。自动化可以指定一个组织列表 — target: { type: contact_list, org_list: <list-name> } — 或一个中心自有列表 — target: { type: contact_list, list: <list-name> },这是联系人簿标签和范围标签的筛选条件,保存在 hub.yaml 的 contact_lists: 下 — 每次触发都会触达该列表中触发中心可见的成员。组织管理员,或持有覆盖整个组织的 contacts:write 权限的令牌,可以管理联系人簿;中心管理员可以查看其中心可见的联系人。联系人的可见范围(创建/导入时选择其范围标签或所有中心,并选择环境:默认为 production,因此预览中心只能看到 preview 和 all 联系人)、组织列表和 CSV 导入:references/automations.md。

  • **缺失与空值:**没有 automations:(或 contact_lists:)键时不会更改任何内容;[] 会删除所有自动化(或 Hub 列表)。自动化所指向的 Hub 列表永远不会被删除;重命名列表时,也会重命名自动化中的引用(除非另一个列表占用了旧名称)。不再读取旧的 outbound_schedules: 键,以及被联系人簿取代的 Hub 联系人和列表区块
  • 保存时绝不会查找组织列表(Hub list 除外:它必须是 Hub 中的某个列表):可以删除或重命名自动化所指定的组织列表;下次触发时会记录 list_not_found 并发出 Hub 警报。每次运行都会一次读取 100 个联系人的列表页面,因此联系人簿所容纳的任意大小的列表都能遍历到,每个联系人最多一次;运行会在联系人的页面加载到时显示这些联系人,暂停后会在下一页开始前停止
  • **抑制规则:**联系人簿会保存要求不接收自动化消息的对象——电话号码、电子邮件或 Instagram ID,范围为 marketing 或 all;即使删除联系人,这些记录也会保留。每项自动化的 purpose(默认为 marketing,或 operational)决定会应用哪些抑制规则:营销消息会跳过这两种范围,运营消息(如提醒)只会跳过 all。管理员可在 Contacts 标签页或通过 API 添加和移除抑制规则;电子邮件的退订链接会写入 all,而 WhatsApp 因对方停止接收营销消息而拒绝发送营销消息时,会写入 marketing。references/automations.md
  • **触发时会触达哪些人:**Hub 屏蔽的联系人永远不会收到消息;联系人簿中的联系人条目会在 Hub 要求新联系人先获得许可时为其授权,因此不会发起访问请求,且其回复会发送给 Agent(如果其请求已在等待审批,则会获批并继续由团队管理;run_agent 会跳过团队管理的对话);在应用中,只有已关联 WayAI 账户且该账户已获得 Hub 访问权限的联系人会收到消息——自动化绝不会授予访问权限
  • 在启用、未暂停且可运行时运行:hub.yaml 中的 enabled:(或应用中的切换开关)会启用自动化——定时计划的下一次运行会进入队列,事件自动化会在事件发生时运行,Webhook 自动化会接受投递——预览和生产 Hub 均如此,但带有 source_hub 的事件自动化只会在生产环境中运行;在应用中暂停会停止自动化,发布会保留生产环境中的暂停状态。除暂停、恢复、立即运行和 Webhook 自动化的密钥轮换(由 Hub 管理员执行)外,只有通过发布才能更改生产环境。立即运行会触发一次
  • **门控:**可选的 gate: { monitor: <agent name> }——基于决策模型的监视器会在每次运行开始前决定(trigger: automation_fire):运行、改用另一个 Agent 运行,或跳过;如果目标是联系人列表,则会在开始处理每位联系人之前逐一决定(trigger: automation_item):开始、改用另一个 Agent 开始,或跳过;门控失败或超时,则不会运行其所控制的内容。references/automations.md
  • **保存时拒绝并指出自动化名称的情况:**未知键、操作不使用的字段(例如任务 Hub 中的 channel 或 connection)、聊天 Hub 中的 none 目标、聊天 Hub 中的事件触发器或带列表目标的事件触发器、聊天 Hub 中的 Webhook 触发器、监视器不是决策模型上的 automation_fire 监视器(或联系人列表目标下的 automation_item 监视器)的门控,以及 Instagram 上的 send_message(目前不可用)

Instagram 只能触达过去 24 小时内发过消息的联系人——承诺结果前,请检查每次触发会执行什么。结构、示例、参考资料、每次触发的行为、消息模板和限制:references/automations.md。

分析

每段对话都会连同来自五种来源的变量写入分析存储:

来源路径设置方
系统指标data.system.*平台 — 消息数、响应时间、时长、令牌(约 25 项指标)
Agent 定义的变量data.variables.*conversation_evaluator / message_evaluator Agent 中声明的 evaluation_variables
元数据data.meta.*平台 — subject、kanban_status、hub_type
事后标注data.annotations.*wayai conversations <id> annotate --set key=value — 对话结束后记录实际业务结果(已购买、已流失);用于对照预测与实际情况
评估分数data.eval_scores.*仅评估运行(is_eval = true 的行 — 不纳入生产分析)

对话行是一个数据粒度;第二张表 message 会将每段对话的开销拆分到各条消息(令牌、美元成本、操作),以便按模型、Agent 和凭证分析成本。

可使用 wayai analytics(汇总和各变量聚合;--metric、--filter、--period)、wayai analytics query(结构化查询:多变量、group_by、相关性)、wayai analytics sql(对 conversation 和 message 执行原始 SQL — 成本分析入口),或 wayai evals sql(对评估行执行相同的 SQL)。如何定义优质变量,参见评估 Agent(roles-and-settings.md → Evaluation Variables);筛选、聚合、成本查询和工作流,参见:references/analytics.md。

团队、用户与访问权限

人员实体由 UI 管理(Hub → Users 选项卡:/settings/organizations/<orgId>/hubs/<hubId>/users),不在 YAML 中配置:

  • Hub User — AI 对话的最终用户(客户/潜在客户/员工)。使用 /chat(移动应用中的 Chat 选项卡);他们可在其中执行的操作:references/using-the-app.md
  • Hub Team User — 在 /support 中处理对话的支持团队成员(收件箱、认领、转接、关闭、看板:references/support-inbox.md);成员归入 Teams(例如 “Tier 2 Support”),transfer_to_team 按名称指定目标团队 — 未知的 target 会在运行时失败
  • Hub Admin — 拥有完整的 Hub 配置访问权限。Org Owner/Admin — 组织级别的管理权限(计费、凭证、Hub)。访问权限按级别区分,不会继承(组织管理员不会自动成为 Hub 管理员)
  • 联系人访问控制 — 当 non_app_permission: require_permission 时,未知渠道的联系人会处于 pending 状态(收到本地化自动回复,可通过 access_request_message 覆盖),直到由 access_approval_role 中指定角色的成员批准或屏蔽

Hub 环境

环境描述
preview默认环境。可编辑的工作区,用于配置和测试
production只读。承载线上流量。更改通过发布/同步从 preview 流转而来

生命周期:

  1. 新建 hub 时会以 preview 环境启动,可自由编辑。创建时,wayai create --label <l>(或自动创建时使用 wayai push --label <l>)会为首个 preview 命名。仅当 API 令牌的授权范围涵盖该组织在 preview 环境中的每个 hub 的 hub:write 权限时,才会创建 hub;否则返回 403。创建 hub 时,wayai create / wayai push 不会发送任何标签,因此受标签限制的令牌无法通过 CLI 创建 hub——请使用组织范围的令牌或 UI
  2. 发布(CLI wayai publish,或 UI)——首次晋级会从 preview 克隆并创建一个 production hub
  3. 同步(CLI wayai publish / 别名 wayai sync,或 UI)——将后续的 preview 更改推送到关联的 production。该命令会自动检测是首次发布还是同步;默认会先确认(显示 preview→production 差异),使用 -y 可跳过提示。它会晋级已推送的 preview 状态,因此请先执行 wayai push
  4. 复制 Preview(CLI wayai replicate [hub] --label <l> 或 UI)——从 preview 或 production 创建一个新的同级 preview,用于实验
  5. 重新标记(CLI wayai relabel <label> / --clear,或 UI)——设置/清除 preview 的 preview_label(用于区分同级项)。不能通过 hub.yaml + push 编辑——它由服务端管理

Production 为只读——所有配置变更都通过 preview 流转。多个 preview 可以关联同一个 production(多对一)。仅在 production 上强制频道唯一性——preview 可以与其 production 共享电话/电子邮件/SID。

发布和同步会写入 production hub,因此 API 令牌(wayai login --token)只有在其授权范围涵盖该 hub 的 hub:write 权限时才能发布。preview 发布后,wayai publish 首先会读取该 hub,以显示 preview→production 差异,因此令牌还需要该 hub 的 hub:read 权限。仅限 preview(按 hub 限制或限制到 preview 环境)的令牌会被拒绝,并返回 403。首次发布会创建 production hub,因此令牌需要访问该组织在 production 中的每个 hub(如果令牌受标签限制,还需要访问 preview 的标签)。已登录用户仍按原方式发布。

WhatsApp/Instagram/Telegram 频道可以在发布前于 preview 上测试——使用 #test CODE 认领码注册测试者(参见 references/connections.md → Channel → “Testing a channel on a preview before publishing”)。

只有 preview hub 可以编辑。wayai pull 也会将关联的 production hub 写入一个只读镜像文件夹(使用纯 slug 名称——不带 --<label> 后缀——并在 hub.yaml 中添加标记注释),以便在 preview 旁浏览线上 production 配置;wayai push 会拒绝该文件夹,且自动选择时会将其排除。使用 wayai diff --production 可查看简洁的 preview 与 production 差异。

Hub 设置

设置值默认值描述
non_app_permissioneveryone、require_permission、not_allowedeveryone谁可以通过外部渠道访问 Hub
timezoneIANA 时区—用于安排时间和显示
languageen、pt、esenHub 发送的文本所用语言(例如,使用 require_permission 的渠道发送的待审批访问通知)
access_approval_roleadmin、teamadmin谁可以批准或屏蔽待处理联系人:仅限 Hub 管理员,或也包括支持团队成员
access_request_message字符串—可选,用于覆盖“您的访问正在等待审批”自动回复的文本(否则会根据 language 使用本地化默认文本)
display_namesen / pt / es → 字符串(≤120 个字符)的映射—按应用语言设置 Hub 终端用户看到的名称。团队和管理员视图仍显示 name
welcome_messagesen / pt / es → 字符串(≤1000 个字符)的映射—按应用语言设置终端用户发送首条消息前看到的问候语
starter_questionsen / pt / es → 最多包含 4 个字符串(每个 ≤120 个字符)的列表的映射—按应用语言设置终端用户可点击发送的推荐首条消息
auto_close_inactive_days1–1807无活动(用户或团队未发送消息)的天数,超过后对话将被强制关闭。每个 Hub 都有此设置
conversation_retention_days1–307已结束对话的 DO 在清理前保持可用于事后 annotate 的天数,以及评估调用页面(evals.md → 调用评估)的保留天数(归档仍在关闭时进行)
ended_index_retention_days1–730365已结束对话在 Hub 索引中保留的天数。此值决定“已结束”选项卡的范围,以及 {{previous_conversations(N)}} 能追溯的时间范围
eval_retention_days0–3650,或 null平台默认值(90)已完成的评估会话(其运行记录、结果和评估对话)在弃用前保留的天数。0 表示永久保留会话。省略此字段会保留当前值不变 — 写入 eval_retention_days: null 可清除覆盖值并恢复平台默认值。弃用会永久删除转录记录 — Analytics 中的评估分数仍会保留
end_user_daily_message_limit1–10000,或 null不限终端用户在 24 小时内可通过 WayAI 应用向 Hub 发送的消息数上限,计时从其首条计入的消息开始。超过上限后,直到计时窗口结束前,其消息都会被拒绝,应用也会告知原因。仅统计终端用户 — 不统计团队消息、组织成员或 Hub 管理员的消息。其他渠道不受限制。省略此字段会保留当前值不变;设为 null 可移除限制

终端用户展示(display_names、welcome_messages、starter_questions):每位查看者会看到与其应用语言对应的条目;若没有,则使用 Hub 的 language;再没有,则使用映射中任意语言的条目。因此,请为终端用户使用的每种语言都设置内容,否则缺失的语言会显示其他语言的条目;仅当 display_names 为空时,名称才会回退为 name。不接受 en、pt 和 es 以外的区域设置。省略映射会保留其不变;null 或 {} 会清除映射。这些设置只会更改终端用户在应用中看到的内容:它们不会翻译 Agent 的指令、name 和 ai_* 通知。Web 和移动应用会在终端用户的聊天列表(搜索可找到任一名称)和对话线程标题中显示名称,并在尚无消息的对话线程中显示欢迎语和推荐问题;点击问题会将其作为首条消息发送。支持、Kanban 以及所有团队或管理员视图仍显示 name。Hub 管理员也可以在 Web 应用的 Hub 设置中按语言编辑这三项内容(概览 → 终端用户展示)。

首次设置(冷启动)

用户的入口是 wayai.pro,其引导部分提供安装命令和示例提示词。技能加载后(此处),本节将引导完成从“技能已加载”到“中心已能响应测试消息”的所有步骤。Agent 必须仅根据本节自行完成初始化——回访用户(第二个中心、新项目)可跳过此页面。

始终先运行 wayai status --json。 它会返回单个状态快照。根据结果选择后续步骤;每完成一步都重新运行以确认进度,再继续下一步(幂等)。

表述模板(逐字使用)
  • Agent 操作 — 先用一行说明,再执行,然后用一行确认:
    • “正在安装 CLI……” → 运行命令 → “完成 — 已安装 wayai 2.4.1。”
  • 交接给用户 — 恰好一个 URL、一个操作、一条返回信号:
    • “打开 <URL>。执行<一个操作>。完成后告诉我。”
状态机
#检测条件(来自 status --json 或环境变量)操作
1缺少 CLI(未找到 wayai --version)Agent 运行 npm i -g @wayai/cli@latest。
1b项目根目录下没有安装任何 harness 技能(<root>/.claude/skills/wayai/SKILL.md、<root>/.opencode/skills/wayai/SKILL.md、<root>/.agents/skills/wayai/SKILL.md 均不存在,其中 <root> 是 git rev-parse --show-toplevel 的结果;若当前目录不在 git 仓库中,则为当前工作目录)如果你是 Claude Code,请先运行 mkdir -p <root>/.claude——只有 .claude/ 已存在时,skills 安装程序才会为 Claude Code 创建 .claude/skills/wayai 链接;否则会跳过且不作提示,但仍会打印 "symlinked: Claude Code"。然后从 <root> 运行 npx skills add wayai-pro/wayai-skill -y。完成后,验证你自己的 harness对应路径是否可解析(Claude Code → <root>/.claude/skills/wayai/SKILL.md,沿符号链接解析;其他 harness → <root>/.agents/skills/wayai/SKILL.md)。如果可解析,则退出(harness 会在下一轮加载技能)。如果不可解析,但 <root>/.agents/skills/wayai/SKILL.md 存在,则自行修复:运行 mkdir -p <root>/.claude/skills && ln -sfn ../../.agents/skills/wayai <root>/.claude/skills/wayai,然后再次验证。如果仍然没有,则显示安装错误并停止——不要静默退出(否则重新进入时会陷入循环)。
1cskill.installed: true,已设置 skill.latest,且 skill.latest 比 skill.version 新(CLI 的 nightly 检查会填充 skill.latest)Agent 从 <root> 运行 npx skills add wayai-pro/wayai-skill -y,就地更新安装,然后退出(更新后的技能会在下一轮加载)。如果安装失败,向用户显示错误,并继续使用现有技能。
2auth.logged_in: falseAgent 运行 wayai login(打开浏览器)。交接给用户:"打开刚才打开的页面。登录或注册。完成后告诉我。"
3auth.logged_in: true,orgs: []询问一次:"组织要叫什么名字?(通常是公司名称)"。然后 Agent 运行 wayai org create "<name>",并重新运行 status --json 以获取新组织。(仅当 CLI 创建失败时使用手动备用方式:打开 https://app.wayai.pro/settings/organizations/new。)
3bgit rev-parse --show-toplevel 失败(当前工作目录不在 git 仓库中)CLI 需要 git 来检测工作区。采取操作前,显示解析出的当前工作目录,并向用户确认——交接内容:"我将在 <cwd> 初始化 git 仓库。请确认,或选择其他文件夹。"这样可以避免意外在 ~ 或其他非预期目录中初始化仓库。确认后,Agent 在当前工作目录运行 git init。然后检查 git config --global user.name 和 git config --global user.email;如果任一为空,则向用户询问一次姓名和电子邮箱,并运行 git config --global user.name "<name>" / git config --global user.email "<email>"。引导流程不需要 GitHub 远程仓库——只有用户想要 GitOps/CI 工作流时,才在后续设置。
4workspace.scoped: false 且 repo_scope_blocker: nullAgent 运行 wayai init --org <active_org.id>——将组织绑定写入 wayai-ws/wayai.yaml,这是该仓库唯一提交的工作区清单文件。
4bworkspace.scoped: false 且已设置 repo_scope_blocker不要运行 wayai init——它会重写 wayai-ws/wayai.yaml,无法修复两个配置文件内容不一致的仓库。对于 kind: "conflict",告知用户两个组织 ID,并询问此仓库属于哪一个组织,然后删除或更正根目录下的 .wayai.yaml。对于 kind: "invalid",显示指定文件及其 detail,并请用户修复。之后重新运行 status --json。
5工作区已限定范围,但尚不清楚 hub 的目标交接给用户:"这个 hub 应该做什么?请描述目标、使用者以及主要用例。"
6所选提供方缺少 LLM 凭证交接给用户:"请在此处粘贴你的 OpenAI/Anthropic/Google API 密钥。"然后 Agent 运行 wayai create-credential --name <name> --type "Bearer Token" --stdin。
7hub 需要 OAuth 连接(WhatsApp / Instagram / MCP OAuth)执行 OAuth 连接交接(连接与凭证 → OAuth 连接交接):发送该连接器的完整路径连接深层链接,等待完成,然后运行 wayai pull -y。之后任何时候需要 OAuth 连接,也适用相同的交接方式,不仅限于此处。
8已满足前置条件阅读一次 references/canonical-example/README.md,了解端到端的连接配置;然后根据用户的描述生成 wayai-ws/hubs/<hub>/hub.yaml + agents/*.yaml + agents/*.md(各部分的具体格式参见下方对应领域的参考资料);接着运行 wayai create -y 创建并推送新 hub(如果工作区中只有这个新文件夹,wayai push -y 也会自动创建)。
9推送成功Agent 运行 wayai send-message "Hi" 并显示响应。交接给用户:"要优化、添加工具,还是发布?"
10用户确认发布Agent 运行 wayai publish——显示预览版→生产版的差异,然后确认(或运行 wayai publish -y 跳过提示)。首次发布会将预览版克隆为新的生产 hub;之后的运行会进行同步。仅限付费套餐——如果 CLI 报告发布需要付费套餐,则使用手动备用方式:打开下方的发布深层链接,在 UI 中升级并发布。
Deeplink(规范 URL — 绝不是面包屑)
状态URL
3(创建组织 — 手动备用方案)https://app.wayai.pro/settings/organizations/new
6(预填凭据)https://app.wayai.pro/settings/organizations/<org_id>/credentials?type=bearer&name=<key-name>&prefill=true
7(OAuth 连接)https://app.wayai.pro/settings/organizations/<org_id>/hubs/<hub_id>/connections?connector=<whatsapp|instagram|mcp-server>
10(发布 — 手动备用方案)https://app.wayai.pro/settings/organizations/<org_id>/hubs/<hub_id>/overview?action=publish
规则
  • 检测,不要假设 — 每个步骤都从全新的 wayai status --json 开始。
  • Agent 操作要提供一行回执;移交给用户时要提供一个 URL、一个操作和一个返回信号。
  • 绝不要编造上表之外的 URL。绝不要指示用户“前往 Settings → …”——始终使用 deeplink。其他 URL 请参阅 references/navigation.md。
  • 在 hub 范围界定期间(状态 5),一次只问一个问题:先目标,然后渠道,最后是 LLM 提供商。
  • 绝不要自动提交 onboarding 期间创建的任何内容——显示 git diff,并等待用户批准后再进行任何提交。

工作流

现有 hub
  1. 更新 CLI — wayai update(执行任何操作前始终运行;如果尚未安装 CLI,则使用 npm i -g @wayai/cli@latest 引导安装)
  2. 技能过时则更新 — 运行 wayai status --json;如果已设置 skill.latest 且其版本高于 skill.version,则运行 npx skills add wayai-pro/wayai-skill -y 并退出(刷新后的技能会在下一轮加载)。否则继续。(冷启动 onboarding 也会执行与状态机第 1c 行相同的检查。)
  3. 拉取 — wayai pull -y(从平台同步本地文件;捕获平台外的变更)
  4. 读取上下文 — 读取此 hub 的 wayai-ws/hubs/<hub>/AGENTS.md 说明(用途、决策、进行中的工作);如果还要处理某个 base,也要读取 wayai-ws/bases/<base>/AGENTS.md。能够读取 AGENTS.md 的运行环境(Claude Code、Codex、Cursor、OpenCode、Aider)会原生自动加载 AGENTS.md,但不要依赖这一点——请参阅Hub 文件夹记忆。顺便清理过时的根目录引导文件——请参阅移除旧的根目录 AGENTS.md
  5. 编辑 — 修改 hub.yaml、agents/*.yaml、agents/*.md
  6. 推送 — wayai push -y(应用到预览 hub;自动将服务器分配的 ID 拉取回来)
  7. 测试 — wayai send-message "Hello"
  8. 审查 — 运行 git diff,请用户确认。**绝不要自动提交。**由用户提交并推送到 main
  9. 上线 — 准备就绪后运行 wayai publish(或使用平台 UI):显示预览版→生产版差异并确认,然后首次发布(克隆预览版→新的生产 hub),或同步后续变更。先运行 push——它会提升已推送的预览状态,而不是尚未推送的本地编辑
新建 hub(从头开始)
  1. 凭据 — wayai create-credential --name "openai-key" --type "Bearer Token"(每个组织、每项凭据只需执行一次)
  2. 初始化 — wayai init(交互式)或 wayai init --org <uuid>
  3. 创建文件 — wayai-ws/hubs/<hub>/hub.yaml + agents/*.yaml + agents/*.md
  4. 创建 — wayai create -y 会创建 hub、非 OAuth 连接,并应用所有配置(自动绑定工作树)。如果工作区中有多个 hub 文件夹,则使用 create <folder>。(wayai push -y 在解析到单个新文件夹时也会自动创建;在多 hub 工作区中则需要 --hub,因此 create 是明确无歧义的动词。)
  5. 测试 — wayai send-message "Hello"

hub 创建后,按照现有 hub 工作流操作。

Hub 文件夹记忆

wayai-ws/hubs/<hub>/AGENTS.md 是此 hub 的专属记忆,用于记录配置文件(hub.yaml、agents/)无法涵盖的上下文信息:用途、关键决策及其原因、正在进行的工作、仅适用于此处的业务规则、术语和集成注意事项。每次处理与 hub 相关的任务时,都要先阅读此文件。如果文件夹中没有 AGENTS.md,wayai pull/push 会在确认文件不存在后创建一个占位文件。支持读取 AGENTS.md 的工具(Claude Code、Codex、Cursor、OpenCode、Aider)会在 Agent 的当前工作目录位于 hub 文件夹内时自动加载该文件;但 Claude Code 是否会这样做,取决于其版本、设置,以及该文件夹中或其上层的 CLAUDE.md 系列文件(Claude Code 文档)。因此不要依赖自动加载:如果 hub 的 AGENTS.md 尚未包含在已加载的指令中,请自行阅读。较早版本的 CLI 还会在旁边创建一个只有一行 @AGENTS.md 的 CLAUDE.md;它不会造成影响,请保留。

主动维护此文件:

  • 完成重大更改后(新增 Agent、新工具、更新业务规则),更新 AGENTS.md,让后续会话能继承这些上下文
  • 如果 hub 文件夹没有 AGENTS.md(或只有自动创建的占位文件),请根据已知信息补充内容,包括用途、当前 Agent 和近期决策,并请用户确认或补充
  • 重点记录决策背后的原因,以及此 hub 的独特之处。不要重述平台机制——这些内容由此技能记录
  • 可在 ## Build plan 部分记录商定的范围——使用这个准确的标题,其下可选填一行 Goal: <一句话>,然后添加 GitHub 任务列表项(- [ ] / - [x]),最多嵌套一层。控制在约 30 项以内;超过后,请拆分为多个阶段,并将已完成的阶段归档到列表上方的正文中。完成后及时勾选——只有推送后且已正常运行,任务才算完成,而不是 YAML 文件存在就算完成。与 AGENTS.md 的其他内容一样,此部分永远不会同步到平台
  • Bases 同样适用。 如果你也在处理一个 base,请将设置无法涵盖的上下文记录在 wayai-ws/bases/<base-id>/ 下 base 文件夹的 AGENTS.md 中(如果文件不存在,请创建)

超出部分移至 wayai-ws/hubs/<hub>/references/:

  • 当 AGENTS.md 超过约 200 行或开始混杂多个主题时,将更深入的内容拆分到 wayai-ws/hubs/<hub>/references/ 下的专门文件中
  • 示例:references/business-rules.md、references/integrations.md、references/glossary.md、references/<api-name>-spec.md、references/<persona>-tone.md
  • 保留 AGENTS.md 作为始终加载的入口,并简短指向每个参考文件,例如:“详细定价规则:references/pricing-rules.md”
  • hub 文件夹中的 references/ 不会同步到平台,仅用于提供 Agent 上下文,与 AGENTS.md 一样
弃用旧的根目录 AGENTS.md

旧版 CLI 会在仓库根目录生成 AGENTS.md(以及一个包含 @AGENTS.md 的 CLAUDE.md)作为会话引导:检查更新,然后加载此技能。现在已没有任何内容会写入或刷新它,因此其中的信息会冻结在生成它的版本,而实际流程却不断演进——如果副本仍然写着本技能已更改的安装命令或启动步骤,就会悄悄把你引向错误的流程。它的内容现在也完全多余:其中的所有内容都已在此说明。如果你在仍有该文件的仓库中工作,请首次工作时将其弃用——这仅针对仓库根目录;hub 和 base 文件夹中的 AGENTS.md 是记忆文件,必须保留。

识别方法:生成的文件标题为 # Working with WayAI,正文全部是“检查更新,然后加载 WayAI 技能”的引导,以及几行与用户沟通的说明——没有任何项目专属内容。(较旧版本的副本可能改为描述要安装和加载两个技能;WayAI 和 Data 两个界面已合并为此技能,因此那种副本就更加过时了。)然后:

首先,确认你是否是通过该文件找到这里的。 不同的运行环境有所不同,这决定了该采取什么操作:

  • 你从自己的技能目录加载技能(Claude Code → .claude/skills/,OpenCode → .opencode/skills/)→ 根目录文件对你不起作用。删除它;如果 CLAUDE.md 只是单行的 @AGENTS.md 引用文件,也一并删除。

  • 你会自动加载 AGENTS.md(Codex、Cursor、Aider)→ 根目录文件可能是指引你找到此技能的唯一线索,删除它会导致下次会话找不到入口。保留该文件并将过时的引导替换为指向此技能的说明,这样内容就不会冻结,同时也保留了跳转入口:

    # Working with WayAI
    
    Load the WayAI skill at the start of every session, before anything else:
    `.agents/skills/wayai/SKILL.md`. It holds the real instructions.
    

无论哪种情况,如果文件还包含你自己的笔记,都要保留——只替换或删除生成的引导部分。完全由你自己编写的根目录 AGENTS.md 并非 CLI 创建的;不要动它。

引导中原有的所有内容现在都在此技能中:更新规范见 Agent 指南,操作流程见 工作流 → 现有 hub。

常用 CLI 命令

wayai update            # Update CLI (run before any operation)
wayai login             # OAuth — or `wayai login --token` for headless/CI
wayai logout            # Sign out and clear stored credentials
wayai whoami            # Show the authenticated identity
wayai org create        # Create a new organization (you become its owner): `wayai org create "<name>"` [--region <r>] [--json]
wayai org pull          # Org-as-code: fetch org-level shared skills → wayai-ws/org/
wayai org push          # Org-as-code: apply local org skills to the platform (fans out to linked hubs); `wayai org diff` previews
wayai create-credential # Create org credential (--name, --type "API Key"|"Bearer Token"|"Basic Auth", --org, --stdin)
wayai update-credential # Rotate/edit an org credential (--name <cred>; --stdin/--secret rotates the secret, --rename, --description, --tag, --environment)
wayai set-connection-credential  # Set a connection's credential directly — --connection <name> + either --org-credential <name> (link) or --field <f> --stdin (raw secret: unlinks only that field's org credential). Works on preview + production (the sanctioned production-credential write)
wayai init              # Scope this repo to an org in wayai-ws/wayai.yaml (interactive — creates an org inline if you have none); --org <uuid> to skip prompt
wayai migrate           # Move a legacy workspace/ + root org/ layout to wayai-ws/, and copy a root .wayai.yaml org binding into wayai-ws/wayai.yaml (the root file is KEPT — older CLIs still need it)
wayai pull              # Pull hub config from platform (-y skips confirmation; auto-binds worktree on first pull). Also writes the linked production hub as a read-only mirror folder
wayai push              # Push local changes (-y skips confirmation; auto-pulls IDs back). Auto-creates a lone new folder; a multi-hub workspace needs --hub or `wayai create`
# `pull`/`push` are ONE verb each, routing by workspace subtree: `hubs/<hub>` (above), `bases/<base>` (the Data surface)
#   or `communities/<community>` (references/communities.md) — a community only by the flag, a positional or its folder as cwd.
# The target resolves in this order: the `--hub`/`--base`/`--community` flag → a positional → the folder you are cd'd into →
#   `wayai-ws/wayai.yaml`'s `default_hub`/`default_base` → the sole folder across the hubs and bases subtrees.
# So in a workspace holding BOTH a hub folder and a base folder, a bare `wayai pull` is refused as ambiguous.
# Name the subtree — `wayai pull bases/crm`, `wayai push hubs/support` — or declare ONE default in wayai-ws/wayai.yaml.
# An invocation naming a target in BOTH subtrees is refused, never merged; run the two it prints, one at a time.
wayai pull bases/<base> # Pull a base's config into wayai-ws/bases/<base>/ (-y skips the overwrite confirm; auto-binds; mirrors a production origin read-only)
wayai push bases/<base> # Push a base folder to its PREVIEW base (--dry-run to stop after the diff; --prune to apply removals). Production is `wayai bases promote`, never push
wayai create [folder]   # Explicitly create a new hub from an idless folder, then push (--label names the preview). The discoverable verb when a workspace has more than one hub folder
wayai diff              # Dry-run diff of local files vs preview (read-only); --production diffs vs the linked production hub
wayai replicate [hub]   # Clone a hub (preview or production) into a new sibling preview; --label <l> names it. Pulls the new preview into its own folder
wayai relabel <label>   # Set a preview hub's label (--clear removes it; --hub to target). Renames the local folder. The server-owned way to change preview_label
wayai publish           # Promote the preview to production (alias: wayai sync). Auto-detects first-publish (clones preview → new production) vs sync (pushes changes to the linked production); shows the preview→production diff and confirms (-y skips). Paid plans only. `wayai push` first — promotes the pushed preview state
wayai use <selector>    # Scope this worktree to a hub, base or community (UUID, folder name, hubs/<n>, bases/<n>, communities/<n>, --hub/--base/--community). Replaces that axis; `--add` widens it instead
wayai unbind [<sel>]    # Drop one entry from the worktree scope; bare, it clears the whole scope (every axis)
wayai send-message      # Test message to a hub (preview or production). -c <id> continues a conversation
                        # `-f, --file <path>` attaches a file (repeatable, max 20, ~7 MB/request) delivered exactly as a real channel does — this is how image/document behaviour gets exercised in the dev loop. Message text is optional when a file is attached (an attachment-only send mirrors a photo with no caption). Images reach the model as a signed URL, not base64
wayai alerts            # Active connection/credential alerts for a hub (Status & Notices). RUN THIS FIRST when a hub misbehaves (audio/TTS not delivered, agent not replying, a tool failing) — an invalid/expired provider key shows as `connection_auth` (usually 401) here instead of forcing a guess from code. --hub <uuid|name>, --json
wayai conversations     # List or inspect conversations (default text view omits message_id — use --json or `observability` to discover ids)
                        # `--status <agent|team|ended>` combines with `--period 7d` / `--from` / `--to`, which bound LAST ACTIVITY: `--status team --to <date>` is the idle human-queue check ("waiting on a person, nothing since <date>"). Without `--status` AND without `--org`/`--all`, a bare `--period`/`--from`/`--to` reads the analytics history instead, which bounds conversation START and covers ended conversations only
                        # `--org <organization_id>` / `--all` list across the hubs `wayai list` enumerates plus the production hubs those name as parents — one command instead of a loop. These always read the live listing (open + ended, windowed on LAST ACTIVITY), with or without `--status`. A production PARENT you cannot read is named as skipped and does not fail the run. A production hub whose PREVIEW you cannot see is not enumerable anywhere, so it is NOT covered and NOT reported at all — reach it with `--hub <id>`. `--limit`/`--offset` are per hub; a hub in scope that refuses is named and the command exits non-zero rather than reporting a smaller queue, and an empty scope is reported as such, never as an empty queue
                        # `wayai conversations <id> observability` — list LLM turns with message_id, latency, tool_calls (assistant turns only)
                        # `wayai conversations <id> observability --message-id <id>` — full record for one turn (prompt, completion, tool calls, tokens; --json for raw)
                        # `wayai conversations <id> annotate --set key=value [--type numeric|categorical|text]` — set a post-hoc business outcome (e.g. customer_purchased=true) on an ended conversation as an analytics dimension; repeat --set for multiple keys (needs the hub within its conversation_retention_days window)
wayai delete-history    # Clear conversation history (testing). Full history (no --conversation-id) ALSO clears the user's user-scoped hub state, so the next send-message is a true cold-open; --conversation-id <id> deletes just one conversation and never touches state
wayai sync-skills       # Sync skills to provider connections; --connection-id <uuid> to scope
wayai sync-mcp          # Re-discover an MCP or Base Toolset connection's tools (refresh stale schemas); --connection <name|uuid>; --check reports drift read-only (CI, exit 1 on drift)
wayai analytics         # Summary + per-variable aggregates; --metric, --filter, --period, --json
wayai analytics query   # Structured ClickHouse query (multi-variable, group_by, correlations)
wayai analytics sql     # Raw single-SELECT SQL over `conversation` (one row per conversation) and `message` (per-message tokens/cost/operations — the surface for cost analysis); --schema prints both catalogs + the message-grain rules (`data.*` paths need `toFloat64OrNull(toString(...))` for numerics, `toString(...)` for grouping); --limit, --json
wayai evals             # List eval scenarios for the hub (--enabled / --disabled)
wayai evals sql         # Raw single-SELECT SQL over the hub's eval result rows ("SELECT …"; --schema prints the column + eval-score-path catalog; --limit, --json)
wayai run-eval          # Run a scenario set's enabled evals (sole set by default; --set to pick on multi-set hubs; repeatable --eval <name> runs ONLY those scenarios and --runs 2,6 only those repetitions of one; --pacing conservative|balanced|fast|<ms> to throttle run dispatch; --call-mode runs every turn the way a live voice call runs it; waits inside --timeout for a fixture held by another session or for transient base write backpressure — --no-queue fails fast and --no-wait implies it; exits 1 if --timeout expires with the session still running)
wayai eval-results      # Inspect eval results (--session <id> or --eval <name>; --runs for per-run detail, --json for raw)
wayai eval capture      # Capture production conversation as eval YAML (<conversation_id> [--set <name>])
wayai eval journey capture  # Capture a conversation's FULL transcript as a journey (<conversation_id> [--name <n>]); then `wayai pull` to sync it to journeys/<slug>.yaml
wayai eval session stop     # Cancel a running eval session (<session_id>) — recovery when a run-eval died without cancelling its own session
wayai eval session delete   # Delete an eval session + its run history (<session_id>, or --all for every session on the hub; -y to skip confirm)
wayai eval call         # Place scored voice calls for a journey whose responder is the pilot_voice agent (--journey <name|id>, --runs, --clips <dir> or OPENAI_API_KEY, cost caps); needs `npm install -g @roamhq/[email protected]` once — see references/evals.md
# Journeys are hub-as-code: edit journeys/<slug>.yaml and `wayai push` (pull after first create to sync step ids)
wayai list              # List organizations and hubs
wayai communities       # An organization's communities (owners and admins; browser `wayai login` only): list, join-link get|rotate|off <community>, stats <community>, access list|add|remove <community> [<email>…] (an invite-only community's access list; remove takes out the members the email admitted); --org, --json, -y. See references/communities.md
wayai contacts          # A contact's customer record in a base (organization admins; browser `wayai login` only): link-customer <contact_id> --base <base_id> --record <record_id>, unlink-customer <contact_id> --base <base_id>; --org, --json. See references/bases/toolsets.md#linking-a-contact-to-its-customer-record
wayai pull communities/<community_id|folder>   # A community's settings, rules, join link state, rooms and courses as files (named explicitly, never by a bare pull); push applies them to the LIVE community (asks first; --dry-run, --theirs on pull)
wayai status            # Show workspace status
wayai report create     # Create platform bug report (--title, --description, --hub, --conversation, --error). With --hub, auto-attaches the hub's active alerts so triage sees a credential/connection cause up front — check `wayai alerts` yourself first, it's often not a platform bug
wayai report edit       # Amend your own pending report (<id> --title/--description/--error/--steps/--context)
wayai report list       # List your reports (newest first; --status <s>, --json)
wayai report get        # Show a report's status + message thread (<id>, --json)
wayai report accept     # Accept a shipped fix (<id>) → addressed
wayai report contest    # Contest a shipped fix or a dismissal (<id> --reason "...") → back to triage

# Bases — the Data surface. A base is org-level and a separate entity from a hub.
# `use`/`unbind` are local (this worktree's scope file) and DEPRECATED — prefer
# `wayai use bases/<id>` / `wayai unbind bases/<id>`; every other command below
# reaches the platform. Full grammar: references/bases/.
wayai bases list        # List bases (--tag to filter)
wayai bases get <id>    # Show one base
wayai bases create <id> --name "<name>"        # Create (--environment preview|production)
wayai bases update <id> --name/--tags/--timezone/--settings/--integrations
wayai bases rename <id> --name "<name>"        # Display name only — the id/slug is immutable
wayai bases tag <id> --tags a,b                # Replaces the existing tags; names must exist as organization tags
wayai bases delete <id>                        # Tombstone; --purge (preview only) destroys storage
wayai bases create-preview <origin-id> --name "<name>"   # Clone config into a new preview
wayai bases list-previews <origin-id>
wayai bases promote <production-id> --from <preview-id>  # NOT `wayai publish`, which promotes a HUB
wayai bases rollback <production-id> --promotion <id>
wayai bases promotions <production-id>
wayai bases use <base>  # Deprecated alias of `wayai use bases/<id>` (see Worktree scope)
wayai bases unbind      # Deprecated alias — clears only the base axis of the worktree scope
wayai bases tokens|secrets|sql|import|batch|providers ...   # namespaced — each names a concept WayAI already owns

# Everything INSIDE a base is its own top-level namespace, each taking --base <id>:
wayai records | record-types | relationships | relationship-types | query-relationships
wayai files | file-types | attachments | toolsets | actions | triggers | inbound-webhooks | seed
wayai files pull|push <file_type> --base <id> [--folder <path>]   # A file type's files as a local folder (knowledge as code). DATA, not config: writes any base, production included. Push shows the diff; a file changed, deleted or created on the base since your pull is a conflict, not written (a new file is sent create-only — references/bases/files.md)
wayai knowledge refresh-preview --org <id> --base <knowledge base>   # Copy the knowledge base's production files into its preview, after creating it and whenever it should be current again (references/bases/files.md)

wayai bases --help(以及 wayai <namespace> --help)会打印完整的命令树;上述所有命令的语法都在 references/bases/ 中。需要牢记的两个命令区别:wayai use/wayai unbind 会维护一个涵盖 hub、base 和社区的工作树作用域(由选择器决定具体对象——wayai use bases/crm 与 wayai use <hub-uuid>),因此 wayai bases use/wayai bases unbind 已弃用,是仅针对 base 轴的别名;而 wayai publish 用于发布 hub,wayai bases promote 用于发布 base。Hub 和 base 是不同的实体,绝不能互相替代。

跟进你提交的报告。 分类处理升级问题并发布修复后,你的报告会变为 shipped 状态——你会收到一封电子邮件,且 wayai login/wayai status 会提醒你一次(也可以通过 wayai report list --status shipped 查找)。查看 wayai report get <id>(状态和处理者在线程中的备注),然后如果有效就执行 accept,如果无效就执行 contest --reason "..."。如果你认为某个已 dismissed 的报告确实成立,也可以执行 contest——报告会重新进入分类处理流程。 异议次数有限(有次数上限,且分类处理人员可能会将驳回标记为最终结论);超过限制后,请联系支持团队。

大多数命令都支持 --hub <uuid|folder>,可在 wayai-ws/hubs/ 中有多个 hub 时消除歧义。

工作树范围

每个 Git 检出(主工作树或关联工作树)都有一个范围:一组中心、一组基础项和一组社区,保存在 <git-dir>/wayai-scope 文件中(每个检出各自独有,绝不纳入版本控制)。

hubs: [11111111-1111-1111-1111-111111111111]
bases: [crm, billing]
communities: [6b1e0000-0000-4000-8000-000000000001]

它是一个路由保险丝,不是并发锁(不会协调并发编辑),也不是授权机制(授权才是安全边界)。它也不会选择目标——只会拒绝目标。

如何填充。 各轴独立初始化:当某个轴的集合为空时,首次成功拉取、推送或创建会将其填充。之后该集合只会按需扩展:自动绑定不会向非空集合追加内容。

如何执行。 wayai pull、wayai push、wayai publish 和 wayai relabel 会拒绝针对非空 hubs 集合之外的中心运行;wayai pull bases/<base> 和 wayai push bases/<base> 会拒绝针对非空 bases 集合之外的基础项运行;wayai pull communities/<x> 和 wayai push communities/<x> 会拒绝针对非空 communities 集合之外的社区运行。在某个轴已有范围限制的检出中创建新中心或基础项,也会以同样方式被拒绝。

如何更改。

wayai use <selector>          # replace that axis with this one target
wayai use --add <selector>    # widen: add one target to that axis
wayai unbind <selector>       # drop one entry
wayai unbind                  # clear the whole scope, every axis

选择器的命名方式与 pull/push 相同:裸 UUID 表示中心,bases/<id> 和 --base <id> 表示基础项,hubs/<name> 和 --hub <x> 表示中心,communities/<folder|id> 和 --community <x> 表示社区;裸文件夹名称会在 hubs 和 bases 子树中查找(两处都存在时会被拒绝,不会猜测;绝不会作为社区处理)。wayai status 会显示当前范围;status --json 会通过 worktree_scope 字段携带该信息。

工作树合法地限定在多个实体范围内很正常——例如,一个基础项服务多个中心,或委派配置将中心 A 连接到中心 B。此类情况请用 --add 扩大范围;不要为了绕过限制而清除保险丝。

如果 push/pull 因范围限制而报错,请停止操作,并先询问用户。这通常意味着提示词原本是针对另一个工作树的。未经当前会话中的用户明确指示,不要运行 wayai unbind、wayai use(无论是否带 --add)、wayai bases unbind、wayai bases use,也不要编辑范围文件——扩大范围和清除范围限制一样,都是会话路由操作;两者都会改变用户认为你正在处理的中心、基础项或社区。

仓库结构

.wayai.yaml                              # DEPRECATED org binding — read as a fallback, never written.
                                         #   `wayai migrate` copies it into wayai-ws/wayai.yaml and
                                         #   KEEPS it (older CLIs still require it). Delete it only
                                         #   once every environment running this repo is current.
AGENTS.md / CLAUDE.md                    # STALE if present — an older CLI's root bootstrap; nothing
                                         #   writes or refreshes these now. Delete it, or (on a harness
                                         #   that auto-loads AGENTS.md) replace its body with a pointer
                                         #   to the skill — see "Retiring the old root AGENTS.md".
                                         #   Hub- and base-folder AGENTS.md are memory and are unaffected.
.claude/skills/wayai/                    # Claude Code skill install (provisioned by `npx skills add wayai-pro/wayai-skill -y`)
├── SKILL.md
└── references/                          # On-demand deep-dive references (see index below)
.opencode/skills/wayai/                  # OpenCode skill install (same provisioner; same SKILL.md + references/ layout)
.agents/skills/wayai/                    # Neutral skill install (same provisioner; same SKILL.md + references/ layout)
wayai-ws/                                # All WayAI config-as-code (init creates wayai-ws/hubs/)
├── wayai.yaml                           # Workspace manifest — the repo's ONE committed config file
│                                        #   `organization_id:` / `organization_name:` — which org this
│                                        #   repo is scoped to. Written by `wayai init`; required.
│                                        #   `default_hub:` / `default_base:` — OPTIONAL, which subtree a
│                                        #   bare `wayai pull`/`push` targets. Declare AT MOST ONE:
│                                        #   declaring both is a mixed invocation and is refused.
│                                        #   Write these two by hand — no command creates them.
│                                        #   `wayai init` keeps their VALUES when it rewrites the file,
│                                        #   but YAML comments in it are not preserved.
├── org/                                 # Org-as-code — shared skills (wayai org pull/push)
│   ├── skills.yaml
│   └── skills/<skill_name>/
├── communities/                         # One folder per community — `wayai pull communities/<community_id>`
│   └── <community-slug>/                #   (see references/communities.md; push edits the LIVE community)
│       ├── community.yaml               # Identity, settings, join link state, rooms, course folders in order — with ids and revs
│       ├── rules.md                     # The rules members see (Markdown); empty = none
│       └── courses/<course>/            # course.yaml (the course, its modules, each module's lessons in order)
│           └── lessons/<lesson>.md      #   and one file per lesson: its fields, then its text
├── bases/                               # One folder per preview base (Data surface) — `wayai pull bases/<base>`
│   └── <base-id>/
│       ├── base.yaml                    # Base identity; `wayai use bases/<folder>` reads it
│       ├── record-types/<id>.yaml       # One file per entity, per kind. Secrets are never written
│       ├── relationship-types/<id>.yaml
│       ├── file-types/<id>.yaml
│       ├── inbound-webhooks/<id>.yaml
│       ├── triggers/<id>.yaml
│       ├── toolsets/<id>.yaml
│       ├── actions/<id>.yaml
│       └── seeds/<id>.yaml
└── hubs/
    └── <hub-slug>--<label>/             # One folder per preview hub (disambiguated)
        ├── hub.yaml                     # Hub config + states + connections + automations + skills
        ├── agents/
        │   ├── <slug>.yaml              # Agent config (one per agent, slugified name)
        │   └── <slug>.md                # Agent instructions (one per agent)
        ├── evals/                       # Eval scenarios (synced)
        │   ├── <name>.yaml
        │   └── <set>/<name>.yaml
        ├── journeys/                    # Eval journeys (synced; flat folder, one file per journey)
        │   └── <slug>.yaml
        ├── attachments/                 # Eval/journey turn attachment files (synced; hub-root, shared by evals + journeys)
        ├── call-openings/               # Voice agents' own call opening audio (synced; `call_openings` in agents/<slug>.yaml)
        ├── skills/<skill_name>/         # Skill files (synced)
        ├── AGENTS.md                    # Hub-specific memory — scaffold seeded on pull/push (NOT synced; fill it in)
        └── references/                  # Hub-specific supporting files (NOT synced)
    └── <hub-slug>/                      # Linked production hub: READ-ONLY mirror (bare slug, no --label). Refreshed each pull; never pushed

预览中心文件夹使用 hub-slug--<preview_label> 或 hub-slug--<hub_id_prefix> 以便区分;关联的生产中心会映射到不带后缀的 hub-slug。仍使用旧版 workspace/ + 根目录 org/ 布局的现有仓库仍可正常工作(CLI 两种布局都能读取)——运行 wayai migrate 可迁移到 wayai-ws/。

hub.yaml 结构

version: 1
hub_id: "abc-123-def"           # set by `wayai pull` — do not edit
hub_environment: preview         # set by `wayai pull` — do not edit
preview_label: experiment-a      # server-owned, set by `wayai pull` — do not edit (only on previews; sets the hub folder's `--<label>` suffix). Editing here is IGNORED on push (push warns); change it with `wayai relabel <label>` / `--clear`, or set it at creation with `wayai create --label` / `wayai replicate --label` / `wayai push --label`

hub:
  name: Customer Support
  # description: Handles refunds, order status, and billing questions   # optional, human-facing
  hub_type: chat                 # chat | task
  ai_mode: pilot+copilot         # pilot | copilot | pilot+copilot | turned_off
  timezone: America/New_York
  non_app_permission: everyone
  # tags: [retail, vip]          # org tag slug names (create in UI first); gate which org credentials this hub can resolve. Omit to leave unchanged; [] clears; only an org admin may change them. See references/connections.md#organization-tags
  # auto_close_inactive_days: 7  # force-close a conversation after N days of inactivity (see Hub Settings)
  # conversation_retention_days: 7  # keep an ended conversation's DO alive N days for post-hoc `annotate` (see Hub Settings)
  # display_names: { en: Customer Support, pt: Atendimento ao Cliente, es: Atención al Cliente }   # end-user name per app language (see Hub Settings)
  # welcome_messages: { en: "Hi! How can I help?", pt: "Olá! Como posso ajudar?", es: "¡Hola! ¿Cómo puedo ayudar?" }
  # starter_questions: { en: ["Where is my order?"], pt: ["Onde está meu pedido?"], es: ["¿Dónde está mi pedido?"] }   # up to 4 per language
  # end_user_daily_message_limit: 50   # messages one end user may send in the app per 24 hours; null removes it (see Hub Settings)
  kanban_statuses:               # full field specs + constraints: references/kanban.md
    - slug: new
      name: New
      order: 0
      color: "#22c55e"
      isInitialStatus: true
      allowed_next_statuses: [in_progress, waiting_for_customer, resolved]
    - slug: in_progress
      name: In Progress
      order: 1
      color: "#3b82f6"
      triggersAgentResponse: true   # transition fires an agent turn; can carry additional_context_schema + additional_instructions (see references/kanban.md)
      allowed_next_statuses: [waiting_for_customer, resolved]
    - slug: waiting_for_customer
      name: Waiting for Customer
      order: 2
      color: "#f59e0b"
      allowed_next_statuses: [resolved]
      followups:
        - order: 0
          type: inactivity
          threshold: 30
          timeUnit: minutes
          instructions: "Hi! Just checking in — do you still need help?"
    - slug: resolved
      name: Resolved
      order: 3
      color: "#ef4444"
      isTerminalStatus: true         # at most one terminal status per hub
      outcomes:                      # terminal-transition policy; selected slug → data.meta.outcome
        - { slug: resolved, name: Resolved, color: "#22c55e", from_statuses: [in_progress, waiting_for_customer] }
        - { slug: canceled, name: Canceled, color: "#ef4444" }
        - { slug: abandoned, name: Abandoned, color: "#a0aec0" }

states:
  - id: "state-uuid-789"          # set by pull
    slug: order_tracking           # immutable identifier; auto-derived from name if omitted
    name: order_tracking
    scope: conversation            # conversation | user
    description: Tracks current order
    json_schema:
      type: object
      properties:
        order_id: { type: string }
        status: { type: string, enum: [pending, shipped, delivered] }
    initial_value: { status: pending }  # must validate against json_schema

connections:
  - name: anthropic
    type: Agent
    service: Anthropic
    # sync_credentials_to_production: true   # default; false keeps production's credential separate (set it via `wayai set-connection-credential`). See references/connections.md#credential-propagation-to-production-sync_credentials_to_production
  - name: my-api-connection
    type: Tool
    service: REST API
    base_url: https://api.example.com   # Its credential is only sent to this origin: required for custom tools while it holds one
  - name: elevenlabs-tts
    type: TTS
    service: ElevenLabs TTS
    settings:            # Per-connection params (voice/model/language, etc.); keys = connector_settings_schema. See references/connections.md
      voiceId: pNInz6obpgDQGcFmaJgB
      modelId: eleven_multilingual_v2

hub.yaml 还包含 skills:、automations: 和 contact_lists: 块。完整架构请参阅各领域的参考文档。

agents/<slug>.yaml 结构

id: "agent-uuid-123"               # set by pull
name: Pilot Agent
role: pilot
connection: anthropic              # connection display name
# instructions resolved by convention from agents/<slug>.md
# additional_context_template:     # per-turn context, emitted as an <additional_context> tag on the last user message (same {{...}} syntax as instructions). Put high-churn placeholders ({{now()}}, {{state()}}) HERE, not in instructions, to keep the system prompt cache-stable (see references/agents/instructions.md#additional-context-cache-friendly)
# response_format:                 # {schema_name, schema_json} — force structured JSON output instead of free text (see references/agents/roles-and-settings.md#response-format-structured-output)
# enabled: true                    # default; omitted
# include_message_timestamps: false  # default; when true, appends [timestamp, weekday, daypart] to user messages
# previous_conversations_count: 3  # off by default (max 20); this user's N most recent ended conversations, prepended to the FIRST user message and frozen at the first agent turn that uses it. Foreground roles only; `0` clears it (omitting the key on update leaves it as-is); summaries come from the conversation_evaluator (see references/agents/roles-and-settings.md#previous-conversations-context)
settings:
  model: claude-sonnet-5-5
  max_tokens: 4096
  # temperature (only sampling knob): Sonnet 5+ / Haiku 5.5 / Opus 4.7+ / Fable strip a non-default value — set it only on Opus 4.6 / Sonnet 4.6 & older
  # reasoning per provider: Anthropic thinking_enabled + effort · OpenAI/OpenRouter/xAI reasoning_effort · Gemini reasoning_level (see roles-and-settings.md)
  # file_handling_mode: no longer changes what the model receives (earlier files are always announced by path, never re-attached); metadata_only still auto-enables read_file. max_attachment_size_mb is inert (see roles-and-settings.md#file-handling-all-llm-connectors)
  # deliver_preamble: true           # default; pre-tool "let me check…" text is delivered as its own message (voice: own TTS clip; ignored on email). false = only the final reply (see roles-and-settings.md#pre-tool-preamble-delivery-all-llm-connectors)
  # copilot_trigger: every_message   # copilot-track only; on_demand suppresses the automatic per-message suggestion — the team pulls one via the "Suggest reply" button (cost/noise lever; see roles-and-settings.md)
tools:
  native:
    - update_kanban_status
    - get_state
    - update_state
  delegation:
    - type: agent
      tool: transfer_to_agent
      target: Specialist - Billing
    - type: team
      tool: transfer_to_team
      target: Tier 2 Support
    # Hub-as-agent: hand a self-contained request to ANOTHER hub in this org.
    # `target` is a PRODUCTION (published) hub name. context_boundary is required
    # reading — see "Hub delegation" below.
    - type: hub
      tool: delegate_to_hub
      target: Billing Hub
      context_boundary: summary   # instruction | summary | transcript
  custom:
    - name: check_order_status
      description: Check order status by email
      method: post
      path: /api/orders/status
      body_format: json
      connection: my-api-connection
      config:
        name: check_order_status
        description: Check order status by email
        parameters:
          type: object
          properties:
            email: { type: string, description: Customer email }
          required: [email]
skills:
  - name: Order Management         # links a hub skill by name (see Skills)
    skill_id: "skill-uuid"         # set by pull
    priority: 0

完整的 Agent 选项(每个连接器的设置、additional_context_template、response_format、文件处理、本机工具参数、自定义工具字段、composed_tools、占位符)请参阅 references/agents/。

评估变量——conversation_evaluator / message_evaluator Agent 会携带 evaluation_variables 列表(它们为每个对话/消息输出的结构化字段,这些字段会成为 Analytics 中的 data.variables.*),并通过 pull/push 保持往返一致。请参阅 references/agents/roles-and-settings.md。monitor 会在同一列表中声明其 flag_conditions 和 rules 所读取的字段;这些字段仅用于其条件,不会进入 Analytics(监控配置)。

关键规则

  • 只读字段: hub_id、hub_environment、id——由 wayai pull 设置,切勿编辑
  • 自动创建连接: hub.yaml 中的非 OAuth 连接会通过匹配 service + authentication_type 解析为组织凭据。如果多个组织凭据具有相同的认证类型,可使用 credential 字段消除歧义。OAuth 连接(WhatsApp、Instagram、MCP OAuth)必须预先创建(通过 UI 设置——参见 OAuth 连接交接)——只按名称引用
  • 生产凭据: 默认情况下,发布/同步时连接会将其凭据复制到生产环境。设置 sync_credentials_to_production: false 可让生产环境使用独立凭据,然后通过 wayai set-connection-credential 直接设置(其他情况下生产环境为只读)。无论标志如何设置,基础工具集连接的令牌都不会被复制:始终设置生产环境自己的令牌。托管 Agent 连接的 webhook 签名密钥(Claude Agent (Managed))也不会被复制:每个 hub 都会注册自己的端点并设置自己的密钥。参见 references/connections.md
  • 组织标签: hub.tags(slug 名称,须先在 UI 中创建)决定 hub 可解析哪些组织凭据(匹配规则见上文「连接和凭据」)。只有组织管理员可以更改这些标签;任何人都可以推送不更改标签的内容。标签的 slug 是永久的——UI 只会编辑其显示名称和颜色——因此这些列表无需重写。参见 references/connections.md
  • 工具组: native(按名称指定的平台内置工具)、delegation(Agent 间/团队移交)、custom(带连接的 HTTP 端点)、mcp(来自 MCP Server 连接的工具,按 name + connection 指定——推送时会发现并分配;参见 references/agents/native-tools.md)。关于如何设计要公开的参数/工具:references/agents/tool-principles.md
  • 名称是外键: 跨实体引用在推送/运行时通过显示名称解析——Agent 的 connection:、委派的 target:(Agent 名称或由 UI 管理的团队名称)、Agent 的 skills[].name、评估的 agent:、自定义工具的 connection:。悬空名称会导致推送失败或运行时调用失败——重命名任何内容时,都要在同一次编辑中更新引用它的实体
  • 重命名: 更改 name 字段——稳定的 id 可确保系统将其识别为重命名,而非删除后新建。对于 Agent,wayai push 会自动重命名 .yaml 和 .md 文件
  • 省略默认值: 与默认值一致的字段会被省略(例如,enabled: true、看板标志默认为 false、excludeHolidays 默认为 true)
  • 实体匹配(同步/差异): 优先使用 id(稳定的 UUID),之后再回退到其他方式。例外情况:状态按 name 匹配(无论作用域如何,在每个 hub 内唯一);评估按 name + path 匹配;原生工具按每个 Agent 的 tool_name 匹配

Slug 化与实体匹配

名称 → 用于文件名的 URL 安全 slug:

  1. 转为小写
  2. 标准化重音字符(NFD + 移除变音符号)
  3. 将非字母数字字符替换为 -
  4. 合并连续的 -
  5. 去除开头和结尾的 -
  6. 限制为 50 个字符

示例:Mario's Pizza → marios-pizza;Suporte Nível 2 → suporte-nivel-2;Specialist - Billing → specialist-billing。

编辑 Agent 指令

  • 文件:与对应的 .yaml 文件位于同一目录下的 agents/<slugified-agent-name>.md
  • 始终将文件保存到 wayai-ws/hubs/<hub>/agents/,绝不要保存到 /tmp 或其他路径
  • 编辑前始终先运行 wayai pull,以免覆盖外部修改
  • 指令支持动态占位符:{{now()}}、{{user_name()}}、{{state()}} 等——请参阅 references/agents/instructions.md
  • 可靠性结构:每个 .md 文件都按步骤 → 护栏 → 语气的顺序组织;说明要做什么(而非要避免什么);将每个操作写成一个具名工具调用。组织提示词,让模型最先、最容易执行正确的操作。完整原则请参阅:references/agents/prompt-principles.md

参考文档

每个领域对应一份参考文档,并遵循 hub 导航顺序。本文介绍相关概念;准备编写该领域的 YAML、需要了解字段级架构或特定提供商的详情,或正在排查该领域的行为时,请打开相应领域的参考文档。

领域参考文档阅读时机
连接references/connections.md配置渠道、Agent 提供方、工具 API 或语音连接器;绑定凭据、组织标签、生产凭据
Agentsreferences/agents/roles-and-settings.md选择 Agent 角色、委派流程、连接器专属设置、评估变量、响应格式
Agentsreferences/agents/native-tools.md原生工具目录及参数、元工具(get_tool_schema、execute_tool)、MCP 工具分配
Agentsreferences/agents/custom-tools.md自定义 HTTP 工具格式、OpenAI 函数架构、composed_tools 的副作用
Agentsreferences/agents/tool-principles.md设计可靠易用的工具界面,供容易出错的 Agent 调用——工具界面整理 > 验证 > 提示词、一个工具对应一个意图、错误明确暴露、受保护的原子操作
Agentsreferences/agents/instructions.mdagents/<slug>.md 的占位符语法({{now()}}、{{state()}} 等)
Agentsreferences/agents/prompt-principles.md放置和组织上下文以确保可靠执行——上下文与插槽生命周期、缓存卫生、状态与工具历史、流程优先于风格、积极表达、将语气单独设为一节
看板references/kanban.md看板字段规范:标志、状态转换、后续操作、附加上下文架构/说明、泳道、约束矩阵、警告
状态references/states.md状态 JSON 架构、范围、Agent 读写、初始值
技能references/skills.md技能(skills:、skills/<skill_name>/)、Agent 关联、将拉取的文件夹转换为技能前的操作、提供方同步(wayai sync-skills)
语音通话references/calls.md为实时 AI 语音通话设置 hub:Realtime 连接、pilot_voice Agent、网页通话及其开场白(AI 通知、WayAI 的开场白或你自己的开场白)、AI 可以接听的对象、转接、口头确认、结束通话、团队看到的内容、录音、计费、限制
评估references/evals.md评估场景 YAML、场景集、代码化旅程、种子数据和变量、wayai eval capture / wayai eval journey capture、运行节奏、通话评估(run-eval --call-mode、wayai eval call)、编写和解读原则
自动化references/automations.md自动化(计划、事件或 webhook 触发器、联系人列表或无目标、send_message / run_agent)、webhook 投递(签名、密钥、轮换)、各 hub 类型的有效组合、任务 hub 任务、门控、缺少键与 [] 的区别、启用、暂停和立即运行、消息模板、限制、hub 列表(contact_lists:)、组织的联系人簿(联系人、可见性、组织列表、CSV 导入)
社区references/communities.mdwayai communities:列出组织的社区、读取、轮换或关闭加入链接、来源标签、统计信息、仅限邀请的社区访问列表;允许运行该命令的人员(所有者和管理员,仅限浏览器登录)及其错误。将社区作为代码管理:community.yaml(其 admission)、rules.md 和课程(course.yaml、课程文件)、房间密钥、名称和修订版本、列表顺序、pull 和 push 的判定方式、冲突、限制、--dry-run / --theirs
分析references/analytics.md变量类别/类型、筛选运算符、时间分析、查询工作流
Basesreferences/bases/README.md开展任何 base 工作前请先阅读——Data 对象模型、预览/发布规则,以及指向下方文件的路由图
Basesreferences/bases/records.md记录类型架构、记录、筛选器 DSL 和 search、日期时间、部分更新、取消/归档、x-fk、已审核记录(x-review)及 Agent 备注方案、关系类型、关系、批处理、批量导入
Basesreferences/bases/querying.mdwayai bases sql——表、必需的范围限定谓词、JSON 子列、示例集;x-search 调优和时区配置
Basesreferences/bases/files.md文件类型、按路径寻址的版本化文件、历史记录/差异、S3 挂载、记录附件
Basesreferences/bases/config-as-code.mdwayai-ws/bases/<base>/、子树路由和拒绝混合调用、base.yaml、发布/回滚、评估模式、种子数据和租约
Basesreferences/bases/integrations.md以规范模型优先的建模方式和模式目录;外部来源、入站 webhook、触发器、提供方适配器
Basesreferences/bases/toolsets.md操作和工具集(面向 Agent 的 MCP 界面)、filterable_fields/writable_fields/base_filter/precondition、base API 令牌、base 凭据、建模和工具设计原则
Basesreferences/bases/executors.md构建代表触发器或外部来源与外部世界交互的 HTTP 服务
规范示例references/canonical-example/README.md端到端 hub,展示 hub.yaml + agents/* + evals/ + journeys/ 如何交叉引用,以及其 Agent 如何从知识库读取组织的文档。完全从头生成新 hub 前,请先阅读一次
仓库 Agent 模板references/repository-agent/README.md在单个 GitHub 仓库中工作的托管 Agent:先读取仓库的 AGENTS.md,从分支或提交开始(repo_checkout),只推送自己的分支。可复制到 hub 的 agents/ 中的文件
使用应用references/using-the-app.md如何为终端用户(Hub User)提供帮助:Agent 列表、聊天和任务 Agent、撰写和附加内容、文件、人员何时接听、账户、通知、移动应用和桌面应用
支持收件箱references/support-inbox.md如何为支持团队成员或 hub 管理员提供帮助:收件箱及其标签页、看板、认领/接管、转接、关闭、回复和 24 小时窗口、Copilot 建议、咨询、联系人审批、通知、移动应用中的支持功能
导航references/navigation.md应用 URL 界面(/chat、/support、/settings/...)、hub 详情页标签、查询字符串深层链接——任何需要向用户提供 URL 的时候;链接在移动应用中的打开方式,以及桌面应用(获取方式、与浏览器版相比新增的功能、设置)
AGENTS.md 文件references/agents-md-template.md每个 hub / base 文件夹的记忆模式——AGENTS.md 应包含哪些内容,以及 CLI 会为哪一个生成初始文件

评论

支持 Markdown