Collaboration
These collaboration surfaces ship by default. Want a different team workflow or an integration (Slack, Linear, …)? Ask the agent to build it — see Extending Cial.
Cial's team surfaces all ride the same cross-instance relay brokered by Citadel: the team channel for surrounding chat, presence for who's around, and shared sessions for working inside one agent conversation together. There is no shared compute — every instance keeps its own data and runs its own turns; the relay room is the only thing in common. All three are team features: on a solo setup there's no roster, channel, or relay to back them. Each can be shown or hidden per person under Settings → Discovery.
Team channel
A persistent, team-wide chat docked in the app shell, alongside your sessions, so the conversation stays close while a turn runs. Open it from the channel bubble; every member shares the one channel, and messages arrive live. It's for in-the-moment coordination — talk through a plan, then start a session to have the agent carry it out — not a shared agent conversation (that's a shared session).
Because messages expire after 7 days, the channel is for coordination, not record keeping. Anything that needs to last belongs somewhere durable — for example a knowledge your agent can use.
Presence
The Team page (Users icon in the sidebar) lists your whole roster with a live status dot per person. It updates on its own — no refresh — as teammates start working, step away, or return.
- Online — active right now.
- Idle — connected but inactive for a little while.
A glance at the roster tells you who's available before you start a conversation or invite someone into a shared session. Toggling presence off under Settings → Discovery only changes what you see; it doesn't remove you from teammates' rosters.
Shared sessions
A shared session lets you and a teammate work inside the same agent conversation,
live — same history, either of you can take a turn, each turn streams in for the
others. The model is run-on-your-own-instance: Cial creates a relay room
(session:{id}); every member joins it, but a turn always runs on the prompter's
own instance, against their own credentials and tools, and republishes the result
into the room. Everyone else's instance spectates and materializes what arrives. The
room is the only shared thing, so everything the UI renders — including a turn in
flight — is reconstructable from it: reload, reconnect, or join late and your
instance rebuilds the full picture.
The room is a few typed collections, each driving a specific surface:
messages— the durable, attributed conversation. Every finalized turn is materialized into every member's local DB with a sequence watermark, so the conversation is always shared and history reads from your own copy.live— the in-flight turn snapshot (status, who started it, streaming text/thinking/tools). Drives mid-turn recovery, the busy spinner, and the turn-lock.jsonl+jsonlhead— the engine's high-fidelity resume transcript shipped as deltas, plus an authoritative content hash. This is what the sync badge tracks.- typing / stream signals — ephemeral nudges for the typing indicator and smooth streaming between snapshots.
Sharing & discovery
Sharing is durable, not fire-and-forget. A share grants writer access, backfills the existing transcript, and writes a durable share record into a team-wide room alongside a best-effort instant nudge. Members reconcile on connect — reading those records and creating any missing shadow sessions — so a share is never lost because someone stepped away; they find it waiting in their sidebar next time they connect. Unsharing writes a revoke tombstone the same way, so a revoke also survives an offline recipient.
To share: open a session's share affordance, search your roster, pick a teammate, confirm — it appears in their sidebar (marked with a people icon). Only the owner can share, add, or remove people; collaborators hold a full shadow but don't see the share controls. To stop, the owner removes the teammate from the Share dialog.
Running a turn
The hard part of "no shared compute" is keeping context coherent when turns run on different machines. Cial converges every member onto one shared engine session id, so a single resume transcript accumulates everyone's turns in order. A turn-lock and a push-then-pull sync keep it convergent and race-free.
Before sending, your instance checks for another member's fresh live record; if one
exists your send is refused and the composer shows "name is responding…" until it
clears. Otherwise it pushes its transcript tail, pulls the merged transcript, resumes
the shared id (creating it on the first turn), and publishes the message + delta. If
the transcript hasn't propagated yet (a brand-new share, or a teammate who hasn't run
a turn), the turn falls back to a context summary rebuilt from the complete local
conversation — so the agent always gets full context, and an amber badge never
means lost context.
Collaborating live
- Anyone can prompt; the others watch. A spectator restores the in-flight bubble
from the room's
livesnapshot and smooths it with the streaming signals, so it looks just like watching your own turn. - One turn at a time. The turn-lock keeps two people from working the agent at cross purposes. The sidebar row shows an activity spinner and elapsed timer for the whole group — gated on the streamed turn start, even when spectating.
- Typing indicators. A throttled heartbeat shows "name is typing…" above the composer; it self-expires a few seconds after the last beat, and the server never echoes your own typing back.
- Mid-turn refresh. The running instance throttle-saves the streaming snapshot to
live(forced at tool boundaries), so a reload reconnects you to the recovered partial — exact text, reasoning, and tool activity — yours or a teammate's. A staleness guard prevents a phantom stuck turn.
The sync badge
Above the composer, the sync badge tracks whether your copy of the resume
transcript (jsonl) is byte-for-byte verified against your teammates' — a finer
signal than the conversation, which is always synced. After a member publishes
deltas it writes a content hash (jsonlhead); your instance rebuilds its transcript
from the full room log and compares hashes.
The badge resolves itself: a sync fires on join, on every transcript delta, before and after each turn, on a quiet background loop, and on opening the session — so opening one is enough to nudge it. "Not synced" does not mean anything is broken; the conversation is fully shared regardless, and the local-conversation fallback keeps turns working with no lost context.
Everyone on a shared session materializes the same conversation into their own database, so anything in the chat — including a secret value surfaced from a vault tool — is replicated to all collaborators. Be deliberate about which sessions you share, and review your vault under Settings → Tools.