Skip to Content
PlatformReferenceWorkbench roles

Workbench roles

A workbench role is the phase-4 layer over the ten personas. It is written in full everywhere, in the contract, in code identifiers (workbench_role*) and in copy (“Working as: Medicinal chemist”), and never shortened to “role”, because “role” is the RBAC role (roles, role_assignments, org.roles.*, program.roles.*). A workbench role selects a home screen, a rail, a toolset, skills, a prompt, a rubric and memory lenses. It never grants a permission. The fixed sentence shown on the picker is:

Workbench roles change what you see first, never what you may do

Authorisation stays with the persona bundle held through role_assignments. The agent’s effective toolset in a run is the intersection of three filters, none of which the workbench role widens: the role’s toolset, the tools of the run role, and the allow-list computed from the person’s live permissions. Names are fixed in PRODUCT-CONTRACT.md section 12.2 and decided in ADR 0027.

Every item on this page ships designed and moves to preview (on the illustrative program first, then partner programs) only when the R4 gate list at the end of this page passes. Nothing here runs for a customer today. Counts are R4 targets, re-derived on release by the owning test.

The fifteen

WORKBENCH_ROLE_VERSION = 1, EXPECTED_WORKBENCH_ROLE_COUNT = 15. The catalogue lives in api/app/auth/workbench_roles.py with a JSON export mirrored by web/lib/workbench-roles.ts and by WORKBENCH_ROLES in docs/lib/content.ts; two sync tests read the export. Record types are permission resources <product>.<resource> whose .manage key exists and is held by at least one mapped persona at persona version 3, so a proposal from a role can always be decided by someone who wears it. Where a person holds several personas, the mapped bundle is the union; sections of the role home appear only for personas the person holds.

KeyNameWhat they decideWhat they see firstRecord types (proposals land here)PersonaHarness at R4
medicinal_chemistMedicinal chemistwhich compounds to make next; series progression; which SAR hypotheses to testSAR tables by series, property profiles, notebook synthesis entries, assay resultsevidence.hypotheses, evidence.findings, evidence.questions, plans.experimentsScientistown prompt; preview candidate
biologist_pharmacologistBiologist / pharmacologisttarget validation calls; assay readiness and acceptance; which model answers which questiontarget dossier, assay protocols, pathway context, dose-response figuresevidence.questions, evidence.findings, plans.protocols, plans.experimentsScientistneutral scientist
dmpk_tox_scientistDMPK and toxicology scientist (bioanalytical and safety pharmacology folded in)dose-range and GLP study proposals; NOAEL interpretation as proposals; species rationale; FIH inputs; bioanalytical method suitabilityPK parameter tables, exposure margins, tox reports, read-across context, guidance textevidence.findings, evidence.gaps, plans.protocols, plans.reportsScientistown prompt; preview candidate
cmc_process_scientistCMC / process scientistroute, salt and form, batch strategy, specification proposals, tech transfer, supply for tox and FIHbatch records, impurity and stability tables, quality guidelines, supply datesplans.plans (both personas); progress.milestones, progress.dependencies (manufacturing specialist); plans.protocols, evidence.findings (scientist)Manufacturing specialist Scientistneutral of the persona held
clinical_pharmacologistClinical pharmacologist / translational lead (pharmacometrics and clinical operations folded in)FIH dose and escalation rationale; PK/PD plan; phase 1 design inputsNCA parameters, projections with inputs shown, label precedents, registry precedentsevidence.findings, evidence.hypotheses, plans.protocols, plans.reportsScientistneutral scientist
regulatory_strategistRegulatory strategistwhat to claim; agency questions; the pre-IND meeting package; which guidance governsguidance changes with version, precedent labels and trials, every open agency questionevidence.gaps, evidence.sources, evidence.questions, plans.reports; requirement sets are a hand-off to qa_reviewerScientistneutral scientist
medical_writerMedical writermodule structure; citation completeness; what is missing before filingthe outline with sources, every source behind every sentenceplans.reports, evidence.sourcesScientistneutral scientist
qa_reviewerQuality reviewer (QA)check outcomes, deviation classification, requirement-set acceptance; twin and memory oversightSOP text beside the record checked, version diffs, checks due, deviationsreview.sops (checks, requirement sets), review.findings, review.deviationsQuality reviewerneutral quality_reviewer
program_managerProgram managerplan approvals, open items, milestone changes, hand-off routingcritical path, decisions waiting on others, blockers, approvals older than a set number of daysprogress.milestones, progress.dependencies, progress.open_items, progress.approvals, plans.plans, program.handoffsProgram leadneutral program_lead
analytical_qc_scientistAnalytical / QC scientistmethod suitability, specifications, stability design, OOS and OOT candidate classificationmethod and stability designs, results and OOS candidatesplans.protocols, plans.reports, evidence.findings (oos_candidate finding kind; hand-off to QA)Scientistneutral scientist; skills R5
formulation_scientistFormulation scientisttox and FIH formulations, excipient compatibility, solubility enhancement, dose-form selectionformulation trials and studiesplans.protocols, plans.experiments, evidence.findings; progress.dependencies (manufacturing specialist)Scientist Manufacturing specialistneutral of the persona held; R5
computational_biologistComputational biologistgenetics, expression, structure and pathway callstarget hypotheses, datasets and sourcesevidence.findings, evidence.hypotheses, evidence.sourcesScientistneutral scientist; R5
biostatisticianBiostatisticiandesign adequacy, analysis plans, dataset conformance readinessdesigns and analysis plans, statistical reportsplans.protocols, plans.reports, evidence.findingsScientistneutral scientist; R5
ip_analystIP analyst (never legal advice)landscape completeness and which families go to counselpatent documents, landscape gapsevidence.sources, evidence.findings, evidence.gapsScientistneutral scientist; tools R6
portfolio_headPortfolio headthe go/no-go chair; a decider on evidencego/no-go decisions, program milestonesprogress.approvals; stage gates (R5)Program ownerneutral program_owner; R5

