feat(skills): add skill authoring built-in

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
Naiyuan Qing
2026-06-01 14:16:48 +08:00
parent 1a820cca67
commit f08f1db219
3 changed files with 290 additions and 0 deletions

View File

@@ -409,3 +409,96 @@ The run with the skill passes if the agent:
### Why this belongs in a skill
Discovery is a conditional workflow. It should not live in the always-on brief because it only matters when the user needs a skill but does not know which one. It also needs product-specific guidance: discovery is not installation; Multica import remains the final source of truth.
## `multica-skill-authoring`
`multica-skill-authoring` exists because creating or updating a skill is not just writing Markdown. A Multica skill is durable workspace behavior: it has a trigger contract, reusable procedure, verification path, and optional supporting files that future agents will load on demand.
### Purpose
The skill teaches the agent how to decide whether a requested method deserves to become a skill, then create or update the workspace skill with the current Multica CLI. It also marks the future `--bundle-dir` workflow as the preferred path once that CLI support lands.
### Platform contract
The current workspace authoring surface is:
```bash
multica skill create --name <name> --description <description> --content <path-or-text> --output json
multica skill update <skill-id> --content <path-or-text> --output json
multica skill files upsert <skill-id> --path <relative-path> --content <path-or-text>
multica skill files delete <skill-id> <file-id>
multica skill get <skill-id> --output json
```
The source of truth is `server/cmd/multica/cmd_skill.go`, which exposes skill create/update/get and file upsert/delete, backed by `server/internal/handler/skill.go`.
The intended future bundle workflow is:
```bash
multica skill create --bundle-dir <dir> --output json
multica skill update <skill-id> --bundle-dir <dir> --output json
```
Until that lands, the skill must teach the current workaround: create/update main content, upsert supporting files one by one, then verify by reading the skill back.
### Without this skill
A prompt like this exercises the failure:
```text
Turn this workflow into a reusable Multica skill, include the reference template, and update it later if the process changes.
```
Without the skill, the agent may:
- write a one-off note instead of a workspace skill;
- create a vague skill whose `description` does not tell agents when to load it;
- omit verification and assume the create/update succeeded;
- put secrets, PR numbers, issue numbers, run timestamps, or temporary session notes into durable skill content;
- paste large examples into `SKILL.md` instead of supporting files;
- ignore the current CLI limitation and claim `--bundle-dir` already exists.
### Failure mode
The failure is durable. A bad skill pollutes future agent runs: it triggers at the wrong time, teaches stale facts, leaks sensitive or temporary data, or hides reusable assets in an oversized `SKILL.md` body. Unlike a bad issue comment, a bad skill keeps being rediscovered and reused.
### With this skill
With the skill, the agent must:
1. Confirm the workflow is reusable and not one-run progress.
2. Write a focused `SKILL.md` with frontmatter, a clear "Use when ..." description, steps, failure modes, verification, and source of truth.
3. Keep secrets, PR numbers, issue numbers, and temporary session notes out of the skill.
4. Put large reusable references, templates, scripts, or assets into supporting files.
5. Use the current CLI create/update/files workaround.
6. Run `multica skill get <skill-id> --output json` after writing and verify the returned content/files.
7. Prefer `--bundle-dir` once that follow-up CLI support exists.
### Test scenario
Use this prompt for an A/B evaluation:
```text
Create a Multica skill from this repeated code review workflow. Include a reusable checklist and a reference template. Do not include this PR number or today's run notes.
```
The run without the skill fails if the agent:
- writes only a comment or local file and does not create/update a workspace skill;
- includes temporary PR/session details in the skill;
- produces a description that cannot act as a trigger condition;
- forgets supporting files or verification;
- claims a future bundle-dir command exists before it is implemented.
The run with the skill passes if the agent:
- creates or updates through `multica skill create` / `multica skill update`;
- uses `skill files upsert` for reusable supporting files;
- verifies by reading the skill back;
- excludes secrets and temporary facts;
- clearly marks `--bundle-dir` as the future preferred path, not the current command.
### Why this belongs in a skill
Authoring is a conditional workflow. It should not live in the always-on brief, but it is important enough to be platform guidance because bad skills become durable agent behavior. The skill keeps the prompt lean while giving agents a concrete method when the user asks to create or maintain skills.

View File

