Create a working Switch expert from the Templates view in two clicks (CHOO-2665) - #409
Draft
abeldantas wants to merge 54 commits into
Draft
abeldantas wants to merge 54 commits into
abeldantas wants to merge 54 commits into
Conversation
Three-step flow: paste YAML or pick a file → fill a form generated from the template's params block → POST to /rooms/from-yaml and navigate to the new room. Paramless templates skip straight to creation. Agent-name params (named exactly "agent" or ending in "_agent") render as a combobox over the live agent list with an inline warning when the name doesn't match. Required fields block submission with inline errors before any server call. Server 400s are mapped back to the offending field. Registered as "Templates" in the workspace sidebar nav. One appended entry each in view-ids.ts, view-registry.ts, and workspace-nav.tsx.
The package is "type": "module" so __dirname is undefined at runtime, crashing electron-vite dev on launch. import.meta.dirname is the ESM equivalent and works in both dev and packaged builds.
Two-column layout: form on left, "What this creates" summary panel on right showing a live preview of the room name (interpolated from inputs), which agents will be added, and template source info. Field labels now use humanized param names with description as helper text underneath. Agent-name fields show an inline "exists ✓" or "not found" badge inside the input. Fields with unchanged defaults show "(default kept)". Buttons are stacked full-width: "Back to template" + "Create room". Step indicator "Step N of 2" in the header. Parser now also extracts the agents list from the template's room block for the summary panel preview.
Make the YAML paste area taller (min-h-64) and vertically resizable so large templates are comfortable to work with. Use describeFailure's detail field directly for server errors instead of the HTTP-prefixed message, so the user sees "Unknown agents: foo" rather than "Could not create the room from this template. (HTTP 400: ...)".
…rors Pull the server's detail field from the RpcError before describeFailure wraps it with an HTTP prefix, so the user sees "Unknown agents: foo" rather than "HTTP 400: Unknown agents: foo".
Server side: new GET /gateway/rooms/template-schema endpoint returning the JSON Schema for a valid room template document, generated from Pydantic's TemplateDocument model (RoomSpec + ParamSpec). Console side: fetches the schema when the Templates view loads and validates the parsed YAML against it (via ajv) at the step 1→2 transition. Schema violations surface as parse errors before the form, so the user learns their template is invalid before filling anything out. Graceful degradation: if the server doesn't support the endpoint (404), validation is skipped. ajv added as an explicit dependency (was already present as a transitive dep).
abeldantas
force-pushed
the
work/import-ux
branch
from
September 9, 2026 09:56
31dd4fe to
b6fb543
Compare
When the schema endpoint returns 404 (server lacks params support), the parser now rejects unknown top-level keys like params: at step 1 with a clear message instead of letting the user fill a form that will fail at create time. Adds drag-and-drop support to the source step textarea — drop a YAML file onto it and it reads the same way the file picker does.
When the schema endpoint is unavailable, skip validation and let the server decide on create. The previous fallback rejected params: on any server without the schema endpoint, which blocked servers that support params but predate this PR's schema endpoint.
The room view reads from a MobX store that caches the rooms list. Navigating immediately after creation showed "still loading" because the store had no entry for the new room. Call refreshSidebarRoomState(true) before navigating — same pattern as CreateRoomModal.
The server reports users/refs/docs that couldn't be added in failedAttachments, but the Console discarded them. Now shows a warning toast naming each failed item so the user knows what didn't land — e.g. "abel.dantas (no account with this name is known on the bridge)".
The existing override mapped <4.3.0 to >=4.3.0, which resolved to 4.3.1 — still vulnerable to merge-key CPU exhaustion. Floor is now 4.3.2, the fixed release. Transitive only; the app's direct js-yaml (5.x) is not in the affected range.
The YAML provisioning path returned None when bridge was omitted, creating an internal-only room. This broke templates with users: since users live on a collaboration bridge. Now looks up the instance's default bridge (same behavior as the regular create-room endpoint).
abeldantas
force-pushed
the
work/switch-expert-template
branch
from
September 10, 2026 15:48
d74a784 to
64a427e
Compare
abeldantas
changed the base branch from
work/import-ux
to
work/template-registry
September 10, 2026 15:48
Hardcoded (non-interpolated) entries in a template's agents: and users: lists now appear in the form as editable, removable fields with live validation against the server's agent list. Before creation, the Console rewrites the YAML's agents/users arrays to reflect the user's edits — so removing an agent that doesn't exist on this server avoids the "Unknown agents" server error.
Specifying the same agent twice in a template's agents list (e.g. both coder and reviewer params resolved to the same agent) caused a 500 when trying to invite the same agent twice. Deduplicate early in _resolve_names_to_ids so all callers are covered.
The from-yaml provisioning path didn't add the creating user to the room, so they saw "unknown-channel" in Slack and the room didn't appear in their sidebar. Now the creator's username is always prepended to the users list (deduplicated), matching the regular create_room behavior.
Templates can now use {creator} anywhere in the room spec to reference
the signed-in user who creates the room. The server resolves it during
interpolation alongside param values. Template authors use it
explicitly (e.g. users: ["{creator}"]) rather than the server
auto-adding the creator unconditionally.
Reverts the unconditional auto-add from the previous commit — the
creator is only added when {creator} appears in the template.
It was added for the auto-add approach and is no longer used now that
{creator} handles it via parse-time builtins instead.
Built-in template variables now use a $ prefix to distinguish them from
user-defined params: {$creator}, {$date} (YYYY-MM-DD), {$timestamp}
(unix epoch). The placeholder regex is updated to match {$name}
patterns. $server deferred — needs a config dependency in the handler.
Two fixes for the template import flow:
1. Bridge user resolution now falls back to the platform's directory
search when a user isn't found in the DB. This resolves users who
exist on Slack but have never messaged through Switch — the adapter's
search_directory_users matches by username and email. Also adds
{$creator_email} builtin so templates can reference the creator's
email for resolution.
2. Templates can now include a kickoff: field — a message posted to the
room after creation to dispatch work to agents. The provisioning
protocol gains send_message so the YAML service can post directly
after room setup completes.
Fixes the 500 on kickoff by implementing send_message properly on
PostgresProvisioning — creates a Message row with all required fields
(transport_event_id, sender, event_type) instead of a partial object.
Makes user resolution more lenient: when the directory search returns
exactly one result (e.g. searching "Admin" finds one person), accept
it without requiring an exact username/email match. Catches RuntimeError
alongside NotImplementedError so a failed Slack API call doesn't crash.
Adds {$creator_email} builtin for email-based user resolution in
templates.
The kickoff crashed because Message.room_id is a FK to rooms.id (Switch room ID), but send_message received the transport room ID. Now resolves it via get_by_matrix_room_id first, matching the pattern used by invite_to_room and kick_user.
When a template specifies users by their gateway display name (e.g.
"Admin" from {$creator}), resolve them to their claimed bridge identity
(e.g. "dantas.abel" on Slack) before passing to room creation. This
uses the external_user_claims table — the same data the Console shows
as the linked identity on the Home page.
Users without a linked identity pass through unchanged and are resolved
by the bridge's own directory search.
…ff as the creating user The kickoff added in fc159b3 could never deliver: it wrote a raw messages row with the transport room id in the rooms.id column and no event id or event type, so every kickoff insert would fail — and even a well-formed system message addresses no agent by design. Replaced with a real path: - RoomService.post_kickoff sends the kickoff through the creating user's puppet, the same rail as a message they typed on the platform, so it addresses the agents it mentions and threads/attributes normally. - BridgeCore.post_as_user stamps SWITCH_ORIGINATED_MARKER and the outbound relay forwards marked puppet events to the platform instead of treating them as echoes, so the kickoff shows up in the external channel too. - Directory-search resolution now persists its hit (ExternalUser + puppet), so ensure_users_in_room — which used to skip anyone Switch had not seen speak — adds directory-resolved people to the room, not just the channel. - $creator resolves claims-first: builtins_for reads the template's bridge and answers with the creating user's linked identity there, falling back to the gateway account name. resolve_switch_user gives kickoff the same claims-first answer. - Kickoff failures land in failed_attachments (visible in the console toast) rather than failing a room that already exists. - Removed the dead send_message from the Provisioning port. Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
…zard
The wizard now answers the two questions that made template testing feel
bugged: will I be in this room, and what starts the work.
- "What this creates" lists the users being invited and, when the template
carries a kickoff, that it is posted as you; the kickoff preview renders
with your inputs filled in.
- Templates using {$creator} get a "You in this room" box: resolved via
your linked identity on the template's bridge, with a warning when no
identity is linked yet.
- The hardcoded-users list validates against the server's known bridge
users instead of flagging every name "not found"; unseen names say so
and note the directory is still tried at create time.
- Interpolated users ({$creator}) now survive the create rewrite — they
were silently dropped when a template mixed them with hardcoded names.
Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
The coder/reviewer-loop template used to exercise the import flow end to
end, now carrying the full surface: typed params with the _agent picker
convention, {$creator} membership, and a kickoff that dispatches both
agents. Doubles as the reference for template authors.
Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
A template param like a task brief carries a full document, and the wizard rendered every string param as a one-line input — pasting a brief stripped its newlines, flattening the Acceptance section the whole red-blue loop keys on. `multiline: true` on a string param is declared in the template, validated by the server's ParamSpec (so the schema advertises it), and rendered as a textarea by the Console. Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
Admin client ("Agent Switch") by default. Falls back to the creator's
puppet when any agent in the room has a restricted addressing policy
that would reject the admin — so owner-only agents still receive the
kickoff as an addressed message from their owner.
The check reads each room agent's addressing_policy from the DB and
uses AddressingPolicy.is_open() to decide. Creator identity params
(user_id, user_name, user_email) are passed through from rooms_yaml
for the fallback path.
Tested: ran local server, created room with kickoff (no agents = open
policy). Verified sender_id=@switch-admin:localhost, sender_name=admin.
64 tests pass.
NOT tested: restricted-policy fallback path (requires agents with
owner-only policy on a bridged room — not available on local stack).
is_open() returns False for policies with wildcard rules (users: '*', agents: '*') because it only checks len(rules)==0. A wildcard policy is functionally open — any user sender is accepted, including the admin bot. New check: _accepts_any_user() returns True when any rule has users='*', so wildcard policies correctly use the admin path. Only policies that restrict users to a specific list trigger the creator puppet fallback. Tested: local server, room with no agents. Kickoff posted by admin (sender_id=@switch-admin:localhost). 64 tests pass. NOT tested: wildcard-policy agents on a bridged room (not on local).
The admin client is not a "user" in the addressing system — agents with any addressing policy reject admin-posted messages, even with users:'*'. The creator puppet is the only sender that passes addressing checks. Bridged rooms: kickoff posted as the creator's puppet via post_as_user. Internal-only rooms (no bridge): best-effort via admin client since there's no puppet to use. Tested: local server, internal room kickoff via admin works. 64 tests pass. Bridged kickoff via creator puppet is the same code path Abel's merge (eef93ab) proved worked — this reverts the adaptive logic that broke it. NOT tested: bridged creator puppet path on local (no bridge).
Brings the branch up to date with main's multi-tenancy wave (CHOO-2623 RLS, tenant-scoped clients and sessions). The adaptations the merge needs are included: - post_kickoff loads the room through _load_room (tenant-scoped read) and passes room.tenant_id to get_by_type — the call CI flagged: the merge context made ClientLifecycleService.get_by_type require the tenant, since every tenant now has its own admin client. - The bridge-core test harnesses stub the attributes the tenant work added (_bridge_tenant_id, _channel_to_room, _room_tenant), mirroring how main's own outbound-rendering harness adapted. Claude-Session: https://claude.ai/code/session_017PdBwqBjgajRdMjLiFSiuA
The paste step now uses Monaco Editor with YAML syntax highlighting, line numbers, code folding, and auto-expanding height (grows with content, min 256px, max 600px). Drag-and-drop still works on the surrounding div. Monaco is already a dependency (@monaco-editor/react + monaco-editor). The gateway has a similar YAML editor (CodeMirror-based) — this uses the same concept but with the Console's existing Monaco integration. NOT tested: visual rendering (no display on this VM). Typecheck, lint, format all green.
abeldantas
force-pushed
the
work/switch-expert-template
branch
from
September 14, 2026 11:24
64a427e to
655ff0b
Compare
Collaborator
Author
E2E Screenshots — dev-abel @
|
# Conflicts: # core/switch_core/gateway/rooms.py
…ed locally The Templates view now reads the server catalogue from the template registry (CHOO-2677) instead of a parallel stored_templates table, which this branch previously carried. The bundled Switch expert ships inside the Console as a local template - it renders in the same listing and works with no server round trip. Registry rows map owner_name to the creator label; a template's content becomes the agent's instructions on create. (cherry picked from commit 64a427e) (cherry picked from commit 132b93b)
Adds repo_url (Text) and sources (JSONB) columns to the registry's templates table via a new migration. The template shape is now the full extractable pattern: persona + provider (user input) + repo + sources. - Replaces the 145-line bundled persona with the full switch-expert/ AGENT.md (~340 lines of system prompt + knowledge file references) - Bundled Switch-expert template declares repo sandbox-quantum/switch and 3 Switch docs source URLs - Template cards in the listing show repo URL and source count - Gateway client types carry repoUrl and sources - Room-template wizard: "+ Create" button on not-found agent-slot chips opens add-agent modal with the name prefilled - Add-agent modal gains prefillName prop for the wizard bridge All checks green: ruff, mypy, oxfmt, oxlint, tsgo typecheck. CHOO-2665. (cherry picked from commit 5ead81f) (cherry picked from commit 8c1ae0b)
…t is Switch" The expert agent receives the connector skill when it joins a room, so pointing it at connectors/*/skills/switch/SKILL.md in the clone sent it after something it already had. Route "what is Switch" and "why use it" to the repository README, whose framing and examples land better than a composed pitch. (cherry picked from commit ea4f7ee) (cherry picked from commit 548f0a3)
…g choices The expert told a user the working directory could be changed later in the agent's settings. It cannot: Switch Console sets it once on the new-agent dialog and has no update path. The editable "Repo dir" on the web dashboard only feeds the generated session command, which is what made this look changeable. Write out the four addressing choices with the owner included in "only me and my agents", and replace the blanket "never describe a UI" rule with an instruction to read the Console source in the clone. (cherry picked from commit e495a2d) (cherry picked from commit 7011134)
…ces columns (CHOO-2665) An agent template is a YAML document with an `agent:` block beside the optional `room:` and `kickoff:` it dispatches into, so `agent` joins the top-level keys the linter knows. The `repo_url` and `sources` columns added earlier go: the registry stores documents as they arrive and keeps the table still while the format moves, so the agent's repository and sources live in the document, where a second expert needs only a second document. The columns were never served by the API anyway. Also repairs three linter tests that treated `multiline` as an unknown param field; it is a known one now that CHOO-2656's format is on this branch. (cherry picked from commit ffffeeb)
…shape (CHOO-2665) switch-expert/template.yaml is the agent-template counterpart of the room template: the agent's name, description, repository and sources as data, plus the room it is put in and the message that starts it working. The persona stays in AGENT.md and is filled in at bundle time, so it is written once. examples/agent-templates/jq-expert.template.yaml is the same shape on a different subject, with its instructions inline, the way a template uploaded to a server carries them. (cherry picked from commit adc6ecb)
…(CHOO-2665) Picking a template used to prefill the description and instructions and stop there: the person still had to choose a directory by hand, and the agent then sat in no room with nobody talking to it, which is a registered agent, not a working one. Now "Use" parses the agent-template document (bundled or from the server's registry), the dialog suggests a directory named after the agent, and on submit the Console creates it, shallow-clones the template's repository inside, registers the agent, provisions the template's room with the person in it, posts the kickoff as them, and opens the room. The room-template wizard's "+ Create" on a missing agent slot offers the matching bundled template when one exists. The bundled Switch expert now reads switch-expert/template.yaml and AGENT.md from the repository root instead of a copy, so the expert the Console offers is the one the repository documents. The parsing lives in agent-template-format.ts, free of Electron, with tests; the controller wraps it with the directory and clone steps. (cherry picked from commit 83be7f6)
…ers them (CHOO-2665) switch-expert/AGENT.md opens with a Claude Code front matter block, and the Console writes its own when it renders .claude/agents/<name>.md, so the agent's definition file came out with two. The parser now drops a leading block from a template's instructions, inline or filled in from AGENT.md. (cherry picked from commit 655ff0b)
abeldantas
force-pushed
the
work/switch-expert-template
branch
from
September 14, 2026 13:30
655ff0b to
89eaebf
Compare
…h template does (CHOO-2665) Opened from a template, the dialog showed the full agent form with three hundred lines of instructions to scroll past, and a second person on a server learned that "switch-expert" was taken only after the directory and clone existed. Now the instructions fold to one line with Edit, a taken prefilled name moves to the first free variant with a note saying so, and the repository fetch and the room are each a switch the person can turn off. A template can declare who may address the agent (`addressing:` owner, owner-agents or anyone); the Switch expert says anyone, since a team shares it. The listing gains a search box, a Details fold per card (repository, sources, the room it starts in, who it answers, the first lines of its brief) and a notice when this computer has no usable agent provider, so the dead end is named before the dialog rather than inside it. Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…sion that answers (CHOO-2665) The room's first message is posted as the person, through their linked account on the room's bridge. Until now both halves were discovered after the click: a server with no messaging app got a room nobody could talk in, and an unlinked person got a red toast with a server error and a silent agent. The dialog now looks both up first and says what to do, with a button that swaps in the claim-identity dialog and hands back afterwards. When it goes through, the Console opens the agent's session as soon as it starts instead of leaving the person on a room page that shows nothing. Also: a template's `addressing:` is applied to the form, a bundled template can be saved to the server's registry from its card (persona inlined), and the agents page offers "From a template" beside the blank form. Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…te so it can update (CHOO-2665) Templates only reached a room by creating a new one, and the daily's ask was to dispatch an expert into the room someone is already working in. The add-agents-to-room dialog and the room's Configuration tab now offer the agent templates too: the agent is created and put in that room, and the toast says to mention it there, since only the room's own kickoff path can speak as the person. An agent's config file now records the template it came from (a new top-level `template` key, ignored by older Consoles), and its settings page offers "Update from <template>", which fills the editor with the template's current instructions and leaves the save to the person. The Switch expert's brief lives in the repository and moves; an agent created in August would otherwise keep August's copy for good. Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…2665) A template on a remote run location kept the old shape: a directory typed by hand, nothing made, nothing fetched. Now the same folder-per-agent layout is suggested under the host's home, the directory is created and the repository shallow-cloned over SSH on submit, and the fetch switch applies there as well. Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…nt (CHOO-2665) The suggested directory is named after the agent, so a leftover from an earlier install (a server since reset, an agent since removed) sits exactly where the next one wants to go, carrying the old credentials the add-agent pre-flight rightly refuses to overwrite. The person saw "name already taken" after the click. Now a directory that already holds a `.switch/` is skipped for `-2`, `-3`, on this machine and on a host. Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…ree" exit zero (CHOO-2665) Two reasons the remote directory suggestion never arrived. A bare `return` of the probe promise ran the `finally` that disposes the SSH context before the probes had run, so they were aborted; and `test -e` exits 1 for a free directory, which the runner reports as a failed command. Both branches now echo and exit zero, and the probes are awaited first. Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…2665) The block that says what a template will do read as a paragraph, and people do not read paragraphs in a dialog. One row per fact now: Repository, Sources, Room, Answers, each with its switch on the right, and the warning as one sentence with the fix beside it. Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…h no messaging app (CHOO-2665) The Room row carried "with you, kickoff sent as you" after the name; the name is the fact, the rest is how rooms work. The no-messaging-app line read as past tense and offered nothing to do; it now says the room would have no chat and carries a button to the server page to connect one. Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
…s (CHOO-2665)
The dialog warned "this server does not know which Slack account is
yours" whenever the person had no explicit claim on the bridge. The
server is more forgiving than that: for a kickoff it matches the
account's name and email against the platform when nothing is claimed,
and remembers a hit, so the warning fired on people the kickoff would
have served fine. A new `GET /collaborations/{id}/me` answers with the
same resolution the kickoff uses, and the dialog asks that instead of
reading the claims list.
Claude-Session: https://claude.ai/code/session_01GpmTz1MFhce8ekJoPZgqBn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.