Two facts shape the QA and regulatory rows. Checks and requirement sets have no .manage key of their own: both are written under review.sops.manage, so the QA record types are spelled review.sops, review.findings and review.deviations, and “checks” and “requirement sets” are display groupings. The scientist does not hold review.sops.manage, so a regulatory strategist’s requirement set is a hand-off to the quality reviewer, never a proposal in the strategist’s own name.

Folded rather than added: the bioanalytical scientist and the safety pharmacologist into dmpk_tox_scientist (with the skills dmpk.bioanalytical_method_checklist and tox.pk_parameter_extraction), the pharmacometrician and clinical operations into clinical_pharmacologist. Roadmap, not keys: clinical operations lead, pharmacovigilance physician, data manager, alliance / BD. No workbench-role key equals a persona key (qa_reviewer, not quality_reviewer) and no key is a substring of any permission string.

What a role changes, and what it never changes

Changes with the workbench roleNever changes
the role home (/p/[slug]/home): four regions in fixed order, “Today’s decisions”, “My open questions”, “My evidence board”, “My program in this role’s terms”the permission bundle: PERSONA_VERSION stays 3 and no permission key is added in R4
the rail: the role’s products promoted, the rest under “All records”; Setup and Organization stay under “More” by permission (the program manager promotes Setup)the records: products stay the record of truth, the H1 keeps the contract record name and the role label is the subtitle
section labels from words.workbenchRoleLabels[<role_key>], for example “SAR hypotheses” for the chemist’s hypotheses or “Study designs” for the DMPK scientist’s protocolsthe approval matrix: who decides what is read from the personas alone
the harness the agent wears in a run: prompt, toolset, skills, rubric, memory lenses (harnesses)the assertion model, the proposal gate, the licence rules and the audit envelope
which duty templates a twin may run: R4 ships sar_refresh (medicinal chemist) and study_gate_check (DMPK and toxicology scientist); guidance_watch, stability_pull_reminder and shortage_watch are R5 and designed, held in the agent’s RESERVED_ROLE_TEMPLATES until their tools enter the catalogue (verified in agent/trovensa_agent/twins/duties.py:79-83); blocker_scan, pre_read and the QA four are persona templates that run whether or not the person wears the workbench rolethe twin’s authority for duties: twin runs keep persona_key

