Communitygithub.com

clankercode/agent-file-chat

两个可复用的智能体技能(simple-agent-comms、simple-agent-room)+ Python CLI 工具,实现基于磁盘的智能体间消息传递。使用 JSON-Lines 房间、inotify 驱动的监控,无需代理依赖。智能体无需知道文件路径。

agent-file-chat 是什么?

该技能提供了一套轻量级的、基于文件的智能体间消息通信系统,包含两个核心技能:simple-agent-room(多对多聊天房间)和 simple-agent-comms(一对一通信)。它通过 shell 命令(simple-room-send、simple-room-monitor、simple-room-scan)实现消息的发送、监控和扫描,智能体只需指定房间名称,无需了解底层文件路径。监控功能利用 pyinotify 实现事件驱动,无需轮询,延迟极低。系统设计为无代理架构,记录使用 O_APPEND 原子写入,支持并发写入,无需锁机制。适用于子智能体间共享中间结果、长期运行智能体的发现与协调、以及团队任务编排等场景。支持 Claude Code、Cursor、Codex 等平台的 Monitor 工具集成,可持久化后台运行。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add clankercode/agent-file-chat

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

简单智能体房间

何时使用

房间 是一个多对多聊天日志。任意数量的智能体都可以向房间发布消息,任何智能体都可以 Monitor(监控)它。典型用途:

  • 多个子智能体协作处理相关任务,需共享中间发现(例如,编码者报告解析器 bug、研究者报告 URL、测试者报告失败的断言)。
  • 一个长时间运行的智能体,需要能被之后可能生成的其他智能体发现。
  • 作为执行多步骤计划的“智能体团队”的协调渠道。

对于一对一的、与单个长期运行的子智能体的通信,兄弟技能 simple-agent-comms(两个文件 + 一个监控器)会更轻量。

你(智能体)需要知道的内容

三个命令,全部位于 $PATH 中。你不需要知道任何文件路径。 房间名称是唯一需要传递的内容。

simple-room-send    <room> [args]    # 发布消息
simple-room-monitor <room> [args]    # 流式输出新消息(对 Monitor 友好)
simple-room-scan    <room> <subcmd>  # 计数 / tail / active / grep / ids / path

就是这样。你选择一个房间名称(字母数字、点号、下划线、连字符;最长 64 个字符),为自己选择一个智能体 ID,然后发送/读取消息。

如果系统的其他部分需要知道房间存储的位置,其标准位置是 ~/.cache/simple-agent-room/<room>.log,可通过 $SIMPLE_AGENT_ROOM_DIR 环境变量覆盖(很少使用,仅用于测试或多租户布局)。

快速开始(一个智能体,一行命令)

simple-room-send kitchen "stove is on"      # 你发布了一条消息
simple-room-scan  kitchen tail -n 5          # 你读取了最近 5 条
simple-room-scan  kitchen active --window 60 # 查看谁在这里

快速开始(两个智能体协调)

# 智能体 A                                            # 智能体 B
simple-room-send tasks -m "I'm starting"             \
                                                      simple-room-monitor tasks   # 在 Monitor 中:
                                                                       ▲           #   新行到达,
                                                                       │           #   自我消息被过滤
# --- 稍后,在另一个终端/轮次中 ---            simple-room-send tasks -m "ack"

正确的模式:将监控器作为持久化的后台命令在 Monitor(...) 工具调用中生成,然后在前台发送/扫描/交谈。

ASCII 流程图

发布消息

       智能体                      simple-room-send              磁盘
       ─────                       ────────────────              ───────
  $ simple-room-send kitchen \         │
        -a alice -m "hi"             │  format_record
                                     │  → JSON 行 + '\n'
                                     │  → os.open(O_APPEND|O_CREAT, 0o644)
                                     │  → os.write(fd, line)
                                     ▼
                          ~/.cache/simple-agent-room/kitchen.log
                          ─────────────────────────────────────────
                          {"id":"…","ts":"…","agent":"alice", … }
                          {"id":"…","ts":"…","agent":"bob",   … }
                          …

