Skip to Content

Skills

A skill is a deterministic, versioned procedure a scientist recognises: a first-in-human dose projection, an exposure-margin table, a non-compartmental extraction of PK parameters, a SAR table, an SOP readiness check. The same inputs give the same outputs; every intermediate value is listed; every number that comes from a guidance document names the document, its version and the date it was retrieved. The agent orchestrates and cites; it does not “reason” the number. Names are fixed in PRODUCT-CONTRACT.md section 12.4 and the design is ADR 0030.

Every skill on this page is designed until the R4 gates pass: GET /skills, GET /skills/{key} and the skill tool specifications report status: designed for every skill while R4_GATE_PASSED = False (verified in api/app/skills/registry.py:36); flipping it is the release act after the gate list passes. The three references of tox.fih_dose_projection were verified on 2026-09-16, so it keeps its preview candidacy for that day; it is still served designed until the flag flips. No qualification is claimed for any skill; outputs are inputs to a decision a person takes.

Where a skill runs and how it is recorded

Skills run on the server, never in the agent container, and every call is recorded the way every tool call is. Two classes:

  • Class A (numeric and checklist skills) are server-side read tools with a typed output schema and the function in api/app/skills/<name>.py. They inherit the allow-list, the live permission check, the tool_calls row, the audit row, the sanitiser and the plan gate.
  • Class B (library skills) run as worker jobs (skill_library_job; the chemistry library and the dataset conformance engine are pinned there and never in the agent image), started by the server-side handler and awaited under the existing job timeout.

A skill exercises the product’s existing <product>.agents.use permission; no permission key is added. Each call writes a tool_calls row with check_logic_version, inputs_hash, result_artifact_id and output_violations. A skill started from the workbench needs no model: POST /programs/{program_id}/skill-runs runs synchronously and stores a skill_result artifact with no run (run_id NULL, the persona_brief precedent). There is no skill_run run kind; run kinds stay 13 and artifact kinds become 12.

The result shape, SkillResult, is {skill_key, check_logic_version, inputs_hash, outputs, citations[], warnings[], reference_refs[], guidance_version, retrieved_on}; every output value carries its unit in UCUM and display form. On screen a skill output reads “Method: <name> (<guidance>, retrieved <date>), version n” with a “How this was computed” section listing the intermediate values and the rules applied.

Vocabulary layer

Every skill input passes through api/app/skills/vocab.py: UCUM unit codes with conversion tables (mass, concentration, AUC, dose per kg and per m²), species with default body weights and km factors, routes, dose forms, analyte and matrix labels. A value without a unit is refused 422 unit_required, and the error sits beside the unit field; nothing typed is lost.

Reference gate

Guidance constants live in api/app/skills/references.json, one entry per reference: {key, url, sha256, retrieved_on, version, supersession, constants, status: verified | to_verify}. skill-references-check runs in the API’s make check and in the release check and fails when a preview or available skill references a to_verify entry. Every output names the guidance version and the retrieval date, so a table computed under a superseded version says so.

Verified on 2026-09-16, 5 of 13 entries (the gate prints 5/13 references verified): fda_2005_mrsd, ema_2017_fih and ich_m3r2 (their sha256 values are in CLAIMS-REGISTER.md) and the two repo-internal entries assertion_model and sop_binding_rule. Still to_verify: pk_golden_synthetic_one_compartment and the seven R5 entries (ich_m10, ich_q1a_r2, ich_q2_r2_q14, ich_q9_r1_m4q_r1, fda_oos_2022, data_integrity_guidances, cfr_312_23). Fact (verified in api/app/skills/references.json, 13 entries, 5 verified) | Consequence: any page quoting six verified references reads five.

The R4 skills

Skill keyProduct; run role; owning workbench roleClassInputs (cited where marked)Output and fixed phrasesReference document
tox.fih_dose_projectionEvidence; evidence; dmpk_tox_scientistANOAEL per species with units (cited), species, body weights, safety factor (default 10), route; a species other than the most sensitive is a required human input with a rationaleHED per species, MRSD with the most sensitive species as default, the km table used; header “Projection for your decision, not a starting dose”; warnings “PAD/MABEL not computed” and “exposure-based projection not computed”FDA 2005 MRSD guidance (km factors; verified 2026-09-16); EMA 2017 FIH guideline, Rev. 1 (verified 2026-09-16); the M3(R2) exposure clause (verified 2026-09-16); version and retrieval date from references.json
tox.exposure_margin_tableEvidence; evidence; dmpk_tox_scientistANOAEL AUC and Cmax per species (cited), projected human exposures (cited)margins per species and endpoint as fold; units checkedarithmetic; no guidance constant
tox.pk_parameter_extractionEvidence; evidence; dmpk_tox_scientistAtable rows read through documents.read_table_rows or typed rows only; dose, route; explicit lambda_z_rule (default: best-fit adjusted R², at least three terminal points) and blq_rule (default: zero before Cmax, missing after), unitsCmax, Tmax, AUC to the last point (linear-up, log-down), AUC to infinity, half-life with the points used, CL/F, Vz/F; the output states the rules appliedgolden test against pk_golden_synthetic_one_compartment: a constructed one-compartment dataset with analytically known parameters, to_verify against a published dataset; the skill intends designed until one is cited (recorded 2026-09-16)
chem.sar_table_buildEvidence; evidence; medicinal_chemistB (chemistry library pinned)compounds, activity records (cited)a comparison_table with R-groups, potency, selectivity, ligand efficiency measures, properties, and a source and licence chip per cell; a share-alike line when any share-alike row is mixed innone
evidence.assertion_lintEvidence; evidence; allAdraft textassertion kinds tagged, uncited interpretations flagged; runs before every evidence.propose_*the assertion model
qa.check_readinessReview; review; qa_reviewerAa check and its accepted requirement setrows met and not met with SOP anchorsextends the container-local SOP binding, which is retired when this skill lands