Every proposal made under a workbench role reads “Proposed by <Name>’s twin (agent, working as <workbench role>); decided by <Name>”, with the role name in the person’s words (“working as Medicinal chemist”). A run under a neutral persona harness reads “working as <persona name>”.

Choosing, assigning, falling back

  • Choosing (self): the picker on the program home, an inline segmented list or listbox in the header limited to the roles whose persona tuple intersects your personas, calls PATCH /me/settings with {workbench_role: {<program_id>: <role_key>}}. The value is stored per person and program in users.settings.workbench_role[program_id] (USER_SETTING_WORKBENCH_ROLE, the eighth USER_SETTING_* constant). A key you may not wear is refused 422 workbench_role_not_held and the error sits beside the picker. Audited workbench_role.set. See How to choose your workbench role.
  • Assigning (by a lead): PUT /programs/{program_id}/workbench-roles/{user_id} with {workbench_role_key, reason} under program.members.manage writes the member’s setting; the member’s header reads “Set by <Name> on <date>. Change” and audit records workbench_role.assign with the lead as actor and the member as target. On Setup › Members, “Assign workbench role” expands inside the member’s row.
  • Fallback when nothing is set: the agent wears the neutral persona harness (never a workbench role key): scientist -> scientist, quality reviewer -> quality_reviewer, program lead -> program_lead, program owner -> program_owner, manufacturing specialist -> manufacturing_specialist, viewer -> no harness (read-only console). With several personas the most senior wins in the fixed order owner > lead > quality reviewer > manufacturing specialist > scientist. The fallback never writes the setting: the home keeps showing “Choose your workbench role” until you or a lead sets it, and it is audited once per person and program as workbench_role.default_applied. The picker’s suggested first choice per persona (qa_reviewer, program_manager, portfolio_head, cmc_process_scientist) is copy, not a stored value.
  • Delegation: when a delegate acts for someone, the run acts as the delegate, the harness is the delegate’s, the memory read is the delegate’s own, the principal’s memory is never read or written, and proposed notes land in the delegate’s own memory tagged on_behalf_of. The inbox keeps “Deciding for <Name>” and “Routed under delegation from <Name>; decided by <Name> in their own right.”
  • Switching a workbench role mid-conversation never switches a running harness; a harness never changes inside a run.

Twin schedules shown beside a role stay the twin design’s illustrative defaults and are labelled so wherever they appear.

Coverage tests

Five tests in the API’s make check keep the layer honest: test_workbench_roles_cover_personas; test_workbench_roles_never_in_permissions (no key a substring of a permission string; no key equal to a persona key); test_record_types_are_permission_resources (every record type’s .manage key exists and is held by a mapped persona at persona version 3); test_harness_toolset_subset (every harness toolset key is in the tool catalogue, its permissions are a subset of the mapped personas’ bundles, and no untrusted-text tool sits in any toolset); test_workbench_role_labels (every label in words.workbenchRoleLabels differs from every contract record name and persona name and carries no vendor word). docs/lib/content.ts repeats the first two at typecheck time. The reader is not a workbench role; every harness delegates retrieval to the reader sub-agent.

Routes, DTOs and audit actions

