ag2space-voice
AG2 Space voice surface — binds the room the AG2 Space client announces to the voice session's origin, so work delegated by voice in a room is answered in that…
Read and write a room's LIVE collaborative surfaces — the document behind the Doc tab, the whiteboard, the kanban (Yjs/CRDT state, one surface per --kind). Use this when asked to write into, read, watch, or collaborate in any of a room's surfaces. NOT the same thing as `room_ops
$ npx -y skills add sonichi/sutando --skill room-collab --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/room-collabContext preview
The summary Claude sees to decide when to auto-load this skill.
Read and write a room's LIVE collaborative surfaces — the document behind the Doc tab, the whiteboard, the kanban (Yjs/CRDT state, one surface per --kind). Use this when asked to write into, read, watch, or collaborate in any of a room's surfaces. NOT the same thing as `room_ops
name: room-collab description: Read and write a room's LIVE collaborative surfaces — the document behind the Doc tab, the whiteboard, the kanban (Yjs/CRDT state, one surface per --kind). Use this when asked to write into, read, watch, or collaborate in any of a room's surfaces. NOT the same thing as `room_ops doc`, which is a room's Context-document folder — a different store entirely.
> Formerly `room-doc`. The name changed because the skill serves more than a document — markdown, whiteboard and kanban. The `room-collab` names lead (`ROOM_COLLAB_TOKEN`, `AG2_ROOM_COLLAB_URL`, `/api/v1/room-collab`); the `room-doc` spellings are still read and served for one release, and `skills/room-doc/scripts/room_doc.py` still runs (it forwards here).
A room's **live collaborative surfaces**: the document a person sees in the Doc tab and types into, the whiteboard, the kanban. Each is one CRDT state that several writers edit at once, merged change by change, with each other's presence visible. `--kind` names the surface; the document is the default.
| You want | Use | |---|---| | The live surfaces people co-edit (document, whiteboard, kanban, deck) | **this skill** | | A room's stored Context files (`get`/`put`/`rm` by name) | `room_ops context` (formerly `room_ops doc`) |
Two different stores. Writing to one never shows up in the other. This has already sent one agent to the wrong place, which is why the warning is here and not further down.
P=skills/room-collab/scripts/room_collab.py python3 $P presence '!room:server' # 0. which surfaces are live, who is in them python3 $P read '!room:server' # 1. the whole document — find the line that names you python3 $P append '!room:server' $'\n\n@you — <your reply>' # 2. answer UNDER it, signed python3 $P read --delta '!room:server' # every later return: only what changed since you last read
Then say one line in the room ("replied in the doc") — the person who called you is watching the room, not the document. With the lane env loaded no flag is needed. If a step fails, `doctor '!room:server'` reports every setup step (deps, token, URL, connect, read, peers) one line each and names the one that broke; it is for that, not for reading.
Every `read` remembers what you saw (per room and surface, under the workspace's `state/room-collab/`), so `read --delta` on your next visit prints only the lines that appeared since — the way a person skims what is new before rereading. The first read of a surface is all new. `--json` carries `delta` and `since` alongside the usual fields.
Use `append` to reply, not `replace`: your text lands where nobody else is typing, and the merge keeps everyone's characters. `replace` is for editing a sentence you own.
**To be seen in a surface, register — do not hold it open yourself.** Every subcommand except `watch` opens the document, does one thing and closes, so presence published by a `read` is gone before anyone looks. A summon asks you to *be* there, and your session is the wrong thing to hang that on: it ends, compacts or restarts, and your presence ends with it.
python3 $P stay '!room:server' # after reading a summon python3 $P --kind board stay '!room:server' python3 $P stay '!room:server' --leave # when you are done there
`stay` writes a record and exits; it holds nothing and needs no token. The presence daemon — supervised, outliving any session — reconciles toward that record, reconnects when a socket dies, and drops a surface after 30 minutes with no activity on it. Identity and presence name are resolved the same way every other subcommand resolves them, so the flagless form is correct.
`watch` still exists and still holds a connection, for watching a surface in the foreground and acting on each event. Use it for that, not for being seen.
**Global flags go BEFORE the subcommand.** `--url`, `--kind`, `--name`, `--json` belong to the program, not the command: `room_collab.py --kind board read <room>` works, `room_collab.py read <room> --kind board` is refused as "unrecognized arguments".
`websockets` and `pycrdt`. Two install routes; which one you need is decided by the python, not by preference.
**In a virtualenv, or on any python whose pip may install into it:**
pip install -r skills/room-collab/requirements.txt
**On a managed python — Homebrew or a Debian/Ubuntu system python —** that command refuses with `error: externally-managed-environment` (PEP 668). Install into a venv and invoke the skill with THAT interpreter; the skill's own `python3` is not it:
python3 -m venv ~/.venvs/room-collab ~/.venvs/room-collab/bin/pip install -r skills/room-collab/requirements.txt ~/.venvs/room-collab/bin/python3 skills/room-collab/scripts/room_collab.py read <room>
Do not reach for `pip --break-system-packages` to make the first command work: it writes into the python other services on the host share.
**The agent's ordinary relay token works.** The one every agent already holds in `channels/<lane>/.env` as `REMOTE_TASK_TOKEN` (or `AG2_REMOTE_TOKEN`) opens a room's surfaces; the service resolves it to the agent's own Matrix id. No per-agent Matrix token and no extra grant are needed. A Matrix access token also works.
The relay token ships in two shapes, **under the same variable names, on different installs**: bare (`secret`) or compound (`https://host/relay|secret`). Both are accepted here — the value is inspected, never the name. Passed to anything else, the compound form must be split on `|`.
Every surface has exactly the **room's own ACL**. core-api distinguishes non-member (404) from below-write-power (403), while the **WebSocket collapses every refusal into one close** — from the client you can only see "refused"
My AI Stand — Realtime by Day, Rewriting Itself by Night. Summon my AI superpower. Voice, vision, screen, meetings, calls when I'm engaged. Learns my patterns, ships its own code when I'm not. Runs across my Macs, interacts with people & their Stands.
Repo: sonichi/sutando
AG2 Space voice surface — binds the room the AG2 Space client announces to the voice session's origin, so work delegated by voice in a room is answered in that…
Streams what the agent is doing into the room, as rows the desktop client renders in an **events drawer** above the composer (collapsed: avatar, pulsing dots,…
Local Agent Registry — a standalone, dependency-free service that tracks running Claude Code (and other) agent instances. Agents self-register on startup and…
**Prefer the `ag2-space` MCP tools when they are connected and the room exposes them** — availability is per-room and per-actor, so check…
Deterministic final-answer normalizer — a last-step pass for any task that ends in a *precise* answer (a number, a short string, a comma-list). Applies the…
Transcribes audio files and voice notes to text via Gemini 2.5-flash. Integrates with Slack, Discord, and Telegram bridges so voice clips surface as readable…