* feat(ui): improve kanban UX, fix dialog scroll, remove delegation page - Kanban: reorder columns (blocked after pending), show blocked-by info on cards, clickable blocker links in task detail, framer-motion card animation between columns - Dialogs: standardize scroll pattern across all modals — header fixed, scrollbar flush with outer edge via negative margin trick - Remove delegation page, types, events, i18n, routes, and all references - Fix activity_logs NULL jsonb scan error (COALESCE) - Board header: show text labels on action buttons (desktop) * docs: comprehensive audit and update of all documentation - Update Go 1.25 → 1.26, PostgreSQL 15+ → 18 across all docs - Add 10 missing internal modules to CLAUDE.md project structure - Expand provider docs from 2 to 6 packages (Anthropic, OpenAI, DashScope, Claude CLI, ACP, Codex) - Add 8 missing store interfaces to data model docs (22 total) - Update bootstrap files from 7 to 13 templates - Expand tool inventory from ~35 to 60+ tools with media/KG/credential categories - Fix Team Task Board: add blocked status, 3 missing actions, V2 versioning, delegate restrictions - Remove all references to removed features: handoff, delegate_search, evaluate_loop, agent_links - Fix lane defaults (2/4/1 → 30/50/100/30), ghost file references, models.list → providers.models - Add SecureCLI, snapshot worker, cost calculation, pairing security docs - Comprehensive changelog catch-up - Trim docs/03-tools-system.md to 800-line limit
12 KiB
16 - Skill Publishing System
How agents create, register, and manage skills programmatically through the publish_skill builtin tool, working in tandem with the skill-creator core skill.
1. Overview
The skill publishing system bridges the gap between skill creation (filesystem) and skill management (database). It consists of two components:
| Component | Type | Purpose |
|---|---|---|
skill-creator |
Core skill (bundled) | Guides agents through skill design, implementation, testing, and optimization |
publish_skill |
Builtin tool | Registers a skill directory in the database, copies files to managed store, auto-grants to creating agent |
Without publish_skill, skills created by agents exist only on the filesystem and are invisible to the database-backed skill management system (no search, no grants, no UI visibility).
2. End-to-End Flow
Agent receives request to create a skill
│
▼
┌─────────────────────────────────────┐
│ 1. skill-creator skill activated │
│ Agent reads SKILL.md guidance │
│ Creates files via write_file: │
│ skills/my-skill/SKILL.md │
│ skills/my-skill/scripts/ │
│ skills/my-skill/references/ │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 2. publish_skill tool called │
│ publish_skill(path: "skills/ │
│ my-skill") │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 3. Tool executes: │
│ a. Validate SKILL.md + parse frontmatter │
│ b. Derive slug, validate format │
│ c. Check system skill conflict │
│ d. Compute SHA-256 hash │
│ e. Copy dir → skills-store/{slug}/{version}/ │
│ f. INSERT/UPSERT into skills table │
│ g. Auto-grant to calling agent │
│ h. Scan + report missing dependencies │
│ i. Bump loader cache version │
│ j. Generate embedding (async) │
└──────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 4. Result returned to agent: │
│ - Skill ID, slug, version │
│ - Grant confirmation │
│ - Dep warnings (if any) │
└─────────────────────────────────────┘
3. publish_skill Tool
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | yes | - | Path to skill directory containing SKILL.md (absolute or relative to workspace) |
Activation Conditions
The tool is registered at gateway startup when:
pgStores.Skillsis available (PostgreSQL skill store initialized)PGSkillStorehas at least one managed directory (skills-store/)- Skills loader is initialized
The tool appears in every agent's tool set — no per-agent configuration needed. Can be toggled via the builtin tools admin UI.
Context Values Used
| Context Key | Source | Purpose |
|---|---|---|
store.UserIDFromContext(ctx) |
WS connect / HTTP header | Skill owner + grant source |
store.AgentIDFromContext(ctx) |
Agent loop | Agent to auto-grant access to |
ToolWorkspaceFromCtx(ctx) |
Tool registry | Resolve relative paths |
SKILL.md Frontmatter Requirements
---
name: my-skill-name # REQUIRED — display name
description: What it does # Recommended — used for search + auto-activation
slug: my-skill-name # Optional — derived from name if absent
---
nameis mandatory; tool returns error if missingslugauto-derived viaSlugify(name)if not specified- Slug must match
^[a-z0-9][a-z0-9-]*[a-z0-9]$
4. Core Logic Details
4.1 Slug Validation
name: "My Awesome Skill"
→ Slugify → "my-awesome-skill"
→ SlugRegexp check → ✓ valid
Rejects: leading/trailing hyphens, uppercase, special chars, spaces.
4.2 System Skill Conflict Check
Prevents overwriting bundled skills (pdf, xlsx, docx, pptx, skill-creator, etc.):
if t.skills.IsSystemSkill(slug) {
return ErrorResult("slug conflicts with a system skill")
}
4.3 Versioned Storage
Skills are stored in versioned directories. Re-publishing the same slug increments the version:
skills-store/
├── my-skill/
│ ├── 1/
│ │ ├── SKILL.md
│ │ └── scripts/
│ └── 2/ ← re-publish creates new version
│ ├── SKILL.md
│ └── scripts/
GetNextVersion(slug) queries MAX(version) from the skills table (includes archived skills).
4.4 Database Upsert
Uses CreateSkillManaged() with ON CONFLICT(slug) DO UPDATE:
- New slug → INSERT with
visibility = 'private' - Existing slug → UPDATE name, description, version, file_path, file_hash
- Archived skill re-published → status reset to
'active' - Embedding generated asynchronously after insert/update
4.5 Auto-Grant
When the calling agent has a valid AgentID in context:
GrantToAgent(ctx, skillID, agentID, version, userID)
This also auto-promotes skill visibility from private → internal, making it accessible via ListAccessible() for the granted agent.
4.6 Dependency Scanning
After publishing, the tool runs static analysis on the skill's scripts/ directory:
- ScanSkillDeps — detects required binaries, Python imports, Node packages
- CheckSkillDeps — verifies each dependency is available on the system
- If missing deps found:
- Stored in
depsJSONB column viaStoreMissingDeps() - Warning returned to agent with specific missing packages
- Agent is guided to install via
exec(pip/npm) or inform the user
- Stored in
Unlike the HTTP upload handler, the tool does not archive the skill on missing deps — it warns and lets the agent decide.
4.7 Directory Copy Security
| Check | Action |
|---|---|
.. in relative path |
Skip (prevent traversal) |
| Symlinks | Skip (prevent escape) |
| System artifacts | Skip (.DS_Store, __MACOSX, Thumbs.db, etc.) |
| Total dir size > 20 MB | Reject with error |
5. skill-creator Skill
Activation Triggers
The skill-creator is a bundled system skill with a "pushy" description that triggers on:
- Creating new skills or extending agent capabilities
- Skill scripts, references, benchmark optimization
- Description optimization and eval testing
Creation Workflow
- Capture Intent — what, when, output
- Research — best practices via docs-seeker
- Plan — identify scripts, references, assets
- Initialize —
scripts/init_skill.py <name> --path <dir> - Write — implement SKILL.md + resources
- Test & Evaluate — eval suite with parallel runs
- Optimize Description — AI-powered trigger optimization
- Publish —
publish_skill(path: "skills/<name>") - Package (optional) — ZIP for external distribution
- Iterate — refine from feedback
Skill File Structure
skills/<skill-name>/
├── SKILL.md (required, <300 lines)
├── scripts/ (optional: executable code)
├── references/ (optional: docs loaded as-needed)
├── agents/ (optional: eval agent templates)
└── assets/ (optional: output resources)
Key Constraints
| Resource | Limit |
|---|---|
| Description | ≤1024 chars |
| SKILL.md | <300 lines |
| Each reference | <300 lines |
| Scripts | No limit (executed, not loaded into context) |
6. Database Schema
skills table (relevant columns)
| Column | Type | Purpose |
|---|---|---|
id |
UUID | Primary key |
slug |
VARCHAR(255) UNIQUE | Canonical identifier |
name |
VARCHAR(255) | Display name |
description |
TEXT | Auto-activation trigger text |
owner_id |
VARCHAR(255) | User who created (or "system") |
visibility |
VARCHAR(10) | private → internal (on grant) → public |
version |
INT | Increments on re-publish |
status |
VARCHAR(20) | active or archived |
is_system |
BOOLEAN | True for bundled skills |
enabled |
BOOLEAN | Admin toggle |
file_path |
TEXT | Filesystem path to versioned dir |
file_hash |
VARCHAR(64) | SHA-256 of SKILL.md |
deps |
JSONB | {"missing": ["pip:opencv", "python3"]} |
frontmatter |
JSONB | Parsed YAML metadata |
embedding |
vector(1536) | pgvector for similarity search |
skill_agent_grants table
| Column | Type | Purpose |
|---|---|---|
skill_id |
UUID FK | References skills |
agent_id |
UUID FK | References agents |
pinned_version |
INT | Stored but not used — agent always uses latest |
granted_by |
VARCHAR | User who granted |
7. Visibility & Access Model
publish_skill creates with visibility = "private"
│
▼
GrantToAgent auto-promotes → "internal"
│
▼
ListAccessible query includes:
- is_system = true (all system skills)
- visibility = 'public' (anyone)
- visibility = 'private' (owner only)
- visibility = 'internal' (agents/users with grants)
Revoking the last grant auto-demotes internal → private (atomic SQL).
8. Cache Invalidation
After publishing, two caches are bumped:
- PGSkillStore cache —
BumpVersion()setsversion = time.Now().UnixMilli(), invalidating theListSkills()cache (TTL 5min + version check) - Skills Loader cache —
loader.BumpVersion()invalidates the filesystem-based skill index used for system prompt injection
Next agent turn picks up the new skill in its tool set.
9. Related Files
| File | Purpose |
|---|---|
internal/tools/publish_skill.go |
Tool implementation |
internal/skills/helpers.go |
Shared helpers: ParseSkillFrontmatter, Slugify, IsSystemArtifact, SlugRegexp |
internal/store/pg/skills_crud.go |
DB operations: CreateSkillManaged, GetNextVersion, StoreMissingDeps |
internal/store/pg/skills_admin.go |
Admin operations: IsSystemSkill |
internal/store/pg/skills_grants.go |
GrantToAgent, RevokeFromAgent, ListAccessible |
internal/skills/loader.go |
Filesystem skill loader with priority hierarchy |
internal/skills/seeder.go |
System skill seeder (bundled → DB) |
internal/skills/dep_scanner.go |
Static analysis for skill dependencies |
internal/skills/dep_checker.go |
Runtime dependency verification |
internal/http/skills_upload.go |
HTTP ZIP upload handler (alternative to publish_skill) |
cmd/gateway.go |
Tool registration and gateway initialization |
cmd/gateway_builtin_tools.go |
Builtin tool seed data |
skills/skill-creator/SKILL.md |
Core skill instructions |