Files
Fu-Jie_openwebui-extensions/plugins/pipes/github-copilot-sdk/SKILLS_BEST_PRACTICES.md
Fu-Jie 0c7201902c feat(github-copilot-sdk): add workspace skills support (v0.9.0) (#51)
* feat(github-copilot-sdk): add workspace skills support

- Introduce ENABLE_WORKSPACE_SKILLS valve to enable/disable workspace custom tools discovery
- Modify _build_session_config() to auto-load tools from .copilot-skills/ directory
- Add workspace_skills_example.py template with 3 working example tools
- Update README.md and README_CN.md with Workspace Skills guide and usage examples
- Create v0.9.0.md and v0.9.0_CN.md release notes
- Sync version to all docs files (index.md, index.zh.md, and main docs)
- Bump version from 0.8.0 to 0.9.0 across all 7+ locations

* docs: establish temp files handling policy (project-based, not /tmp)

- Add TEMP_FILES_POLICY.md guideline for all skills and workflows
- Update pr-submitter skill to use .temp/ directory instead of /tmp
- Update release-prep skill documentation with temp file convention
- Add .temp/ and .build/ entries to .gitignore
- Create internal policy memo in /memories/repo/

This policy ensures:
- All temporary files stay within project workspace (not system /tmp)
- Alignment with OpenWebUI workspace isolation principles
- Multi-user safety and cleanup traceability
- Consistent handling across all skills and development workflows

* fix(terminology): rename 'workspace skills' to 'workspace custom tools' for accuracy

The term 'Skills' in Anthropic context refers to instruction-based frameworks
(SKILL.md files with YAML frontmatter + markdown), not custom tool functions.

Our implementation uses @define_tool decorator to define custom tools that the
SDK auto-discovers from .copilot-skills/ directory. These are Tools, not Skills.

Changes:
- Rename ENABLE_WORKSPACE_SKILLS valve -> ENABLE_WORKSPACE_TOOLS
- Update all documentation (README, README_CN, docs, release notes)
- Fix section headings and descriptions throughout
- Ensure consistent terminology across all files

This is a terminology-only change; functionality remains identical.

* feat(pipes): release v0.9.0 of GitHub Copilot SDK Pipe

- Integrated OpenWebUI Skills Bridge and manage_skills tool
- Reinforced status bar stability with session_finalized logic
- Added persistent SDK config directory support

* docs(pipes): add comprehensive guides and v0.9.0 notes for Copilot SDK

- Added skill manager and best practices guides
- Added publishing tool documentation
- Included v0.9.0 release notes and deployment script
- Updated usage guides
2026-02-28 03:50:56 +08:00

7.6 KiB
Raw Blame History

Skills Best Practices

A concise guide to writing, organizing, and maintaining Copilot SDK skills effectively.


Understanding How Skills Work

Skills are not command-line tools. They are context-injected instruction sets:

  1. The Copilot SDK daemon reads every SKILL.md file from your skill_directories
  2. It extracts the YAML description field from each skill
  3. When the user sends a message, the SDK compares intent against all descriptions
  4. If a match is found, the SDK fires skill.invoked and injects the full SKILL.md body into the conversation as instructions
  5. The agent reads those instructions and executes them using bash, create_file, view_file, etc.

Key implication: never run a skill's name as a bash command (e.g., finance-reporting). The skill IS the instructions, not an executable.


Writing a Good description Field

The description in SKILL.md frontmatter is the primary trigger mechanism. The SDK uses it like a semantic router.

Do

  • Start with a verb: "Manage…", "Generate…", "Analyze…"
  • Include explicit "Use when:" scenarios — this is the most reliable trigger signal
  • Cover all the intent variations a user might express
description: Generate a PowerPoint presentation from an outline or topic.
  Use when: creating slides, building a deck, making a presentation, exporting to PPTX.

Don't

  • Vague descriptions: "A useful skill for various things"
  • Overlapping descriptions with other skills (causes misfires)
  • Omitting "Use when:" examples (reduces trigger reliability significantly)

Rule of Thumb

If two people would phrase the same request differently (e.g., "make slides" vs. "create a deck"), both phrasings should appear somewhere in the description.


Structure: What Goes Where

skill-name/
├── SKILL.md          ← Required. Frontmatter + core instructions
├── .owui_id          ← Auto-generated. DO NOT edit or delete
├── references/       ← Optional. Supplementary docs, loaded on demand
│   └── advanced.md
├── scripts/          ← Optional. Helper shell/Python scripts
└── assets/           ← Optional. Templates, sample files, static data

When to Use references/

Put content in references/ when it is:

  • Only needed for edge cases or advanced usage
  • Too long to read every time (> ~100 lines)
  • Reference material (API specs, format docs, examples)

Use progressive disclosure: the agent reads SKILL.md first, then loads a specific reference file only when the task requires it.

## Advanced Export Options

See [references/export-options.md](references/export-options.md) for the full list.

When to Inline in SKILL.md

Keep content in SKILL.md when it is:

  • Needed for every run of the skill
  • Short enough not to slow down context injection (< ~150 lines total)
  • Core to the skill's main workflow

Naming Conventions

Item Convention Example
Skill directory name kebab-case export-to-pptx
name field in frontmatter kebab-case, matches dir name export-to-pptx
Script filenames snake_case.py or snake_case.sh build_slide.py
Reference filenames kebab-case.md advanced-options.md

Avoid spaces and uppercase in skill directory names — the SDK uses the directory name as the skill identifier.


Writing Effective SKILL.md Instructions

Open With a Role Statement

Tell the agent who it is in this skill context:

# Export to PowerPoint

You are a presentation builder. Your job is to convert the user's content into a well-structured PPTX file using the scripts in this skill directory.

Use Imperative Steps

Write instructions as numbered steps, not prose:

1. Ask the user for the outline if not provided.
2. Run `python3 {scripts_dir}/build_slide.py --title "..." --output "{cwd}/output.pptx"`
3. Confirm success by checking the file exists.
4. Provide the user with the download path.

Handle Errors Explicitly

Tell the agent what to do when things go wrong:

If the script exits with a non-zero code, show the user the stderr output and ask how to proceed.

End With a Closing Instruction

After completing the task, summarize what was created and remind the user where to find the file.

Skill Scope

Each skill should do one thing well. Signs a skill is too broad:

  • The description has more than 45 "Use when:" entries covering unrelated domains
  • The SKILL.md is > 300 lines
  • You've added more than 3 reference files

When a skill grows too large, split it: one parent skill for routing + separate child skills per major function.


Managing the shared/ Directory

The shared/ directory is bidirectionally synced with the OpenWebUI database:

  • Skills created via the OpenWebUI UI are automatically imported into shared/
  • Skills created by the agent in shared/ are exported back to OpenWebUI at session start

Safe operations

Operation Method
Install from URL python3 {scripts_dir}/install_skill.py --url <url> --dest {shared_dir}
Create new skill mkdir -p {shared_dir}/<name>/ && create SKILL.md
Edit skill Read → modify → write SKILL.md
Delete skill rm -rf {shared_dir}/<name>/ (does NOT delete from OpenWebUI UI — do that separately)
List skills python3 {scripts_dir}/list_skills.py --path {shared_dir}

The .owui_id file

Every skill synced with OpenWebUI has a .owui_id file containing the database UUID. Never edit or delete this file — it is the link between the filesystem and OpenWebUI DB. If deleted, the skill will be treated as new on next sync and may create a duplicate.


Session Lifecycle Awareness

Skills are loaded once at session start. Changes made during a session take effect in the next session.

When What happens
Session starts SDK daemon reads all SKILL.md files; _sync_openwebui_skills runs bidirectional DB↔file sync
During a session New/edited/deleted skill files exist on disk but are NOT yet loaded by the daemon
After user starts new session New skills become available; edited descriptions take effect

Always tell the user after any create/edit/delete: "This change will take effect when you start a new session."


Anti-Patterns to Avoid

Anti-pattern Why it's bad Fix
Running <skill-name> as a bash command Skills are not executables Read the SKILL.md instructions and act with standard tools
Editing .owui_id Breaks DB sync Never touch it
Storing per-session state in SKILL.md SKILL.md is static instructions, not a state file Use separate workspace files for session state
Ultra-broad skill descriptions Causes false positives on every message Narrow to specific intent with "Use when:"
Putting all logic in one 500-line SKILL.md Slow context injection, hard to maintain Split into SKILL.md + references/*.md
Creating skills in /tmp Not persisted, not found by SDK Always create in {shared_dir}/

Quick Checklist for a New Skill

  • Directory name is kebab-case and matches the name field
  • description starts with a verb and has "Use when:" examples
  • SKILL.md opens with a role statement for the agent
  • Instructions use imperative numbered steps
  • Long reference content moved to references/
  • Scripts placed in scripts/
  • Confirmed: skill does NOT overlap in description with other loaded skills
  • User informed: "new skill takes effect next session"