| 1 | /** |
| 2 | * Agent skills (docs.g1t.sh/guides/agent-skills/): how an agent does a kind |
| 3 | * of work with the tools it already has. A skill never adds a tool or a |
| 4 | * permission: it names the tools it uses, and an agent without one of them |
| 5 | * (in a conversation whose people can't read code, say) is told that part |
| 6 | * isn't available there. |
| 7 | * |
| 8 | * Every skill is a folder in the open SKILL.md format (skill-format.ts). |
| 9 | * Agents load them progressively: each skill's name and when to use it are |
| 10 | * in the agent's instructions, and it reads the rest with `use_skill` when |
| 11 | * a request matches. |
| 12 | * |
| 13 | * Every agent starts with g1t's foundational skills, below, which are |
| 14 | * written out as SKILL.md too (`foundationalSkillMd`). Each says, ability by |
| 15 | * ability, what works today and what is coming, and the agent is told the |
| 16 | * same, so it never claims to do what it can't. A workspace's owners can |
| 17 | * turn any skill off for one agent (`WorkspaceAgent.skills_off`, which |
| 18 | * holds foundational ids and library skill ids); turning one off takes it |
| 19 | * out of the agent's instructions and leaves its tools as they were. |
| 20 | * |
| 21 | * The workspace's own skills (written, imported, saved from a session, or |
| 22 | * followed from a repository) are its skill library (skill-library.ts). |
| 23 | * |
| 24 | * Wire shapes are snake_case. |
| 25 | */ |
| 26 | |
| 27 | export type SkillCategory = "documents" | "research" | "data" | "code" | "communication" | "files"; |
| 28 | |
| 29 | /** Where a skill comes from: g1t's own, written in the workspace, from the Marketplace, or learned from finished work. */ |
| 30 | export type SkillSource = "foundational" | "workspace" | "marketplace" | "learned"; |
| 31 | |
| 32 | /** One thing a skill does, and whether it works today. */ |
| 33 | export type SkillAbility = { |
| 34 | /** Unique within its skill: `pdf`. */ |
| 35 | id: string; |
| 36 | /** What it does, as the Skills tab lists it: "Make PDFs". */ |
| 37 | label: string; |
| 38 | /** `ready` works today with the tools listed; `coming` is planned and the agent says so when asked. */ |
| 39 | status: "ready" | "coming"; |
| 40 | /** The agent's tools it uses; none for a coming ability. */ |
| 41 | tools: string[]; |
| 42 | /** A line on how, or what is missing: "From Markdown, as a file attached to a doc." */ |
| 43 | note: string; |
| 44 | }; |
| 45 | |
| 46 | export type AgentSkill = { |
| 47 | /** `documents`, unique among skills. */ |
| 48 | id: string; |
| 49 | name: string; |
| 50 | /** One line, as the Skills tab shows it. */ |
| 51 | description: string; |
| 52 | /** When to use it: the description in its SKILL.md, which agents read to choose it (skill-format.ts `foundationalSkillMd`). */ |
| 53 | when: string; |
| 54 | category: SkillCategory; |
| 55 | source: SkillSource; |
| 56 | /** Which release of it: foundational skills change with g1t's releases. */ |
| 57 | version: string; |
| 58 | /** |
| 59 | * The playbook, in the second person, as it is put in the agent's |
| 60 | * instructions while the skill is on. Coming abilities are added to it |
| 61 | * as what the agent can't do yet. |
| 62 | */ |
| 63 | instructions: string; |
| 64 | abilities: SkillAbility[]; |
| 65 | }; |
| 66 | |
| 67 | /** The foundational skills' release: they change together, with g1t. */ |
| 68 | export const FOUNDATIONAL_SKILLS_VERSION = "2026.10"; |
| 69 | |
| 70 | /** The formats `make_file` writes. */ |
| 71 | export const MAKE_FILE_FORMATS = ["pdf", "docx", "xlsx", "csv", "md"] as const; |
| 72 | export type MakeFileFormat = (typeof MAKE_FILE_FORMATS)[number]; |
| 73 | |
| 74 | const V = FOUNDATIONAL_SKILLS_VERSION; |
| 75 | |
| 76 | /** |
| 77 | * g1t's foundational skills, in the order the Skills tab shows them. The |
| 78 | * tools named are the agent tools in services/agents (src/tools.ts); a |
| 79 | * test there fails when one is named that doesn't exist. |
| 80 | */ |
| 81 | export const FOUNDATIONAL_SKILLS: AgentSkill[] = [ |
| 82 | { |
| 83 | id: "documents", |
| 84 | when: "Use when someone asks for a document: a PDF, a Word document, a spreadsheet or CSV, or a doc to read and edit together in Artifacts.", |
| 85 | name: "Documents", |
| 86 | description: "PDFs, Word documents, spreadsheets and docs in Artifacts.", |
| 87 | category: "documents", |
| 88 | source: "foundational", |
| 89 | version: V, |
| 90 | instructions: [ |
| 91 | "When someone asks for a document, give them the document, not a description of one.", |
| 92 | "- A doc to read and edit together: write it with create_artifact (Markdown: headings, lists, tables, task lists, callouts, Mermaid charts), or change one with edit_artifact.", |
| 93 | '- A file (a PDF, a Word document, a spreadsheet, a CSV): call make_file with the format. For pdf and docx, write the whole document as Markdown in content; for xlsx and csv, give the rows in sheets. Without an artifact, make_file makes a doc holding the content with the file attached; with one, it attaches the file to that doc. Link what it returns: "Here\'s the PDF: <link>".', |
| 94 | "- Write the finished thing: a title, short sections, real numbers and names from what you read. Never leave placeholders like [Company name] unless they asked for a template.", |
| 95 | "- PDFs and Word documents keep headings, paragraphs, bold, italic, code, lists, quotes and tables; images and charts don't carry into the file (they do in the doc). PDFs are in Latin script: say so if the text needs another.", |
| 96 | "- Long or many-step documents belong in a session (start_session), which reports back with the link.", |
| 97 | ].join("\n"), |
| 98 | abilities: [ |
| 99 | { id: "doc", label: "Write and edit docs in Artifacts", status: "ready", tools: ["create_artifact", "edit_artifact", "read_artifact"], note: "Markdown with tables, task lists, callouts and Mermaid charts, edited live with people." }, |
| 100 | { id: "pdf", label: "Make PDFs", status: "ready", tools: ["make_file"], note: "From Markdown, attached to a doc. Latin script." }, |
| 101 | { id: "docx", label: "Word documents", status: "ready", tools: ["make_file"], note: "A .docx from Markdown, attached to a doc." }, |
| 102 | { id: "xlsx", label: "Spreadsheets", status: "ready", tools: ["make_file"], note: "An .xlsx with one or more sheets, or a .csv." }, |
| 103 | { id: "slides", label: "Slide decks", status: "coming", tools: [], note: "Comes with slides in Artifacts. Until then, an outline as a doc or a PDF." }, |
| 104 | ], |
| 105 | }, |
| 106 | { |
| 107 | id: "research", |
| 108 | when: "Use when someone asks you to research, investigate or find out what is known about something, or wants a report with sources.", |
| 109 | name: "Research", |
| 110 | description: "Reports with sources, from what the workspace knows; the open web is coming.", |
| 111 | category: "research", |
| 112 | source: "foundational", |
| 113 | version: V, |
| 114 | instructions: [ |
| 115 | "When someone asks you to research something, find what is known before you write, and say where each fact comes from.", |
| 116 | "- Look in the workspace first: search_artifacts and read_artifact for specs, runbooks and decisions; search_code and read_file for how the code works; search_messages and read_thread for what was said.", |
| 117 | "- Report what you found, not what you expect: lead with the answer, then the evidence, and link every source (the artifact, file or thread). Say plainly what you couldn't find.", |
| 118 | "- A report worth keeping goes in a doc (create_artifact) with a Sources section at the end. Long research is a session's job (start_session).", |
| 119 | ].join("\n"), |
| 120 | abilities: [ |
| 121 | { id: "cite", label: "Reports with sources", status: "ready", tools: ["search_artifacts", "read_artifact", "search_code", "read_file", "search_messages", "read_thread", "create_artifact"], note: "From the workspace's docs, code and chat, each source linked." }, |
| 122 | { id: "search", label: "Search the web", status: "coming", tools: [], note: "Comes with web access, set per team." }, |
| 123 | { id: "browse", label: "Browse and read pages", status: "coming", tools: [], note: "Comes with web access, set per team." }, |
| 124 | ], |
| 125 | }, |
| 126 | { |
| 127 | id: "data", |
| 128 | when: "Use when someone asks about data: analysing a CSV, JSON, log or table, totals and comparisons, charts, or results as a spreadsheet.", |
| 129 | name: "Data", |
| 130 | description: "Analyze files and tables, chart the results and hand back a spreadsheet.", |
| 131 | category: "data", |
| 132 | source: "foundational", |
| 133 | version: V, |
| 134 | instructions: [ |
| 135 | "When someone asks about data, work from the data itself and show your working.", |
| 136 | "- Read it where it lives: a CSV, JSON or log file in a repository (read_file), or a table in a doc (read_artifact). Data pasted into the conversation counts too.", |
| 137 | "- You add up and compare by reasoning, not by running code, so keep tables small enough to check: count rows, say what you totalled, and round sensibly. Above a few hundred rows, say the result is an estimate, or ask for a summary.", |
| 138 | "- Charts: put a Mermaid chart in a doc. Bar or line: ```mermaid with xychart, a title, x-axis [labels], y-axis \"Unit\", then bar [values] or line [values]. Shares of a whole: pie with \"Label\" : value lines. Label axes and units.", |
| 139 | "- A table they'll work on goes back as a spreadsheet: make_file with format xlsx (or csv), header row first, numbers as numbers.", |
| 140 | ].join("\n"), |
| 141 | abilities: [ |
| 142 | { id: "analyze", label: "Analyze files and tables", status: "ready", tools: ["read_file", "read_artifact"], note: "CSV, JSON and logs in repositories, tables in docs. Worked by the model, not run as code." }, |
| 143 | { id: "charts", label: "Charts in docs", status: "ready", tools: ["create_artifact", "edit_artifact"], note: "Bar, line and pie charts, drawn from Mermaid in a doc." }, |
| 144 | { id: "export", label: "Spreadsheets of results", status: "ready", tools: ["make_file"], note: "An .xlsx or .csv attached to a doc." }, |
| 145 | { id: "dashboards", label: "Dashboards", status: "coming", tools: [], note: "Comes with dashboards in Artifacts." }, |
| 146 | { id: "sql", label: "Query databases and forks", status: "coming", tools: [], note: "Comes with workspace datasets and database connections." }, |
| 147 | ], |
| 148 | }, |
| 149 | { |
| 150 | id: "code", |
| 151 | when: "Use when the work is code: reading or explaining it, reviewing a pull request, or getting a change made.", |
| 152 | name: "Code", |
| 153 | description: "Read and review code, and get changes made as pull requests through issues.", |
| 154 | category: "code", |
| 155 | source: "foundational", |
| 156 | version: V, |
| 157 | instructions: [ |
| 158 | "When the work is code, read before you answer, and get changes made the way the team ships them.", |
| 159 | "- Find and read it: list_repositories, search_code, read_file; for history, recent_activity, get_issue and get_pull. Quote the lines you mean, with their path.", |
| 160 | "- Review on the pull request itself with review_pull (approve, request changes or comment), and leave findings with comment. Your review is advisory.", |
| 161 | "- To get a change made, draft an issue with draft_issue: what to change, why, where in the code, and how to tell it worked (the tests to add or run). Once it's filed, assigning it to @g1t makes the pull request on a runner, with checks and revisions.", |
| 162 | "- You don't run code yourself: never say you ran, built or tested something. Say what you'd run and why.", |
| 163 | ].join("\n"), |
| 164 | abilities: [ |
| 165 | { id: "read", label: "Read and explain code", status: "ready", tools: ["list_repositories", "search_code", "read_file", "recent_activity"], note: "In repositories everyone in the conversation can read." }, |
| 166 | { id: "review", label: "Review pull requests", status: "ready", tools: ["get_pull", "review_pull", "comment"], note: "Advisory: people still give the approvals a merge needs." }, |
| 167 | { id: "pr", label: "Open pull requests", status: "ready", tools: ["draft_issue"], note: "Through an issue assigned to @g1t, which makes the pull request on a runner." }, |
| 168 | { id: "run", label: "Run code on its runner", status: "coming", tools: [], note: "Comes with agents on runners." }, |
| 169 | { id: "test", label: "Write and run tests itself", status: "coming", tools: [], note: "Comes with agents on runners; @g1t runs them on issues today." }, |
| 170 | ], |
| 171 | }, |
| 172 | { |
| 173 | id: "communication", |
| 174 | when: "Use when someone asks you to draft an email or message, summarize a thread, or write a status update.", |
| 175 | name: "Communication", |
| 176 | description: "Draft emails and messages, and summarize threads.", |
| 177 | category: "communication", |
| 178 | source: "foundational", |
| 179 | version: V, |
| 180 | instructions: [ |
| 181 | "When someone asks you to write to people, or to catch them up, do it in their voice and keep it short.", |
| 182 | "- Drafts: write the email or message ready to send, with a subject line for an email, in a fenced block or a doc they can copy. You can't send email: say they send it.", |
| 183 | "- Summaries: read the thread first (read_thread, search_messages for related ones). Lead with what was decided and what is open, then who owns each next step, with links to the messages that matter.", |
| 184 | "- Status updates: from recent_activity, issues and pull requests, say what shipped, what is in progress and what is blocked.", |
| 185 | ].join("\n"), |
| 186 | abilities: [ |
| 187 | { id: "draft", label: "Draft emails and messages", status: "ready", tools: [], note: "Written ready to send; sending email is coming." }, |
| 188 | { id: "summarize", label: "Summarize threads", status: "ready", tools: ["search_messages", "read_thread"], note: "Decisions, open questions and owners, with links." }, |
| 189 | { id: "schedule", label: "Find times and book meetings", status: "coming", tools: [], note: "Comes with calendar integrations." }, |
| 190 | ], |
| 191 | }, |
| 192 | { |
| 193 | id: "files", |
| 194 | when: "Use when someone needs a file in another format, or a diagram such as a flowchart, sequence or timeline.", |
| 195 | name: "Files and media", |
| 196 | description: "Convert between formats, and draw diagrams.", |
| 197 | category: "files", |
| 198 | source: "foundational", |
| 199 | version: V, |
| 200 | instructions: [ |
| 201 | "When someone needs a file in another form, make it.", |
| 202 | "- Text, Markdown and tables convert to PDF, Word, Excel, CSV or Markdown with make_file. To convert a file from a repository or a doc, read it (read_file, read_artifact) and pass its content on.", |
| 203 | "- Diagrams (flows, sequences, timelines, org charts) are Mermaid fences in a doc (create_artifact).", |
| 204 | "- You can't see images or read scans, and you can't draw or edit images yet. Say so, and offer what you can do from text.", |
| 205 | ].join("\n"), |
| 206 | abilities: [ |
| 207 | { id: "convert", label: "Convert between formats", status: "ready", tools: ["make_file", "read_file", "read_artifact"], note: "Markdown, text and tables to PDF, Word, Excel, CSV or Markdown." }, |
| 208 | { id: "diagrams", label: "Diagrams", status: "ready", tools: ["create_artifact"], note: "Flowcharts, sequences and timelines from Mermaid in a doc." }, |
| 209 | { id: "ocr", label: "Read scans and images", status: "coming", tools: [], note: "Comes with image input for agents." }, |
| 210 | { id: "images", label: "Create and edit images", status: "coming", tools: [], note: "Comes with image models." }, |
| 211 | ], |
| 212 | }, |
| 213 | ]; |
| 214 | |
| 215 | /** The ids of the foundational skills. */ |
| 216 | export const FOUNDATIONAL_SKILL_IDS: readonly string[] = FOUNDATIONAL_SKILLS.map((skill) => skill.id); |
| 217 | |
| 218 | /** Every tool a skill's ready abilities use. */ |
| 219 | export function skillTools(skill: AgentSkill): string[] { |
| 220 | return [...new Set(skill.abilities.filter((ability) => ability.status === "ready").flatMap((ability) => ability.tools))]; |
| 221 | } |
| 222 | |
| 223 | /** Where skills come from, and which are here yet. */ |
| 224 | export const SKILL_SOURCES: { source: SkillSource; label: string; status: "live" | "coming"; description: string }[] = [ |
| 225 | { source: "foundational", label: "Foundational, from g1t", status: "live", description: "Every agent starts with them, updated with every release." }, |
| 226 | { source: "workspace", label: "Written or imported in your workspace", status: "live", description: "Your own skills, such as how you cut a release or your brand voice: written in the editor, uploaded as SKILL.md or a zip, or read from a repository." }, |
| 227 | { source: "learned", label: "Saved from a session", status: "live", description: "Drafted by the agent from a finished session, published after a person reviews it." }, |
| 228 | { source: "marketplace", label: "From the Marketplace", status: "coming", description: "Skills that extensions bring, added in one step." }, |
| 229 | ]; |
| 230 | |
| 231 | /** The foundational skills an agent has on: every one unless `off` names it. */ |
| 232 | export function skillsOn(off: readonly string[] | null | undefined): AgentSkill[] { |
| 233 | const skip = new Set(off ?? []); |
| 234 | return FOUNDATIONAL_SKILLS.filter((skill) => !skip.has(skill.id)); |
| 235 | } |