Summary
In this PR we make the Switch expert something you get from the Templates view in two clicks, working: pick it, click "Add agent and open its room", and the agent is created, put in a room with you, spoken to, and answering. It reconciles #434 and #409 (and #436, stacked on it) into one branch on top of the merged template registry (#421), with #405 (the Create-from-template view) merged in underneath.
What an agent template is now: a YAML document with an
agent:block (name, description, instructions, the repository it works from, the pages it reads) beside an optionalroom:andkickoff:in the room-template shape.switch-expert/template.yamlis the first one and the field-by-field description of the format; the persona stays inAGENT.mdand is filled in at bundle time, so it is written once.examples/agent-templates/jq-expert.template.yamlis the same shape on a different subject, with inline instructions, the way a template uploaded to a server's registry carries them. Templates uploaded with kindagentshow in the same listing as the bundled one, with their owner as creator.What the Console does on "Add agent": suggests a directory named after the agent under the Console's locations directory, creates it, shallow-clones the template's repository inside, registers the agent (auto-session on, owner-only addressing, as before), provisions the template's room through
POST /rooms/from-yamlwith{agent}filled in, and opens it. The kickoff is posted as the creating person, which is what starts the agent working. The room-template wizard's "+ Create" on a missing agent slot opens the form filled from the matching bundled template when there is one.What we dropped from the earlier branches: the parallel
stored_templatestable and endpoints from #434 (the registry is the single store), and therepo_url/sourcescolumns from #436 (the registry stores documents as they arrive; the repository and sources live in the document, where a second expert needs only a second document, and the API never served the columns anyway). Kept from #434: the persona and knowledge fixes underswitch-expert/from August that never reached main.Server side this is small:
agentis a known top-level key for the registry linter, and{agent}counts as declared inside an agent template. Also repairs three linter tests that still treatedmultilineas an unknown param field; it is a known one once #405's format is on the branch, so #405 will hit the same three.The second pass, from a first-run user's seat
After the flow worked once, we went through it as someone who just installed the Console and fixed what stood between them and a working agent:
GET /collaborations/{id}/me, which resolves the caller the way a kickoff does (a claimed identity, else the account's name or email matched on the platform), so the warning fires only when the kickoff itself would fail. Missing either, it says so with the fix beside it (the claim dialog takes over and hands back; a button to the server page for connecting a messaging app).Testing
Live on a local stack (this branch's core and Console, Test Slack bridge): Templates → Switch expert → Use → Add agent and open its room. Directory created at
~/switchdash/repositories/switch-expertwithswitch/cloned inside, agent registered, room "Ask switch-expert" created on the bridge with me in it, kickoff posted as me, session auto-started, and the agent answered from its brief 32 seconds after the click (first check for a silent agent: is anything running it). A second template (the jq expert) uploaded to the registry with kindagentappeared in the listing and opened the same prefilled form. On an isolated stack for this branch (own Postgres, core on 8001, Test Slack bridge, identity linked): the two-click flow createdswitch-expertinto a stepped directory, provisioned the room, posted the kickoff as me, the Console opened the session on its own, and the agent answered 26 seconds after the kickoff. From the room's Configuration tab, "From a template" createdswitch-expert-2(auto-renamed) into that room with the toast. The settings page shows "Update from Switch expert" and reports already up to date. Save to server put the Switch expert on the registry, where it listed as "by Admin". Choosing the POC host as run location filled the directory with/home/ubuntu/switchdash/repositories/switch-expert-3, stepping past a taken folder on the host. Not exercised live: creating an agent on the remote host end to end, the wizard's "+ Create" from a matching template, and the name-or-email match behind/me(covered by unit tests; my test stack's admin account matches nothing on Slack).Checks: ruff, mypy,
test_template_lint.py(54 passed),test_collaboration_me.py(3 passed); Console typecheck, oxlint, oxfmt, vitest (agent-template-format 13 passed; one pre-existing failure insession-spawner.test.tsthat depends on this machine's Claude trust state, untouched here).https://claude.ai/code/session_01VNFGdRYHsohGjSdkJYgVtt