Every skill key is <namespace>.<leaf> and constructs a read tool without tripping the forbidden-verb test. One consequence shapes three later names: the test rejects any leaf that contains a forbidden verb as a substring, so sign matches design, and the R5 skills are spelled tox.glp_tox_study_checklist, cmc.stability_study_plan and stats.study_adequacy_check.

Reserved for R5 and R6

Keys are fixed now so the tests can assert them; nothing below exists in code in R4 and nothing is presented as live.

Skill keyProduct; owning workbench roleClassReferenceRelease
chem.property_profileEvidence; medicinal_chemistBrule set and MPO source to verifyR5
tox.glp_tox_study_checklistPlans; dmpk_tox_scientistAM3(R2) sections (to verify)R5
dmpk.bioanalytical_method_checklistPlans; dmpk_tox_scientistAM10 (to verify)R5
bio.target_dossier, bio.assay_readiness_checklistEvidence; biologist_pharmacologist, computational_biologistAfixed orderR5
cmc.stability_study_planPlans; analytical_qc_scientist, cmc_process_scientistAQ1A(R2) (under revision; to verify)R5
cmc.method_suitability_checklistPlans; analytical_qc_scientistAQ2(R2), Q14R5
cmc.oos_oot_classificationEvidence; analytical_qc_scientist (hand-off to QA)AFDA OOS guidance (2006, revised 2022; sha to verify); output “investigation phase and candidate class”R5
formulation.excipient_compatibility_checklist, formulation.tox_formulation_checkPlans; formulation_scientistAfixed checklist; precedent through clinical.get_label_metadataR5
cmc.qbd_risk_table, cmc.ctd_module3_outlinePlans; cmc_process_scientistAQ9(R1), M4Q(R1)R5
reg.ind_module_outline, reg.citation_completenessPlans; medical_writerA21 CFR 312.23 items (text to verify)R5
reg.agency_question_log, reg.guidance_deltaEvidence; regulatory_strategistAguidance referencesR5
qa.deviation_classification_rubricReview; qa_reviewerAversioned rubricR5
qa.data_integrity_checklistReview; qa_reviewerAFDA 2018 data integrity guidance, MHRA 2018 GxP data integrity guidance, PIC/S PI 041 (to verify); rows attributable, legible, contemporaneous, original, accurate, complete, consistent, enduring, available; output “checked against <document> <version>”, never “data integrity assured”R5
stats.study_adequacy_checkPlans; biostatisticianAnoneR5
clinical.trial_precedent_scanEvidence; clinical_pharmacologist, regulatory_strategistAnoneR5
pm.critical_path_recalc, pm.decision_log_scaffoldProgress; program_manager, portfolio_headAnone; lens scorecards are linked, never attached as recordsR5
portfolio.go_no_go_dossierProgress; portfolio_headAnone; scorecards under “Rubric views (advisory)”R5
stats.send_conformance_reportPlans; biostatisticianB (conformance engine)CORER6
patent.mention_scanEvidence; ip_analyst, medicinal_chemistAheader “Compounds mentioned in patent documents; not claim coverage, not an opinion”; families listed “for counsel”; dedupe on family idR6

PK/PD simulation stays planned for R6 as a separate worker container.

Routes and DTOs

RouteRuleReturns
GET /skillsauthenticatedSkillOut[] {key, name, product, run_role, permission, skill_class, check_logic_version, input_schema, output_fields[], required_citations[], references[{key, version, retrieved_on, status}], status, release}; status is designed for every skill while R4_GATE_PASSED = False
GET /skills/{key}authenticatedSkillOut
POST /programs/{program_id}/skill-runsthe skill’s <product>.agents.use, checked per skillSkillRunIn {skill_key, inputs, citations?} -> SkillResultOut {artifact_id, skill_key, check_logic_version, inputs_hash, outputs: Record<string, SkillValue>, citations[], warnings[], reference_refs[], guidance_version?, retrieved_on?, created_at} where SkillValue {value, unit_ucum?, unit_display?}

Audit action: skill_run.start. Error codes: unit_required, unit_unsupported, unit_mismatch and invalid_input (422 and tool refusal; each carries field so the error sits beside the input it names; verified in api/app/skills/result.py:26-28). Budgets in a conversation: max_skill_runs_per_turn = 4.

Source: PRODUCT-CONTRACT.md sections 12.4, 12.7 and 12.8; PRODUCT-PLAN.md Part 9 section 4.4; api/app/tools/catalogue.py (FORBIDDEN_TOOL_VERBS and the substring check in ToolSpec.__post_init__; every key <namespace>.<leaf>); decisions/0030-skills-as-server-side-tools.md