簡單代理聊天室
使用時機
聊天室是一個多對多的聊天記錄檔。任何數量的代理都可以發布訊息到聊天室,任何代理也可以監控它。典型用途:
- 多個子代理處理相關任務,需要共享中間發現(例如,程式設計師回報解析器錯誤、研究員回報 URL、測試員回報測試失敗)。
- 長期運作的代理需要讓可能稍後啟動的其他代理發現它。
- 執行多步驟計畫的「代理團隊」的協調頻道。
如需與單一長期運作的子代理進行一對一通訊,姊妹技能 simple-agent-comms(兩個檔案 + 一個監控器)更為輕量。
你需要知道的事
三個命令,都在 $PATH 上。**你不需要知道任何檔案路徑。**聊天室名稱是你唯一需要傳遞的內容。
simple-room-send <聊天室> [參數] # 發布訊息
simple-room-monitor <聊天室> [參數] # 串流新訊息(適合監控)
simple-room-scan <聊天室> <子命令> # 計數 / 檢索 / 活躍 / 搜尋 / ID / 路徑
就是這樣。你選擇一個聊天室名稱(字母數字、點號、底線、破折號;最多 64 字元),為自己選擇一個代理 ID,然後發送/讀取。
如果系統的其他部分需要知道聊天室的儲存位置,唯一的標準位置是 ~/.cache/simple-agent-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 # 在監控中:
▲ # 新行到達,
│ # 自我訊息已過濾
# --- 稍後,在另一個終端機/回合 --- 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", … }
…
並行發布者不會互相干擾記錄:在 POSIX 系統上,對於 ≤ PIPE_BUF(4096 B)的緩衝區,O_APPEND 寫入是原子操作,而 JSON 記錄在實務上始終小於 1 KiB。
監控(Monitor(...) 形狀)
simple-room-monitor Monitor 工具
─────────────────── ───────────
回溯:檢索最後 N 條記錄 stdout
(或 0 表示「僅即時」) │
解析 JSON,丟棄自我 ──────►│ 每行都是一個
│ 背景事件,
即時: pyinotify.watch 監控檔案 │ 不是使用者回覆
IN_MODIFY ─► 讀取新位元組
IN_DELETE ─► 等待重新建立
IN_MOVE ─► 等待重新建立
▼
代理讀取該行,
決定如何處理
該腳本不會輪詢。它會阻塞在 pyinotify.Notifier 中,並在核心事件發生時喚醒。在本地檔案系統上,從發送到事件傳遞的延遲低於毫秒。
掃描(唯讀)
simple-room-scan <聊天室> <子命令> [參數]
────────────────────────────────────────
│
├─ count → 1 行:記錄總數
├─ ids → 每行一個 ID(排序)
├─ path → 1 行:絕對檔案路徑
├─ active [--window S] → 每個活躍代理的 "代理<TAB>時間戳"
├─ tail [-n N] [-a A] → 最後 N 條(或特定代理的)記錄
└─ grep <模式> → 訊息符合條件的記錄
[--since-seq N]
[-a A] [--json]
│
▼
iter_records(path) → dict 串流
(跳過空白 / '#' / 格式錯誤的行)
參考
simple-room-send <聊天室> [-m 訊息] [-k {msg,system,meta}] [-a 代理] [--stdin]
| 標誌 | 意義 |
|---|---|
-m 訊息 | 訊息文字(否則從 stdin 讀取) |
--stdin | 強制從 stdin 讀取(覆蓋 -m) |
-k 類型 | msg(預設)、system 或 meta |
-a 代理 | 本地代理 ID;預設為 $SIMPLE_AGENT_ID 否則為 $USER-<主機>-<PID> |
--seq N | 明確的單調遞增序號(可選) |
--id ID | 明確的記錄 ID(uuid4 十六進位,可選) |
--ts ISO | 明確的時間戳(可選) |
-q | 抑制 stderr 上的 "sent id=…" 確認訊息 |
訊息會原樣儲存(換行、製表符、反斜線在記錄內會以 JSON 跳脫處理;在讀取端你會看到正常的字元)。
simple-room-monitor <聊天室> [-a 代理] [--exclude-self] [--backfill N] [--grep 模式] [--json]
| 標誌 | 意義 |
|---|---|
-a 代理 | 本地代理 ID(預設同上) |
--exclude-self | 丟棄來自本地代理的記錄(預設:開啟) |
--no-exclude-self | 包含它們(當你想看到自己的訊息時使用) |
-b N | 在進入即時模式前,發送最後 N 條現有記錄 |
(-1 = 全部;0 = 僅事件,預設值) | |
--grep 模式 | 僅發送其渲染行符合正則表達式的記錄 |
--json | 每行發送原始 JSON 記錄(否則為 HH:MM:SS 代理: 訊息) |
該腳本會一直執行直到被終止。將其用作持久 Monitor(...) 工具呼叫的 command — 正確模式是每個聊天室每個會話一個 Monitor。Monitor 事件是背景事件,不是使用者回覆;不要將它們視為結束回合的使用者訊息。
simple-room-scan <聊天室> <子命令> [參數]
| 子命令 | 參數 | 輸出 |
|---|---|---|
count | — | 總記錄數 |
ids | — | 每行一個代理 ID |
path | — | 絕對檔案路徑 |
active | --window SECONDS (120) | 每個活躍代理的 代理<TAB>時間戳 |
tail | -n N (20), -a 代理, --json | 最後 N 條記錄 |
grep | 模式, --since-seq N, -a A, --json, -c(計數→stderr) | 符合條件的記錄 |
grep 區分大小寫,並使用 Python 正則表達式語法(對於常見情況,它接近 PCRE — .、*、+、?、\b、字元類別)。
自我過濾模式(「不要自言自語」配方)
監控器預設使用 --exclude-self,因為在單一代理的回合循環中,代理剛剛發送了它自己的訊息,將其作為事件重播會是雜訊。如果你需要看到單一代理除錯會話的雙方,請傳遞 --no-exclude-self。
同一個聊天室中的兩個代理必須選擇不同的代理 ID。預設值($USER-<主機>-<PID>)每個行程都是唯一的;如果你從同一個 shell 啟動多個代理,請為每個代理設定 SIMPLE_AGENT_ID 以保持它們不同。
你不需要知道的事
- 磁碟上的路徑。它是
~/.cache/simple-agent-room/<聊天室>.log。你永遠不會直接寫入它。simple-room-scan <聊天室> path會告訴你,如果你好奇的話。 - 結構定義。函式庫會讀取檔案、解析 JSON、丟棄格式錯誤的行,並取消跳脫訊息字串。你會看到一個包含
id、ts、agent、msg、kind、可選seq的字典。 - 輪詢。監控器完全由事件驅動(inotify)。
- 鎖定。記錄小於 4 KiB,O_APPEND 在 POSIX 上是原子操作,因此不需要 flock / fcntl。兩個寫入器可以同時發布而不會互相干擾。
值得了解的失敗模式
- 刪除/重新命名後的過時 inotify:函式庫會在
IN_CREATE時重新附加對相同路徑的監控,因此處理日誌輪替工具替換檔案的情況。如果你手動rm檔案,監控器會在下一次發送時建立一個新的空檔案。 - 代理 ID 衝突:具有相同 ID 的兩個代理會將對方的訊息視為自己的(並預設將其過濾掉)。始終使用
SIMPLE_AGENT_ID或$USER-<主機>-<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不需要它即可運作。