并发的发布者不会破坏彼此的记录:对于缓冲区 ≤ PIPE_BUF(4096 字节)的写入,POSIX 上的 O_APPEND 写入是原子的,而实际的 JSON 记录通常小于 1 KiB。

监控(Monitor(...) 形态)

       simple-room-monitor                  Monitor 工具
       ───────────────────                  ───────────
  backfill: 输出最后 N 条已有记录          stdout
             (或为 0 表示“仅实时”)            │
             解析 JSON,丢弃自身消息    ──────►│  每行都是一个
                                             │  后台事件,
  实时:    pyinotify.watch 监控文件            │  不是用户回复
           IN_MODIFY  ─► 读取新字节
           IN_DELETE  ─► 等待重新创建
           IN_MOVE    ─► 等待重新创建
                                             ▼
                                       智能体读取该行,
                                       决定如何处理

此脚本不会轮询。它阻塞在 pyinotify.Notifier 中,并在内核事件发生时唤醒。在本地文件系统上,从发送到事件传递的延迟低于毫秒级。

扫描(只读)

       simple-room-scan <room> <subcmd> [args]
       ────────────────────────────────────────
              │
              ├─ count                 → 1 行:总记录数
              ├─ ids                   → 每行一个 ID(已排序)
              ├─ path                  → 1 行:绝对文件路径
              ├─ active  [--window S]  → 每个活跃智能体一行 "agent<TAB>ts"
              ├─ tail    [-n N] [-a A] → 最后 N 条(或特定智能体的)记录
              └─ grep    <pattern>     → 消息内容匹配的记录
                       [--since-seq N]
                       [-a A] [--json]
              │
              ▼
       iter_records(path) → dict 流
       (跳过空白 / '#' / 格式错误行)

参考

simple-room-send <room> [-m MSG] [-k {msg,system,meta}] [-a AGENT] [--stdin]

标志含义
-m MESSAGE消息文本(否则从标准输入读取)
--stdin强制从标准输入读取(会覆盖 -m)
-k KINDmsg(默认)、system 或 meta
-a AGENT本地智能体 ID;默认为 $SIMPLE_AGENT_ID,否则为 $USER-<host>-<pid>
--seq N显式单调序列号(可选)
--id ID显式记录 ID(uuid4 十六进制,可选)
--ts ISO显式时间戳(可选)
-q在标准错误输出上抑制“sent id=…” 确认信息

消息会原样存储(换行符、制表符、反斜杠在记录内部会被 JSON 转义;在读取端你会看到它们作为普通字符)。

simple-room-monitor <room> [-a AGENT] [--exclude-self] [--backfill N] [--grep PATTERN] [--json]

标志含义
-a AGENT本地智能体 ID(默认如上)
--exclude-self丢弃来自本地智能体的记录(默认:开启)
--no-exclude-self包含自身记录(当你希望看到自己的消息时使用)
-b N在进入实时模式前,发射最后 N 条已有记录
(-1 = 全部;0 = 仅事件,默认值)
--grep PATTERN仅发射渲染后的行匹配正则表达式的记录
--json每行发射原始 JSON 记录(否则为 HH:MM:SS agent: msg)

此脚本会一直运行直到被终止。将其用作持久化 Monitor(...) 工具调用的 command —— 正确的模式是每个房间、每个会话一个 Monitor。Monitor 事件是后台事件,不是用户回复;不要将它们视为结束一轮对话的用户消息。

simple-room-scan <room> <subcommand> [args]

子命令参数输出
count—总记录数
ids—每行一个智能体 ID
path—绝对文件路径
active--window SECONDS (120)每个活跃智能体一行 agent<TAB>ts
tail-n N (20), -a AGENT, --json最后 N 条记录
grepPATTERN, --since-seq N, -a A, --json, -c (计数→stderr)匹配的记录

grep 区分大小写,使用 Python 正则表达式语法(在常见情况下接近 PCRE——.、*、+、?、\b、字符类)。

