Skills

A skill is a short Markdown document describing how one specific task is done in this workspace — how a refund is approved, which fields a support case must carry, how to wire a new spotter. A chat carries a set of skills. The assistant is told their names and one-line descriptions up front and reads the bodies on demand, so a conversation pays for the skill it actually needs.

Skills are ordinary graph nodes (_Skill). They are editable from the admin UI and from the Build interface, they export and import with the rest of your configuration, and any assistant — not only the admin assistant — can carry them.

Two different things are called "skills"

The Sudo pages Read-only skills and Change skills group the operations the admin assistant can callintrospect-*, propose-*, apply-*, test-*. Those are AI tools, not the documents on this page.

The two do meet: the recipes Sudo reads before proposing anything (create-ai-tool, add-code-endpoint, graph-query-language, …) are built-in _Skill nodes of exactly the kind described here. See Sudo.

Skill, tool, or agent

Building block What it is What the model gets Reach for it when
Skill Markdown the model can read A name and one line in the system prompt; the body only when it reads the skill The model has to know a house rule, a procedure, or a convention
AI tool A C# class with [Tool] methods A callable function schema, every turn the tool is enabled The model has to do something — search, fetch, write
Agent A system prompt, a tool set and a model, packaged as one unit One call that runs a whole sub-conversation A task needs its own prompt, tools and several steps of its own

A skill changes what the assistant knows; a tool changes what it can do. A rule that has to hold for a whole conversation about a specific tool is a third thing again — that belongs in the tool's own [ToolSystemPrompt], which is paid for on every turn whether or not it is relevant.

What a skill holds

Field What it is for
Name How the model addresses the skill (read-skill takes it, matched case-insensitively) and how the UI labels it.
Description One line. This is the only part of the skill that goes into the system prompt, so it is what the model decides on — say what the skill covers, not that it exists.
Category Free-text grouping, shown beside the name in the admin list.
Icon UIcon name used in the admin list.
Content The Markdown body. Returned whole by read-skill, and indexed so search-skill can find it.

A body may contain ${…} placeholders that expand to generated API documentation when the skill is read — ${ToolScopeDocs}, ${CodeEndpointScope}, ${IQueryDocs} and similar. That is how the built-in skills stay current with the code-scope surface instead of restating it.

How a chat comes to carry skills

There are two ways in, and one rule that keeps them there.

From the assistant. An AI assistant carries a set of skills (SkillUIDs), chosen in the assistant editor. Every chat started from that assistant inherits them. This is the fallback whenever the caller does not choose.

Per turn, from the caller. A caller that drives the chat itself picks the skills explicitly:

  • useSkills on POST /api/chatai/post-message — a ;-separated list of skill UIDs;
  • enabledSkills on ChatAI.TriggerChatAsync — a SkillUID[].

Absent and empty mean different things: omitting the parameter means "not chosen" and falls back to the assistant's skills, while an empty list means "none".

A skill used once stays in the conversation. Each skill the run carries gets a _UsedToolOrAgent edge from the chat, and every skill the chat already carries is re-added on the next turn. The transcript keeps referring to what a skill said, so the model has to be able to re-read it later. The set only ever grows — the same rule already applied to tools and agents.

What the assistant is told

A run that carries at least one skill gets two things.

An # Available skills section on the system prompt, listing each skill by name and one-line description, sorted by name. The bodies stay out of the prompt. Sorting is not cosmetic: the same set of skills produces the same prompt bytes every turn, which is what lets the provider's prompt cache keep hitting.

A read-skill / search-skill pair, synthesised for that run:

Tool What it does
read-skill Takes a skill name and returns the full Markdown body, plus the skill's description and category.
search-skill Keyword search over the conversation's skills — name, description and body — returning a short snippet per match. Default 10 results, maximum 25.

