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.

Three surfaces, one relay
Citadel relaycross-instance rooms · single source of truthBrokers team-wide rooms; your instance reconciles each room into local state on connect.
Channel, presence, and shared sessions are independent rooms on the same Citadel relay. Your instance materializes each into its own local state.

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).

CapabilityDetail
MessagesSent to the whole team instantly; live typing indicator while a teammate composes
RepliesReply to a specific message; the quote keeps context as the channel scrolls
ReactionsEmoji react to acknowledge, vote, or thank without another message
AttachmentsUp to 4 files per message — screenshots, docs, anything the team needs to see
Edit / deleteEdit your own messages anytime; only the author can delete a message
RetentionRecent history kept; messages auto-clear after 7 days

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.

Run on your own instance
Owner instancecreated the session · manages membersThe creator. Only the owner can add or remove people.
session:{id} roomCitadel relay · source of truthEvery member materializes this room identically into their own local DB.
Collaborator instanceshadow copy · runs its own turnsHolds a shadow of the session pointing back to the owner; runs its own prompts locally.
The room joins every member; each prompt runs locally and republishes. No shared server — the room is the only thing in common.

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.

Share & discovery
Owner sharespicks a teammate
Grant + backfillwriter access · transcript copied in
Durable recordteam share row + nudgeThe durable record guarantees delivery; the nudge is best-effort.
Recipient reconcilescreates shadow · joins room
A share persists a durable team record plus an instant nudge; the recipient creates a local shadow either way.

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.

A shared turn, end to end
Turn-lockanother member running? → 'is responding…'One turn at a time, enforced across instances. A crashed holder self-clears via a staleness heartbeat.
Sync before turnpush your tail · pull merged transcriptPush-then-pull guarantees the resume never shrinks below what you just contributed.
Resume shared idappends to the one transcript
Publish + materializemessage + delta → room → everyone
The lock admits one member at a time; a sync pushes your tail and pulls the merged transcript before the engine resumes the one shared id; the result publishes back.

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 live snapshot 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.

What the badge means
Syncedgreen check · rebuilt transcript hashes byte-for-byte to the room head
Syncingpulsing dot · a rebuild + verify is in flight
Not syncedamber dot · not yet verified — often the other side hasn't published a transcript
A content-hash comparison of the resume transcript — not whether the conversation is shared. The conversation is always shared.

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.