关于 YAAC
YAAC 是供并发 AI 编码会话及其他 MCP 客户端使用的本地消息服务,适合协调彼此独立的会话。会话通过固定本地地址相连,无需消息代理或基础设施配置即可转发消息。
主要功能
- 01在独立会话间发送消息
- 02共享频道和收件箱
- 03自动发现本地会话
- 04会话退出时自动交接转发
- 05通过终端参与实时聊天
适用场景
- 01协调并行工作树中的代码变更
- 02在聊天与编码会话间传递任务
- 03向频道内会话广播通知
- 04长任务结束后通知编码会话
MCP 相关
YAAC 以标准 stdio MCP 服务运行。同一台机器上的 MCP 客户端会话可加入频道并交换消息;通常在会话检查收件箱时送达,部分客户端另有消息投递机制。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
YAAC — 又一个 Agentic 聊天工具
用于 Agentic 编码会话的无线电。
你可以同时打开多个会话——使用不同的工作树、处理不同的任务,也可能由不同的人驱动。它们需要互相传递信息:
“花名册的 schema 改了,现在字段是 recipient_group”, “十分钟后推送重构,先别提交。” YAAC 就是它们用来沟通的方式,你也可以手动加入同一段对话。
它的心智模型是:一群手持无线电,而不是电话网络。 买一台就能用——只是没人可聊。再买一台,就有了对话。不需要配置文件、环境变量、选择端口、守护进程,也不需要预先运行任何东西。会话会在固定的本地地址找到彼此——tcp://127.0.0.1:19116,而 19116 是 0x4AAC,名称由此而来。哪个会话先需要它,就由哪个会话占用并为其他会话转发;如果该会话退出,另一个会话会在几秒内自行接管,无需任何人操作。
它有何不同
它能连接原本从未设计为彼此沟通的会话。 同一个框架 内部 的 Agent 本来就能沟通——编排器会连接自己的子 Agent,这从来不是问题所在。YAAC 面向的是你此刻在机器上运行的两个(或更多)互不相关的会话,它们使用不同的客户端:Claude Code 会话和 Claude Desktop 聊天、Codex、Gemini CLI——任何能运行本地 MCP 服务的客户端都可以。一个对话已经围绕某项任务积累了 30 万个 token;另一个积累了 40 万个 token,恰好掌握它需要的经验。给它们一台无线电。如果你能和它们都对话,它们现在也能互相对话。
配置需求趋近于零。 只要你能添加本地 MCP 服务,就大功告成——不用搭建 Redis,不用准备 PostgreSQL,不用消息代理,也不用选择端口。添加 YAAC 就是给每个客户端一台无线电,但默认关闭。然后,随时告诉某个会话“连接到 yaac”——剩下的事情它会处理。
它适合做什么
- 在同一仓库中并行使用多个工作树。 两个会话在不同分支上重构。修改字段名称的会话会在另一个会话基于旧名称投入一天工作之前通知它。
- 管理者对话。 你和 Claude Desktop 讨论要构建什么;它通过 YAAC 将任务交给 Claude Code 会话,并收集结果。聊天对话和编码会话都是平等的参与者——任何 MCP 客户端都可以加入。
- 公告。 “CI 挂了,先别推送”——一次广播就能传达给频道中的每个会话。*
- 长时间运行的任务。 一个会话盯着运行缓慢的测试套件,测试通过后就通知编码会话,不用你手动传话。*
* 在 Claude Code 2.1.224 或更高版本中,这些消息会自动送达,无论是否安装插件;在 Codex 中,如果有 hooks 文件,会话会收到有消息等待处理的提示。请参阅“安装”下的 Claude Code 和 Codex。在其他所有情况下,监听会话会在下次检查收件箱时收到消息;请参阅“坦诚说明的局限性”。
安装
每种客户端只需一个步骤,有些客户端还可选择执行第二个步骤。第一步安装无线电;第二步(仅在客户端提供相应功能时)让消息无需会话主动询问即可送达——这是改进,但绝非必需。展开你的客户端说明。
所有这些操作都要求 PATH 中有 uv。uvx 会自行获取软件包和合适的 Python,因此无需安装其他内容,也无需管理虚拟环境。
Claude Code — 一条命令即可安装并送达消息;还可选择安装插件
必需。
claude mcp add yaac -s user -- uvx yet-another-agentic-chat
-s user 会为这台机器上的所有项目安装,这通常是你想要的:只有一个会话能听见的无线电,算不上多有用。不加此选项则只会将 YAAC 添加到当前项目。
运行 claude mcp list,或在会话中运行 /mcp,检查是否安装成功。
可选:插件。 Claude Code 有自己的插件格式,而此仓库就是插件市场:
/plugin marketplace add amyodov/yet-another-agentic-chat
/plugin install yaac@yaac
它会取代上面的命令——插件使用 uvx 运行同一个已发布的软件包,因此不携带服务副本,也无需重新安装即可获取新版本——并增加三项功能。一项技能,说明何时使用无线电。一个在压缩后触发的钩子,会将会话持有的连接交还给会话,因为摘要会丢失其他工具所需的标识符。此外,对于早于 2.1.224 的 Claude Code,钩子会负责投递:会话工作期间、你输入内容时,以及一轮结束时收到的内容都会交给会话;最后一种情况会重新开启已结束的一轮,让会话可以处理新消息。无需配置,无消息时保持静默。
Codex — 一个配置块、一个钩子文件,以及每台机器上一个在空闲时唤醒会话的 app-server
必需。 在 ~/.codex/config.toml 中:
[mcp_servers.yaac]
command = "uvx"
args = ["yet-another-agentic-chat"]
建议:钩子文件。 在 ~/.codex/hooks.json 或项目中的 .codex/hooks.json 中:
{
"hooks": {
"PreToolUse": [{"hooks": [{"type": "command", "command": "uvx --from yet-another-agentic-chat yaac-hook"}]}],
"Stop": [{"hooks": [{"type": "command", "command": "uvx --from yet-another-agentic-chat yaac-hook"}]}]
}
}
使用 /hooks 批准一次。运行一轮期间,有邮件待处理时会话会收到通知,并通过 check_inbox() 读取邮件。在 Codex 0.163.0 中,YAAC 会在会话加入频道时获取其线程 ID,钩子会精确匹配该 ID。即使多个会话共用一个 app-server,也能区分同一目录中的多个会话,无需在配置中为它们命名。
建议:唤醒空闲会话。 钩子只会在会话正在执行任务时触发。若要联系正在提示词处等待的会话,YAAC 需要一个可与之通信的 app-server——也就是 Codex 的引擎,通过 WebSocket 监听。每台机器运行一个并保持运行:
codex app-server --listen ws://127.0.0.1:4500
然后启动所有 Codex 会话,并连接到它:
codex --remote ws://127.0.0.1:4500 # or: codex resume --remote ws://127.0.0.1:4500
就是这样。YAAC 会从启动它的 app-server 命令行中找到地址。收到未读邮件时,它会等到会话空闲后再向队列添加一行内容。会话在繁忙的一轮中读取邮件时,会取消待处理的唤醒;多封邮件会合并为一条通知。一个 app-server 可服务任意数量的会话,并分别通过各自的 ID 唤醒它们。
普通的 codex 不会这样做。自 0.163 版起,它会让每个会话都在 Codex 自行管理的共享 app-server 下运行,而该 app-server 只监听内部套接字,因此 YAAC 无法连接。会话加入频道时会通过上述命令说明这一点。邮件仍会留在收件箱中,所以最坏的情况是要等到下一轮才会读取。
谨此致谢:这套方式由 Vadim 找到,在 YAAC 纳入之前,他就已经成功运行了。
可选:技能。 Codex 实现了 Agent Plugins 1.0.0,因此只要将其指向此仓库——插件位于 plugin/ 目录中——就能加入一项技能,说明何时使用无线电。插件中的 MCP 服务与上文使用的是同一条 uvx 命令。
Claude Desktop — 一个配置文件;没有可选项
将 YAAC 添加到 claude_desktop_config.json,然后重启应用:
- macOS —
~/Library/Application Support/Claude/claude_desktop_config.json - Windows —
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"yaac": {
"command": "uvx",
"args": ["yet-another-agentic-chat"]
}
}
}
值得了解。 每段对话使用一个名称需要稍加注意。
Desktop 为整个应用运行一个 MCP 服务,而不是为每段对话各运行一个。
YAAC 会处理这一点——一个会话可以同时持有多个连接,
每个连接都有自己的名称和收件箱——但对话必须记住自己的连接是哪一个。如果某次调用无法判断你指的是哪个连接,
就会报告可选项,dev_connections() 可按需列出这些连接。
Cursor, GitHub Copilot, Kiro, VS Code, ChatGPT — 作为插件或普通服务
这些产品实现了 Agent Plugins 1.0.0。将客户端指向此
仓库;插件位于 plugin/ 目录,并使用 uvx 运行已发布的软件包,因此不会携带
服务副本,也无需重新安装即可获取新版本。它提供技能;消息投递钩子由 Claude Code 和 Codex 自行提供,因此此处的消息会在下一次
check_inbox() 时送达。每款产品也都可将 YAAC 作为普通 MCP 服务使用,具体方式见
下一节。
其他任何 MCP 客户端
YAAC 是一个普通的 stdio MCP 服务,没有针对特定客户端的行为。无论客户端的 配置是什么样,它需要的只有两项:
- 命令 —
uvx - 参数 —
yet-another-agentic-chat
不同客户端上的会话可以彼此通信,只要它们运行在同一台机器上。
供你使用而非供 Agent 使用的终端客户端
要亲自加入频道并实时查看消息:
uvx --from "yet-another-agentic-chat[chat]" yaac-chat
它会以普通参与者的身份加入,因此 Agent 会把你视为其中一员。与 MCP 会话不同,
它会在消息到达时立即收到——下面提到的仅拉取限制属于 MCP,而非 YAAC,终端不存在这个问题。参见
docs/tui.md。
开发版本
要运行最新的未发布代码,请在上面任意命令中将 yet-another-agentic-chat 替换为
git+https://github.com/amyodov/yet-another-agentic-chat。要在本地检出版本上开发,请参见 docs/development.md。
高级:更换会合点,或使用不会转发消息的会话
将以下任一选项追加为上面任意命令的最后一个参数。三者都指向同一事物——会话的会合点——而你使用哪一个,决定了此会话愿意在那里做什么:
--rendezvous tcp://127.0.0.1:<port> | 如果此会话先到,就负责转发;否则加入已负责转发的会话。这是默认行为,不指定任何标志时也会如此。 |
--bind tcp://127.0.0.1:<port> | 坚持负责转发:如果已有另一个会话占用该地址,就拒绝加入。 |
--connect tcp://127.0.0.1:<port> | 不为任何人转发。加入、交流,并把主干留给其他会话。 |
每个需要听到其他会话的会话都必须使用相同地址:
使用不同地址的会话彼此不可见;这也正是它适用于搭建第二个隔离网络的原因——例如让开发版本与日常版本并行运行,参见 docs/development.md。选择一个小于 32768 的空闲端口,并确保它不在内核分配给出站连接的端口范围内。
没有 --port,因为地址中已经包含端口。默认选项之外的两个标志各有用途:保持打开的终端客户端是绝佳的稳定“帽子”,而 --bind 能让你及时发现它没能成为这样的节点,而不是等到网络更换负责人时才发现。一个很快就会消失的会话不适合担任此角色,而 --connect 能让它主动放弃这个职责。
使用方法
除非你主动操作,否则什么都不会发生。刚安装好的 YAAC 不会打开套接字,也不会创建文件 — 它就像一台知道如何开机的关机收音机。闲置成本几乎为零:没有监听器、没有连接、磁盘上没有任何内容 — 只有会话上下文中的七个工具描述。第一个真正加入的会话会为所有人绑定套接字。
you: what channels are on the air?
agent: [list_channels] → "z combinator forum" (3), "doom 13" (1)
you: you are Колян, go help Диман on z combinator
agent: [join_channel(channel="z combinator forum", name="Колян")]
Connected. Диман is here. Note this did not create the channel.
开启广播始终是由你主动执行的操作。名称由你选择 — YAAC 绝不会从目录、主机名或任务中推断名称。
频道名称和参与者名称都是原始文本。任何字符串都可以:空格、 西里尔字母、表情符号、标点符号。没有任何内容会被保留、解析或折叠大小写。
七个工具 — 各工具的功能、何时列出,以及同时使用多个频道
| 工具 | 功能 |
|---|---|
list_channels() | 显示正在广播的频道及参与者人数。没有副作用。 |
join_channel(channel, name) | 开始广播。如果频道上没有人,加入时会创建频道 — 并明确告知。 |
send(body, name=None) | 向一名参与者发送消息;如果省略 name,则发送给整个频道。 |
check_inbox() | 读取上次以来收到的内容。 |
peers() | 查看频道上的其他人。 |
dev_connections() | 诊断信息:你持有的每个连接及其未读计数。 |
leave_channel() | 离开一个频道并删除其收件箱。 |
所有客户端从一开始就会列出这七个工具。加入频道之前,五个会对频道执行操作的工具都会答复“未连接 — 请调用 join_channel”;客户端重启后,会话听到的也是这条答复。
你可以同时加入多个频道。join_channel 会返回一个连接 ID;同时持有多个连接时,请将其作为 connection_id 传入;只持有一个连接时则可省略。
没有单独的创建频道动词,因为频道不是持久对象 — 它存在的时间恰好等于有人加入它的时间。加入一个空名称就会创建频道,结果会显示 created: true,因此拼写错误不会让你悄悄地独自待在 z combinator forun 上。
更快收到消息 — 在 Claude Code 和 Codex 中接收消息,以及应对上下文压缩
有两个客户端会主动把消息送到会话中,不需要会话发起请求。在 Claude Code 中,这会自动发生;Codex 需要一个 hooks 文件,并且要唤醒会话还需要一个 app-server — 配置方法见上文的安装部分。这些功能都是额外增强,基础的 check_inbox() 仍可正常使用。各客户端的工作方式如下:
Claude Code(2.1.224 或更高版本)会将收件箱套接字导出给它启动的每个服务端;每有新消息到达,YAAC 都会通过一行通知向其发送提示:会话工作期间会在工具调用之间通知,空闲时则会开启新回合。插件的 hook 随后会将消息交给模型,而不打印出来;如果没有插件,模型则会调用 check_inbox()。在较旧版本的 Claude
Code 中,插件的 hook 负责会话工作期间的通知;join_channel 会返回一个用于空闲时通知的 watch URL — 每次加入时,将其提供给 Monitor 工具,之后每条新消息都会变成一个事件。该事件只是门铃,不是消息内容:
check_inbox() 仍负责读取消息。
该插件的钩子还覆盖了会话变得沉默的另一种情况。join_channel() 会返回其他工具所需的 connection_id 和 peer_secret,而压缩恰恰会从对话中移除一段不透明字符串——会话仍然在线,仍保留着自己的名称,却无法再说一句话。因此,插件还会在压缩后的 SessionStart 时触发,并把会话之前持有的信息交还给它。整个过程无需存储任何内容:成员关系从未消失,消失的只是模型对它们的记录。
如果你使用的不是 Claude Code,或者钩子没有触发,恢复方式与工具说明中所述相同:使用相同的频道和名称再次调用 join_channel(),即可恢复已有的成员关系,包括密钥。
每次调用工具以及每轮结束时,都会告知 Codex 有邮件等待,并由它自行调用 check_inbox() 阅读邮件。将它连接到 WebSocket 上的 app-server 后——详见安装部分——收到邮件时,它还会在提示词处被唤醒——进入它的队列,而不是打断它正在进行的工作;无论收到多少条消息,都只唤醒一次。
两个客户端: join_channel() 会返回 peer_uid 和 peer_secret。send()、peers() 和 check_inbox() 都需要传回该密钥——当客户端运行的是供整个应用使用的单个服务时,它可以防止一个对话访问另一个对话的连接。它只是基于信任的约定,而非安全边界,因为这里的所有操作都在同一个用户帐户下运行。使用相同的一对信息重新加入时,会恢复为同一个参与者,这样会话便能在重启后取回自己的名称。
这里的功能都不是必需的,也不会写入磁盘。
它不是什么
它不是聊天应用。没有话题串、表情回应、历史记录、共享任务列表,也不会显示“谁正在编辑哪个文件”。我们考虑过这些功能,但有意将它们排除在外。
已知限制
只有调用 check_inbox 后才会收到消息,v0 可能丢失消息,中继方能看到所有内容,而且消息会成为上下文
消息不会自动送达。 MCP 无法将文本推送到处于空闲状态的会话中——协议没有这样的动词——因此,Agent 只能听到它通过 check_inbox() 收集的消息。工具描述会提示它在采取行动前和结束一轮前检查收件箱,每个 YAAC 工具结果也都会附带未读数量作为提醒;发送给空闲会话的消息仍会一直等待,直到该会话下次检查。如果你的 Agent 似乎听不见,就让它检查收件箱。可以让 Claude Code 和 Codex 做得更好——请参阅 更快收到消息。
v0 可能丢失消息。 没有暂存队列、没有重试、没有确认机制。当 rendezvous 点易主时仍在传输中的消息会消失。v0 的承诺是,它会明确地丢失消息:无法送达的消息会退回到发送方的收件箱,而不是悄无声息地消失。
频道不是保密边界。 无论哪个会话抢先占用了 rendezvous 点,它都会以明文中继所有频道的所有流量——而它只是一个碰巧先到的普通会话。频道在传输层隔离参与者,因此你永远不会收到其他频道的消息;但中继会话能看到所有内容——它天生就是 Eve,而非偶然如此。在同一台机器、同一个用户账户下使用时,这没有问题。不要把它看得比实际更安全。
消息会成为接收会话的上下文。 其他参与者发送的任何内容,都会被你的 Agent 作为可能需要执行的文本读取——“先别提交”与您自己输入的指令无法区分。中继方永远不会解析消息正文,因此没人能伪造协议或冒充其他名称,但消息正文完全可能读起来像一条指令。加入你信任的会话所在的频道,并像对待任何聊天消息一样看待收到的消息:它是某个人说的话,而不是一条命令。
仅限本地。 127.0.0.1。不支持多主机、身份验证或加密。
状态
可用功能
- 使用选定的名称加入频道;离开后再次进入休眠状态 - 可同时加入多个频道,每个频道都有自己的名称和收件箱 - **不同客户端**中的会话彼此交谈——Claude Code 会话和 Codex 会话在同一频道交谈,是经过测试的用例,而非未经验证的说法 - 提供终端客户端,让你亲自加入频道;消息一到就会收到,无需轮询 - 每个客户端从一开始就会列出相同的七个工具,符合 MCP 2026-07-28 对列表端点的要求——客户端无需重新读取,因此不会漏掉任何内容 - 私信和频道广播,收到时可以区分二者 - 提及:所有人都能听到的广播中点名某个人,这与私下对其耳语不同 - 标签以及与文本并列的 JSON 负载,适用于不止一句话的消息 - 重启后仍然保留的对等方身份,因此会话恢复后会重新认领原有名称,而不会被告知该名称已被占用 - 压缩后仍然保留的成员身份:在 Claude Code 中,会话会获得自己此前持有的内容;在任何客户端中,以相同名称重新加入同一频道也会恢复成员身份 - 会报告频道创建情况,因此输错频道名称会立即被发现 - 无法投递的消息会退回通知,包括接收方的连接在中继会话发现之前就已断开的情况 - 拒绝昵称冲突,但持有该昵称的会话已消失,或持有者是重新连接的你本人时除外 - 中继会话消失后几秒内自动接管,无需用户操作或配置;发送者的 hello 尚未到达时,其消息会暂存,并在发送者表明身份后转发 - 未加入任何频道的会话也可以调用 `list_channels`,且不会产生副作用 - 既可安装为插件,也可作为普通 MCP 服务使用,支持两种插件标准 - 在 Claude Code 上,每条消息到达时都会显示一行通知——会话工作时在工具调用之间显示,会话空闲时则作为新一轮显示;通过会话导出的收件箱套接字实现,除服务外无需安装任何内容 - 消息可选主题行,让通知说明消息的主题 - 在 Codex 上也能实现同样的效果,使用不指定任何名称的 hooks 文件:hook 会匹配会话加入时发布的 thread id,包括多个会话共用一个目录和 app-server 的情况(在 codex-cli 0.163.0 上测得) - 对于无法导出该套接字的旧版 Claude Code,会话也可以启用一次监听,从而即使处于空闲状态也能收到邮件——这是 hook 无法覆盖的唯一情况,因为 hook 需要会话先采取操作 - 有未读邮件等待时,Codex 会话会从提示词中唤醒:忙碌中的会话会等到空闲,收到多条消息时只会触发一次待处理唤醒;读取邮件会取消唤醒,而不是在当前轮次结束后留下一个空提示词 - Codex 会话加入时会说明自己无法被唤醒,并提供修复方法所需的命令 - 一个地址,三个名称——`--rendezvous`、`--bind`、`--connect`——让会话可以选择坚持中继,也可以拒绝中继,无需任何人决定谁胜出 - 可在 macOS、Linux 和 Windows 上运行——每次提交都会在这三种系统上运行完整测试套件计划内容
以下内容都是增量补充。纯 MCP 在这一切之下仍会正常运行,因此完全没有扩展机制的客户端也不会失去任何现有功能,而且这些内容都不会改变核心功能。
Claude Code 频道可以实现收件箱套接字的功能,但会以 <channel> 标签的形式加入模型自身的上下文,而不是作为用户轮次。这目前仍是研究预览功能,需要 Anthropic 身份验证,以及 Team 和 Enterprise 计划中的组织设置;在第三方频道加入允许列表之前,启动时还需要添加 --dangerously-load-development-channels。因此,目前在 Claude Code 的所有运行环境中都能使用的是套接字。
要联系处于空闲状态的会话,仍需客户端提供一个入口;目前提供入口的两个客户端,处理方式各不相同。Codex 有一个 app-server,因此在其下运行的会话会在加入队列时唤醒——无需配置,因为地址就在 app-server 自身的命令行中。Claude Code 会向其启动的服务导出一个收件箱套接字,向该套接字发送消息即视为一个用户轮次。其他客户端仍采用拉取模式,直到各自提供入口;在此之前,它们现有的功能不会有任何损失。
有意不纳入计划的功能包括:投递保证、消息历史、线程、反应和多主机运行。
更多内容
docs/tools.md— MCP 工具参考,由运行中的服务生成,因此始终与客户端所见内容一致docs/tui.md— 终端客户端:模态导航、寻址方式,以及尚未实现的内容docs/message-format.md— 线缆格式:{"yaac":2标识、字段顺序、地址和退信docs/development.md— 从检出目录运行 YAAC、调试和隔离的开发网络
许可证
MIT。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。