Agent: general
The default — the plain @-mention. An agent with a small, workspace-free toolset: it answers directly, reads the org's repositories and acts on their issues through Switchboard's GitHub credential, reads a linked URL, recalls retained source evidence and keeps its own working notes — so the everyday asks are answered here, and only code changes, PR reviews, and web research are handed to the other agents.
- Code:
src/agents/registry.ts(general,GENERAL_SYSTEM),src/tools/toolsets.ts(theassistanttoolset),src/tools/github.ts, default model in the deployed config (config/config.example.yamldocuments the key) - Docs: The agents and their toolsets, github-tools.md
- Budgets: 60 min / 16k tokens (the turn guard is derived: 360, six a minute — harness-pi.md item 15) · toolset
assistant
Behavior
- Answers directly and concisely in Slack-friendly formatting — the length is the shared brevity rule's (routing-and-config.md item 26): the answer first, nothing after it is complete. Its tools are the
assistanttoolset (github-tools.md items 4–5): the GitHub reads (github_repos,github_tree,github_file,github_search_code,github_issue_list,github_issue_get,github_pull_get,github_actions_run,github_actions_job_log), the issue writes (github_issue_create/update/comment/delete),web_fetch,update_status,recallandnotes— no shell, no file writes, noweb_search, no verdict or PR submission. - Runs on the model resolved from config. Short questions can finish promptly; the declared hour-long ceiling lets a multi-source lookup continue without a five-minute cutoff, unless a request boundary clips the effective lease. The three-minute write-up allowance remains inside that lease (harness-pi.md item 15). If the source lookup's budget ends without a write-up, the final answer states that the requested findings are unverified instead of claiming a result or presenting the generic budget sentence as a completed answer; it names a same-conversation
continuereply, without asking the person to repeat the question. A follow-up from the original requester reconstructs the original ask across successive budget-ended continuations, verifying each prior budget close and requester (including earlier thread pages), rather than trusting a prior source result; all new tool calls run under the follow-up requester's grant. An unreadable question fails closed, and a different sender cannot continue the previous requester's source lookup. An answer with partial findings remains labelled as partial. The ordinary-run outcome records the typed ending and raw write-up presence before fallback wording. The final card shows an absent or unknown answer separately from the unchanged source checklist; checked research steps never establish answer delivery. Same-requester continuation reads that durable budget ending, not words in the reply. A legacy budget close with no saved outcome fails closed. Research source lookups use the same boundary. - Never claims abilities it lacks and never fabricates: when a request needs a code change, a PR review, or web research it says so and points at the agent that can, in the person's own words, never as a directive line to type — the prompt says a plain message reaches those agents by itself (routing-and-config.md item 21: a change routes to
ship, the write door) and gives the plain-words form as the example ("in acme/api: fix the failing login test", "review<PR URL>"), and forbids handing back a command or anagent:…line. The redirect points at asking in plain words right where the person is — a follow-up in the same thread or anywhere in the channel: under the operator (routing-and-config.md item 29, on by default) the door reads every message, thread replies included, and starts the right agent from the person's own words — so the prompt forbids telling the person to post a new top-level message, re-post, re-ask elsewhere or retype anything (issue 2046: that retype hand-back is the shape record 0069 retires — a write askgeneralcannot run is the door's to hand to the ship route with the thread's words, never the person's to re-say). The prompt also forbids asserting a hand-off it cannot make — never "I'll hand this to the coding agent":generalcannot start another agent's run, so it never says it will hand off, route, forward or start anything (interim until the operator of record 0057 binds before any agent runs). A general answer that ends in "runagent:ship …" is the router's miss turned into the person's chore, the shape the door exists to remove; the redirect names what was found and how to ask, not what to type. When it acts, it reports exactly what the tool did (issue number + URL) and never claims an action it did not perform. A loosely-named repo ("the switchboard app") is resolved withgithub_reposor the thread, not by asking. Deleting an issue happens only on an explicit delete request — closing is an update; and since GitHub grants deletion only to a repo admin's user credential, the App-backed delete reports its refusal and offers to close instead (github-tools.md item 1). Regression pins: inventing a repo URL and telling the user to run git; bouncing "open an issue on the switchboard app" toagent:codingwith "I have no tools for that". - Runs on machine class
none(AgentDef.machine): a general ask never creates, reconnects, or touches a sandbox or workspace — even when remote execution (E2B/Cloudflare) is configured, and even when the sandbox credential is missing. The GitHub tools are REST calls in the bot process, not a workspace. See execution.md behavior 7. - Knows its own settings — and itself. Like every agent, its system prompt carries the dispatcher's config block (routing-and-config.md behavior 8) naming the agent/model that actually resolved and how users tune them, and the self-description block (behavior 11) saying what Switchboard is, which agents exist, how residents work, and where the source and specs live — so "what are your settings?" and "how does your resident system work?" are answered from fact, never with a confabulated "I'm stateless" or a public-web 404.
- Issue writes are permission-gated per repo (github-tools.md item 3): the resolved actor's compiled code access, checked before any API call: explicit
codeRepos, otherwise thereposfallback, plus additive human/surface grants and code-scope delegation intersections; a matching code-only grant covers a restricted repo without memory ownership; a refusal is reported to the user, not retried. - Runs on pi as a child of the bot. Like every preset it runs on the pi harness (harness-pi.md item 1); having no workspace, its pi is a child of the bot itself: none of pi's own shell or file tools, the
assistanttoolset relayed and run in the bot as the requesting user, pi reaching the model proxy over loopback, the same record (harness-pi.md item 12).
Validation criteria
| Criterion | Proof |
|---|---|
Toolset assistant, 60 min; the turn guard derived from the wall clock | [unit] src/agents/registry.test.ts::general: the assistant toolset*, ::the turn cap is a runaway guard derived from the wall clock…::* |
assistant = GitHub reads + issue writes + web_fetch + update_status + authorized recall + own-session notes; no shell, file writes or verdict/PR submission | [unit] src/tools/github.test.ts::toolset wiring::assistant holds GitHub, web_fetch, status, recall and notes without shell, file writes or verdict/PR submission |
Machine class none (coding and review declare repo-resident) | [unit] src/agents/registry.test.ts::machine class declarations: coding and review run on repo-resident; general and research on none |
| With remote execution configured, a general ask provisions no sandbox and still answers | [unit] src/core/dispatcher.test.ts::a general ask with remote execution configured provisions no sandbox and still answers |
Prompt names its GitHub tools, forbids claiming unperformed actions, redirects coding/review/research in plain words (the example ask, "review <PR URL>") and never as an agent:… line to type, never says "NO tools" | [unit] src/agents/registry.test.ts::general's prompt names its GitHub tools* |
| Prompt never promises a hand-off (cannot start another agent's run) and never sends the person to a new top-level message — the door reads thread replies (issue 2046) | [unit] src/agents/registry.test.ts::general's prompt never promises a hand-off and never sends the person to a new top-level message — the door reads thread replies (issue 2046) |
A plain mention opens an issue through github_issue_create and the reply quotes number + URL; a restricted repo refuses an ungranted user before the API | [unit] src/core/dispatcher.test.ts::self-description in the system prompt … and the github_* tools::a plain mention opens an issue*, ::the issue write is gated* |
| Budgeted source lookup after a restart and cut source call: without a write-up the answer states uncertainty and same-conversation continuation; the original requester can continue from the original question without replaying the source result, another requester cannot; a verified partial write-up keeps its findings | [unit] src/agents/registry.test.ts::general continues a budget-ended source question in its conversation without trusting a cut source result, src/core/dispatch/runLoop.test.ts::runLoop — the model turn and everything that rides on it::a restarted source read cut at the budget answers without invented findings and leaves the unfinished checklist open, src/core/dispatcher.test.ts::a follow-up seeds from its session (docs/reference/specs/session-log.md item 9)::a budget-ended source answer continues in the same conversation for its requester without replaying the cut source or another sender's access, ::a second budget-ended continuation keeps the original question instead of seeding continue twice, ::recovers the original question when several budgeted continuations exceed the thread page, ::refuses a repeated continuation when its original question is unavailable, src/core/dispatch/runLoop.test.ts::a resume with the answer in hand (the \finish` plan)::a budgeted source answer recovered after a restart keeps its original partial checklist on the reply card` |
| Plain question → direct answer in seconds | [agent] @switchboard what is a Durable Object? — expect a concise answer, status card showing general and single-digit seconds. |
| Settings question → truthful answer naming the resolved agent/model and the tuning commands | [unit] src/core/dispatcher.test.ts::config awareness in the system prompt::a default dispatch names the resolved agent+model and says config is tunable; live check in routing-and-config.md (behavior 8 [agent] row). Regression pin: general must never claim "stateless … no per-user or per-channel tuning". |
| Self question → answered from the About block | [agent] @switchboard how does your resident repo system work, and how do I add a repo? (fresh thread, no directive) — expect residents, repo onboard, the cap, and a pointer to docs/reference/specs/resident-repos.md; never "I have no access". |
| Issue ask → done, not redirected | [agent] @switchboard open an issue on the switchboard app with the title "foo" and the body "bar" → the reply quotes <owner>/<repo>#<n> + URL and the issue exists on GitHub. |
| Code-change / PR-review ask → honest redirect | [agent] @switchboard fix the flaky test in acme/api and open a PR (no agent: directive, fresh thread; only reachable with the router off, since a plain change ask routes to ship) — expect a redirect in plain words (what was found, how to ask for the change in a new message); no agent:… line to paste, no invented diffs, commands-to-run-yourself, or fabricated output. |
| 7: a general ask runs on pi as a child of the bot with the assistant toolset relayed and none of pi's own tools | [unit] src/core/dispatch/runLoop.test.ts::the pi harness — a preset without a workspace, as a child of the bot::* |
| A budget end with every research step checked still shows an unwritten answer explicitly; the typed ending and raw write-up presence persist independently of fallback prose and reply delivery, including restart | [unit] src/core/dispatch/runLoop.test.ts::runLoop — the model turn and everything that rides on it::an all-checked source lookup without a write-up retains its work and records the missing answer* |