RouteRuleReturns
GET /workbench-rolesauthenticatedWorkbenchRoleOut[] {key, name, personas, record_types, rail, harness_key, status, label_map_key, version: 1}
GET /programs/{program_id}/workbenchprogram.settings.readWorkbenchOut {workbench_role_key, name, decisions, other_decision_count, questions, pins, status_lines[{text, record_ref, as_of}], sources[{provider, status, verified_on?}], twin, memory_summary (at most 3), set_by?}; RecordRef {record_type, record_id, href}
PUT /programs/{program_id}/workbench-roles/{user_id}program.members.manageWorkbenchRoleAssign {workbench_role_key, reason} -> WorkbenchRoleAssignmentOut {user_id, program_id, workbench_role_key, set_by_user_id, set_at, reason}
PATCH /me/settingsauthenticatedUserSettingsUpdate.workbench_role?: Record<program_id, WorkbenchRoleKey | null>; null clears the program’s entry, audited workbench_role.set with new: null, and the role home returns to the persona home (contract 12.3, 2026-09-16)
GET /meauthenticatedMeOut.user carries settings: UserSettings (workbench_role included), so the web reads the workbench role from the identity call (contract 12.8)

Fact (verified in api/app/schemas/console.py:269, api/app/routers/me_settings.py:50-57, api/app/schemas/identity.py:70-74 and web/components/workbench/role-picker.tsx:128-131): the settings schema types the map as dict[uuid.UUID, str | None], the router pops a program’s entry for null, MeOut.user carries settings: UserSettings, and the picker offers Use the persona home whenever a role is set | Consequence: choosing, clearing and reading the role are built; the feature as a whole keeps the status word designed until the R4 gates pass.

Audit actions: workbench_role.set, workbench_role.assign, workbench_role.default_applied. Error code: workbench_role_not_held (422). Source statuses on the home: connected, not_connected, degraded; terms_changed (a weekly probe hashing each provider’s terms page) is R5 and designed (verified in api/app/db/models/connection.py:16: the status does not exist and rate_budgets has no terms columns).

The R4 gate list

Workbench roles, the evidence panel, skills and memory tiers move from designed to preview together, and only when every item below is green (contract 12.1, Part 9 section 8):

  • check and verify green on every repository; permissions in sync: 87; EXPECTED_TABLE_COUNT = 63; EXPECTED_ROUTE_COUNT = 206; EXPECTED_HARNESS_COUNT = 20; EXPECTED_WORKBENCH_ROLE_COUNT = 15.
  • The renderer-per-licence tests and the “abstract body withheld when the abstract’s own licence code is publisher copyright” test.
  • The two-organisation and two-program memory isolation tests; the injection fixture through every provider handler and through memory.propose_note.
  • The container tests: every flagged untrusted tool absent from every non-reader agent, documents.list_assets present, harness_denied handled, refusal lines present.
  • The skill golden tests and skill-references-check (5/13 references verified).
  • no-popups.lint.test.ts and the plumbing-word copy test inside the web app’s npm run check (recorded 2026-09-16; today they run under npm run test, which verify calls).
  • The screenshot set, taken by npm run shots:workbench against the running web and API, with zero browser console errors at 1440 and 390: two role homes; one CC BY article with a figure and its attribution line (PMC10000000.1); one no-derivatives source as a quote in context; one publisher-copyright source as metadata and link; one notebook entry; one rendered PDF page.
  • A live twin cycle under a harness on the illustrative program.

Reserved for later releases and never presented as live: the remaining harness prompts, lens reviews, tier 3 memory curation, stage gates and PERSONA_VERSION 4 (R5); ip_analyst tools, per-user connector grants, PK/PD simulation and organisation twins (R6).

Source: PRODUCT-CONTRACT.md sections 12.1, 12.2, 12.3, 12.7, 12.8 and 12.11; PRODUCT-PLAN.md Part 9 sections 2 and 3 and Part 8; api/app/auth/permissions.py (EXPECTED_PERMISSION_COUNT = 87; checks and requirement sets written under review.sops.manage); api/app/auth/personas.py (PERSONA_VERSION = 3); api/app/db/models/org.py and twin.py (the seven USER_SETTING_* constants before USER_SETTING_WORKBENCH_ROLE); forge.config.json (words.workbenchRoleLabels, words.plumbing); docs/lib/content.ts (WORKBENCH_ROLES, R4_TARGETS); decisions/0027-workbench-roles-as-ux-and-harness-layer.md; decisions/0031-harness-from-the-run-row.md