Both are scoped to exactly the skills that conversation was given. The list is baked into the tool description, and it is also the whitelist: a name outside it is refused, with the allowed names returned so the model can correct itself. search-skill runs through the regular search pipeline as the calling user, restricted to those skills.

The workspace-wide skill reader is a different tool

skills-list / skills-search / skills-read reach every skill in the workspace. That tool is part of the admin assistant's surface and is attached deliberately — a chat never gets it automatically, and never reaches a skill it was not given.

Managing skills

Skills live under Manage → AI → Skills (#/manage/ai/skills), in the same Assistants group as Assistants, AI Tools and Agents. The page mirrors the Agents one:

  • List and search across name, description, category and body.
  • Add (+) opens the editor: name, description, category, and the Markdown body with a live preview.
  • Delete a workspace-authored skill.
  • Export downloads every workspace-authored skill as a zip of .md files.
  • Import takes that zip back.
  • The eye toggle reveals the read-only built-in skills, the same filter the Build interface applies to Sudo's built-in features. Built-ins open read-only — clone one to change it.

The same skills are editable from the Build interface, and Sudo can propose changes to them through propose-skill.

Built-in skills are reseeded on every boot

They are defined in code with deterministic UIDs, so they are re-applied at startup, excluded from exports, and skipped on import in both directions. Edit a copy rather than expecting an edit to a built-in to survive.

Pinning skills to an assistant

The AI assistant editor has a Skills multi-select next to Tools and Agents. What you pick there is what every chat started from that assistant carries.

Built-in skills are not offered in that list for a workspace-authored assistant — they describe tools such an assistant does not have, and the built-in admin assistant already reaches all of them through its own workspace-wide tool. The Tools and Agents dropdowns beside it apply the same filter.

Referencing a skill from workspace code

Code running in a workspace scope gets a generated Skills helper, next to AI_Tools and Agents (see Auto-generated Helpers). Each skill is a SkillUID keyed by the skill's name, with two helpers to convert between the UID and the name the skill-reading tools accept:

SkillUID uid  = Skills.RefundPolicy;                  // by name, as an identifier
string   name = Skills.GetSkillName(uid);             // "Refund Policy"
SkillUID same = Skills.GetSkillUID("Refund Policy");  // round-trips back

Member names are the skill names turned into valid C# identifiers; two skills whose names collide get a _2, _3 suffix. Because the helper is generated from the graph, renaming or deleting a skill surfaces as a compile error rather than a wrong result at runtime.

Pass the UIDs to TriggerChatAsync to start a chat that carries exactly those skills:

var chat    = await ChatAI.NewChatAsync(CurrentUser, chatName: "Refund request");
var message = await ChatAI.AddUserMessageAsync(chat.UID, CurrentUser, "Can we refund order 12345?");

await ChatAI.TriggerChatAsync(
    chat.UID,
    CurrentUser,
    message,
    enabledSkills: new[] { Skills.RefundPolicy, Skills.EscalationRules });

Skills travel with your definitions

Workspace-authored skills are part of the tracked workspace definitions, so they promote across environments the same way endpoints, tools and agents do:

  • Each one exports as a Markdown file under code/skills/ in the workspace-definitions zip, with its metadata in [skill: Curiosity.Skills.…] header lines above the body, and imports back under the same UID.
  • Built-in skills are excluded — they are reseeded from code on every boot.
  • An exported AI assistant pins its skills by UID. If you import an assistant whose skills are not in the same archive, the import records a warning naming the missing skill rather than silently dropping it — include the skills alongside the assistant.

Use export-workspace-definitions and import-workspace-definitions to move them from the command line, or the Skills page's own Export / Import buttons to move skills alone.

  • AI Tools — what a tool is, and how a tool contributes guidance to a whole conversation.
  • Built-in AI Tools — the tools every workspace already has.
  • AI Agents — packaging a prompt, a tool set and a model.
  • Sudo (Admin Assistant) — the assistant whose recipes are built-in skills.
© 2026 Curiosity. All rights reserved.