Terminology hazard. In the repository, “artifacts” means release versions and wire contracts — the declared registry of what each component ships and which contract revisions it speaks. It has nothing to do with the attachable resource library. The Gateway calls that library Resources, and so does this page.
The resource model
Everything attachable is either library-wide or room-scoped. A library-wide resource exists independent of any room and can attach to many; a room-scoped one is part of a single room and is deleted with it.Reference types
A reference records a type, an address and instructions. Switch ships types for Google Drive, Confluence, GitHub and Jira, and users can define new types for other integrations.Room-scoped documents
Room-scoped documents are the agent-writable kind. A room-scoped document is deleted with its room, records the agent that created it, and has a name unique within that room. An agent can change or delete only a document it created. Authorship is enforced, not advisory. Create, update and delete are not direct database writes from the caller’s side. Each is an operation switch-core serves, so the check that the document belongs to the room being asked from runs server-side rather than being trusted to the caller.Room groups
A group is a tree node with an optional parent. A room belongs to at most one group. Deleting a group doesn’t delete rooms. Its rooms become ungrouped, and its child groups are moved up to sit under whatever the deleted group sat under.Role leases
A lease is keyed to the agent and is room-agnostic: an agent holds at most one lease globally, whatever room the role lives in. Leases are heartbeat-based. A stale lease is logically free, and no reaper process sweeps it up, so the stored row alone never tells you a lease is dead . Code that reads one has to check freshness itself.Gateway and agent surfaces
Almost everything here is reachable from either side: from the Gateway, as a human operator with a cookie session, or as an agent operation invoked over HTTP. References, library documents, room-scoped documents, room groups, room links and roles all have both, backed by the same operations registry. Packages are the exception. Creating a package and editing its contents are Gateway-only. An agent can attach an existing package to a room it’s creating, but it can’t assemble one or change what’s inside. The Gateway attaches a package only to a room that already exists, and Switch Console has no package surface. An agent connecting to a room receives each attached package as its id, name, description, and instructions, with itsreferences and documents. The two arrive differently: references come complete, including their value, while documents come as metadata only and are fetched with load_internal_documents. Package contents aren’t merged into the room’s top-level references and documents lists, so a reference that reaches the room only through a package appears only under that package. A package’s contents are a set, with no order.
The ecosystem graph and the room-link graph are Gateway-only aggregations built for the dashboard.
Creating a room, in order
Room creation touches PostgreSQL and an external chat platform. The order is deliberate, and some of it exists to prevent specific bugs.1
Validate everything first
The attachments and the group id are validated before anything is provisioned, so a request naming a reference that doesn’t exist fails before anything exists to clean up: no orphaned room and no stray external channel.
2
Resolve the participants
The named agents are resolved, along with which of them should receive join events in this room.
3
Resolve the bridge
The room gets a named bridge, or no bridge at all if it’s internal-only, or the instance default. A default bridge that’s configured but not running raises here rather than quietly producing a room with no route out to a chat platform.
4
Settle the external channel
If the room is adopting an existing channel and the caller didn’t state its type, the adapter is asked what type it is. If a new channel is being created, the operator’s channel-creation switch is checked first, and then the adapter creates it.
5
Mark the channel as provisioning
Creating a channel makes the bot auto-join it, and that join arrives back as an inbound event before the room mapping is committed. Without the mark, the inbound handler doesn’t see the uncommitted mapping, concludes the channel is unknown, and creates a second Switch room for the same channel.
6
Create the room
The room itself is created. Everything after this point takes membership in it.
7
Persist in one transaction
The room row, its group, its agents, its roles and its seeded aliases are written and committed together, so the durable state either exists completely or not at all.
8
Register the mapping, and always clear the mark
The channel-to-room mapping is registered and the provisioning mark is cleared in a
finally, so a failure above doesn’t leave the channel permanently marked as provisioning.9
Invite the bridge client before any agent
The bridge client is invited ahead of every agent, because a client ignores events that predate its own join. A message posted before the bridge joins is filtered as a pre-join event and never reaches the external channel . The room looks active inside Switch and silent in Slack.
10
Populate the external channel
The agents and users are added on the platform side, so the channel’s membership matches the room’s.
11
Invite the remaining participants
The agent clients and the system clients are invited together, and then the membership rows are persisted and committed. Membership is an ordinary invitation, which managed clients auto-accept.
12
Attach references, packages and links
Attachment failures are collected per item rather than aborting the operation, so a bad reference costs you that attachment and not the room.
Internal rooms require at least one agent. A room with a bridge needs no agent. The check belongs to that route, not to this sequence, so the YAML route and the agent create_room operation don’t apply it.
Room lifecycle
- Update changes metadata, instructions, group membership and the agent list.
- Delete removes the room and everything scoped to it, including its room-scoped documents. Its channel stays unless the caller asks for
retire_channel(a query flag on the delete route, a body field on bulk delete, a checkbox in Switch Console that is off by default). When asked, Switch retires the channel through the adapter’sretire_channel: Slack and Mattermost archive it, Discord deletes it, the Telegram bot leaves the chat, and a Teams channel stays, because Switch isn’t granted permission to delete one. A direct room’s channel always stays. A channel that can’t be retired doesn’t block the delete: the room is deleted and the failure is returned, so the person can clean up by hand. Removing a whole connection deletes its rooms without retiring their channels, because by then the bot may have lost access. - Archive sets a reversible metadata-only flag. The room, the mapping and the membership stay as they were, and restoring the room brings it back without rerunning the provisioning sequence.
- Membership changes add or remove agents and users after the fact, on the same invitation model as creation.
- Moving a room to a different bridge re-points it at another external chat connection.
The durable model
Switch state lives in PostgreSQL besideswitch-core. The tables that hold rooms and resources:
rooms— the room plus Switch metadata: bridge, external channel, channel type, instructions, group, owner, visibility, archive flagroom_groupsandroom_links— the tree, and the directed graph over itroom_agents— which agents are in a room, with the alias and the join-event flagroom_rolesandrole_leases— roles defined per room, and who currently holds onereferences,documents,packagesand their association tables — the library and what it’s attached toagents— name, description, integration profile, owner, optional parent agent for subagents, addressing policyclientsandclient_rooms— one client per participant, and the rooms it’s incollaboration_bridges— a configured external chat connection; at most one is the defaultbridge_message_map— the Switch-to-external correlation, written in both directionsexternal_usersandexternal_user_claims— platform identity to puppet client, and the claims linking a platform account to a Switch useragent_sessionsandagent_runtime_states— reachability and transport-to-room binding, and what a live session is doing
Next steps
Identity and access
Ownership, what an agent inherits from its owner, and who’s allowed to make it respond
Share context
What references and documents are for, from a user’s point of view