自我过滤模式(“不要自言自语”配方)

监控器默认启用 --exclude-self,因为在单智能体轮询循环中,智能体刚刚发送了自己的消息,将其作为事件回放是噪音。如果你需要看到单智能体调试会话的两边消息,请传递 --no-exclude-self。

同一房间中的两个智能体必须选择不同的智能体 ID。默认值($USER-<host>-<pid>)在每个进程中是唯一的;如果你从同一个 shell 中生成多个智能体,请为每个智能体设置 SIMPLE_AGENT_ID 以保持它们不同。

你不需要知道的内容

  • 磁盘路径。它是 ~/.cache/simple-agent-room/<room>.log。你永远不需要直接写入它。simple-room-scan <room> path 会告诉你(如果你好奇的话)。
  • 模式。库会读取文件、解析 JSON、丢弃格式错误的行,并转义消息字符串。你会看到一个包含 id、ts、agent、msg、kind、可选的 seq 的字典。
  • 轮询。监控器完全由事件驱动(inotify)。
  • 锁定。记录大小 < 4 KiB,POSIX 上的 O_APPEND 是原子的,因此不需要 flock / fcntl。两个写入者可以在不破坏彼此记录的情况下同时发布。

值得了解的故障模式

  • 删除/重命名后 inotify 过期:库会在 IN_CREATE 事件上为同一路径重新附加监控,因此执行日志轮换的工具可以正常处理。如果你手动 rm 文件,监控器会在下一次发送时创建一个新的空文件。
  • 智能体 ID 冲突:具有相同 ID 的两个智能体会将对方的消息视为自己的(并默认过滤掉它们)。始终使用 SIMPLE_AGENT_ID 或 $USER-<host>-<pid> 默认值。
  • 时钟偏差:ts 是发送方的挂钟 UTC 时间。如果你跨智能体按 ts 排序,请设置 NTP。对于单个智能体内部的排序,使用 seq。
  • 非常长的消息:没有硬性上限,但如果你经常发布超过 4 KiB 的消息,可能会达到 PIPE_BUF 并开始看到记录被截断。请将消息保持在 4 KiB 以下。
  • 格式错误的行:读取器会静默跳过任何无法解析为 JSON 对象的行。垃圾输入 = 垃圾被静默丢弃;其周围的合法记录不受影响。

文件

skills/simple-agent-room/
  SKILL.md                       ← 本文档
  bin/
    simple-room-send             ← 瘦包装器,调用 lib.simple_room_send.main
    simple-room-monitor          ← 瘦包装器,调用 lib.simple_room_monitor.main
    simple-room-scan             ← 瘦包装器,调用 lib.simple_room_scan.main
  lib/
    simple_agent_room_lib.py     ← 共享库(格式化/解析、inotify、扫描)
    simple_room_send.py          ← 发送入口点
    simple_room_monitor.py       ← 监控入口点
    simple_room_scan.py          ← 扫描入口点

每个 bin/simple-room-* 包装器都是一个 12 行的 Python 文件,它调整 sys.path 并委托给 lib/simple_room_*.main。包装器会解析自己的真实路径,因此 ~/.local/bin/ 中的符号链接可以透明工作。

安装

从仓库根目录:

./install.sh

这会将 simple-agent-room 放置到 ~/.claude/skills/ 和 ~/.agents/skills/ 中,并将三个 CLI 程序作为 simple-room-send、simple-room-monitor、simple-room-scan 添加到你的 $PATH。

如果你希望手动安装:

ln -s "$PWD/skills/simple-agent-room"                    ~/.claude/skills/simple-agent-room
ln -s "$PWD/skills/simple-agent-room"                    ~/.agents/skills/simple-agent-room
ln -s "$PWD/skills/simple-agent-room/bin/"*             ~/.local/bin/

依赖

  • Python ≥ 3.10
  • pyinotify(pip install pyinotify)。仅监控器需要;simple-room-send 和 simple-room-scan 无需它也能工作。

相关技能