@@ -0,0 +1,160 @@
---
name: multica-skill-authoring
description: Use when a user asks to create, edit, or maintain a Multica workspace skill. Teaches the current CLI workflow for SKILL.md content, metadata, supporting files, verification, and the future bundle-dir path without treating one-off notes as durable skills.
user-invocable: false
allowed-tools: Bash(multica *)
---
# Authoring Multica skills
Use this skill when the user asks to create, update, or maintain a Multica
workspace skill. This is different from finding an existing skill
(`multica-skill-discovery`) or importing a known URL (`multica-skill-importing`).
## The invariant
A Multica skill is durable workspace behavior. It should capture a reusable method,
platform rule, or tool workflow that future agents should apply on demand.
Do not create a skill for one-run progress, temporary TODOs, PR numbers, issue
numbers, session summaries, transient decisions, credentials, API keys, or other
secrets. Those belong in issue comments, issue metadata, project docs, or not at
all.
## Authoring standard
Every `SKILL.md` must have clear frontmatter and body guidance:
```md
---
name: short-slug
description: Use when ...
---
# Skill title
Use this skill when ...
```
The `description` is the trigger contract. Write it as a concise "Use when ..."
sentence so the agent can decide whether to load the skill before seeing the
body.
The body should cover:
- when to use the skill and when not to use it;
- the exact commands or APIs to run;
- verification steps that prove the work succeeded;
- failure modes and recovery rules;
- source of truth links to code, API, CLI, docs, or product behavior.
Keep the main body focused. Put large examples, templates, or reference material
in supporting files instead of bloating `SKILL.md`.
## Current create flow
Until bundle directory support exists, create the workspace skill from explicit
CLI fields:
```bash
multica skill create --name <name> --description <description> --content <path-or-text> --output json
```
Read the JSON response and keep the returned `id`. Do not claim the skill exists
until the create command succeeds.
If the content lives in a local `SKILL.md`, read the file first and pass its full
content as the `--content` value. The current CLI does not yet have
`--content-file` or `--bundle-dir`, so large content may require a wrapper script
or shell-safe command construction.
## Current update flow
Update an existing skill with the skill id or supported identifier:
```bash
multica skill update <skill-id> --content <path-or-text> --output json
```
Use `--name`, `--description`, or `--config` only when those fields actually need
to change. Avoid rewriting unrelated fields.
After update, verify by reading it back:
```bash
multica skill get <skill-id> --output json
```
Compare the returned `name`, `description`, `content`, `config`, and `files`
against what you intended.
## Supporting files
Use supporting files for reusable references, templates, scripts, and assets that
are too large or too specific for the main `SKILL.md`.
Current workaround for supporting files:
```bash
multica skill files upsert <skill-id> --path <relative-path> --content <path-or-text>
multica skill files delete <skill-id> <file-id>
multica skill get <skill-id> --output json
```
Recommended relative paths are stable, portable paths such as:
```text
references/<topic>.md
templates/<name>.md
scripts/<name>.sh
assets/<name>.<ext>
```
Do not store secrets in supporting files. Do not store one-off PR numbers, issue
numbers, run timestamps, or temporary session state. If the fact will be stale in
a week, it is not skill content.
## Future bundle directory path
When the CLI supports bundle directories, prefer the atomic local bundle flow:
```bash
multica skill create --bundle-dir <dir> --output json
multica skill update <skill-id> --bundle-dir <dir> --output json
```
Expected bundle shape:
```text
<dir>/SKILL.md
<dir>/references/...
<dir>/templates/...
<dir>/scripts/...
<dir>/assets/...
```
Until `--bundle-dir` lands, use the current workaround: create/update the main
content, then upsert supporting files one by one, then verify by reading it back.
## Quality gate
Before creating or updating a skill, check:
1. Is this reusable across future runs?
2. Is the trigger condition clear from the description alone?
3. Does it cite a real source of truth instead of relying on vibes?
4. Does it include verification steps?
5. Does it avoid secrets, temporary progress, PR numbers, issue numbers, and stale
session notes?
6. Are large examples moved into supporting files?
If the answer is no, do not create the skill yet. Write an issue comment or a doc
instead.
## Source of truth
- `server/cmd/multica/cmd_skill.go` implements `multica skill create`,
`multica skill update`, `multica skill get`, and `multica skill files upsert`.
- `server/internal/handler/skill.go` implements the workspace skill API.
- `docs/agent-skills/skill-necessity.md` records why built-in platform skills
exist and how to evaluate whether they work.

View File

@@ -255,6 +255,43 @@ func TestSkillDiscoverySkillCoversFindVerifyImportContracts(t *testing.T) {
}
}
func TestSkillAuthoringSkillCoversCreateUpdateMaintainContracts(t *testing.T) {
skill, ok := findSkill(t, "multica-skill-authoring")
if !ok {
return
}
fm, body, _ := splitFrontmatter(skill.Content)
if got := strings.TrimSpace(fm["user-invocable"]); got != "false" {
t.Errorf("user-invocable = %q, want false (skill authoring guidance triggers from context)", got)
}
if got := strings.TrimSpace(fm["allowed-tools"]); !strings.Contains(got, "Bash(multica *)") {
t.Errorf("allowed-tools = %q, want access to the Multica CLI", got)
}
mustContain := []string{
"multica skill create --name <name> --description <description> --content <path-or-text> --output json",
"multica skill update <skill-id> --content <path-or-text> --output json",
"multica skill files upsert <skill-id> --path <relative-path> --content <path-or-text>",
"multica skill files delete <skill-id> <file-id>",
"multica skill get <skill-id> --output json",
"SKILL.md",
"frontmatter",
"supporting files",
"secrets",
"PR numbers",
"--bundle-dir",
"current workaround",
"source of truth",
"verify by reading it back",
}
for _, want := range mustContain {
if !strings.Contains(body, want) {
t.Errorf("skill-authoring skill missing %q", want)
}
}
}
func findSkill(t *testing.T, name string) (AgentSkillData, bool) {
t.Helper()
for _, s := range loadBuiltinSkills() {