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