feat(skills): reload external skill inventory for an idle session
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 152
- Forks
- 16
- Avg merge
- 14h 48m
- Merged PRs (30d)
- 536
Description
User outcome
An authorized caller can explicitly reload externally configured skills for one existing session without restarting the server or affecting other sessions.
V1 is a silent model-facing reload: source and dispatch state refresh, but the model continues to receive the skill inventory it was already advertised. This preserves the provider prompt-cache generation. The initial user-facing affordance is /reload-skills in mecatui, backed by a server-owned control operation.
This is intentionally useful but incomplete for discovery:
- an already advertised skill whose body changed loads its refreshed body when invoked;
- a newly added skill is callable only when its name is supplied explicitly (for example, by the user through
/name), not through autonomous discovery from the stale model inventory; - a removed skill may remain advertised for the session and must return an honest unavailable/unknown result if invoked;
- the TUI may refresh its user-facing palette/inventory after a successful reload, but that must not alter the model-facing tool definition in V1.
Current behavior
External skills are deployment/build-lifetime snapshots:
tool.SkillSourceguarantees stableListSkillsoutput for the source lifetime and documents no watch/reload seam.- Local
skillfs.FSSourcesnapshots skill metadata andSKILL.mdbodies at construction; only an already-known skill's logical assets are disk-live. internal/appresolves the external skill seam once into process-widecatalogAssets.- The
Skilltool, skill-backed/<skill-name>commands, agent-definitionskills:preload index, and skill inventory/listing derive from that seam.
Today the Skill tool description embeds the full name/description inventory. Rebuilding it with changed metadata alters an early provider tool-definition input. Anthropic documents that changing tool definitions invalidates the entire tools/system/messages prompt-cache hierarchy; OpenAI likewise includes tool definitions in its rendered cache prefix.
V1 contract: silent model-facing reload
Add an explicit session-scoped ReloadSessionSkills control operation, exposed by the mecatui /reload-skills builtin.
- Caller supplies only the owned session ID; it cannot select directories, source URLs, workspace paths, or trust settings.
- Reload is accepted only for an inactive, non-awaiting session. Reject a live or awaiting run; do not queue an implicit reload or mutate state mid-turn.
- Re-resolve sources through the existing composition-owned
skillResolveOptions/resolveSkillSeampath. This must preserve configured precedence and reapply the project-ingestion trust gate; do not duplicate source resolution in the server handler. - Install a complete replacement external skill source/catalog for the target session through the existing engine-replacement lifecycle. A default session may need promotion from the shared default engine to a private per-session engine.
- Preserve the previous model-facing
Skilltool specification, including its advertised names/descriptions, while routingSkillactivation to the refreshed source/inventory. Do not alter the generic tool description, tools array, system prompt, or persisted conversation merely because reload occurred. - Rebuild user-initiated skill slash-command expansion and command-palette listing from the refreshed source. A user who knows a newly added name can invoke it; that does not imply the model discovers it unaided.
- Rebuild the agent-definition skill preload index for newly constructed specialist-agent engines, while leaving any model-visible generic inventory unchanged.
- Preserve non-skill session characteristics and catalog inputs: exact placement/profile, provider/model/mode, client-MCP attachment, global MCP, hooks, permissions, memory, and learning partitions.
- On discovery or engine-build failure, retain the currently installed session catalog unchanged. Return bounded status/count metadata only; no paths, skill bodies, source configuration, or private placement metadata.
- Reload is process-local and session-local in V1. It does not persist a separate external-skill generation; after server restart normal startup snapshot semantics apply.
Scope
internal/app: composition-owned session refresh factory/seam, using the existing skill source resolver and the singleassembleCatalogregistration path.internal/adapter/server: caller authorization, run/awaiting/lease checks, engine replacement, and an additive authenticated RPC/HTTP control operation.contracts/proto: additive control request/response if gRPC support is added; regenerate generated contracts.cmd/mecatui/clientandcmd/mecatui/ui: server collaborator,/reload-skillsbuiltin, and user-facing palette/inventory refetch.engine/adapter/skillfs: separate theSkilltool's advertised inventory from its refreshed activation inventory so V1 can preserve its priorToolSpecbyte-for-byte while serving refreshed bodies/known names.- User documentation: semantics, source/trust behavior, active-run rejection, silent-model-discovery limitation, and cache-preservation rationale.
Acceptance criteria
- A reload in session A cannot change source/dispatch state, tool metadata, slash commands, or agent preloads in session B.
- Active and awaiting sessions reject reload with a stable failed-precondition response; no engine/catalog is closed or swapped.
- A failed reload leaves the old source/catalog usable.
- The model-facing
Skilltool specification is byte-identical before and after a V1 reload, preserving the existing provider cache generation. - An already-advertised skill with a changed body returns the refreshed body after reload.
- A newly added skill can be activated by an explicit known name after reload but is absent from the model-facing inventory.
- A removed yet previously advertised skill fails honestly on activation; it is never silently substituted.
- User-facing palette and
/<skill-name>expansion reflect the refreshed source after successful reload. - Project-tier skills remain absent unless the existing trust decision admits them; explicit/user tiers retain their current behavior and precedence.
- Added, edited, removed, malformed, and name-shadowed external skills have deterministic results after reload.
- Existing learned-skill partitions retain their caller/project isolation if learning is enabled.
- Tests are offline; all normal engine/public API compatibility rules remain intact.
Deferred follow-on: model-visible, cache-aware inventory refresh
A later design may keep the generic Skill tool definition stable while delivering an updated skill name/description inventory through an append-only, late-positioned, trusted model-context notice. This should be treated as separate work, not smuggled into V1.
It requires a provider-neutral way to represent a mid-conversation harness/system reminder, provider-specific rendering and cache-breakpoint behavior, lifecycle/persistence semantics, and an atomic binding between the notice's advertised generation and the dispatchable source. It must not rewrite existing history, accumulate unbounded notices, or expose source paths/assets. This work may need extensions to the session and LLM-provider handling layers.
Non-goals
- Filesystem watching or automatic reload.
- Telling the model that a V1 reload occurred or updating its available-skill list.
- Process-wide reload or mutating shared
catalogAssets. - Reload during a live model/tool turn.
- Reusing learned-skill publication as a filesystem reload mechanism.
- Persisting reproducible external-skill generations across restart.
- Exposing paths/assets as workspace roots or making skill assets executable.
Relevant code
engine/tool/skillsource.go— external source snapshot contract.engine/adapter/skillfs/fssource.goandresolve.go— filesystem source snapshot, source locations, and precedence.engine/adapter/skillfs/tool.go— current coupled advertised/activation inventory.internal/app/build.go(skillResolveOptions,resolveSkillSeam,buildCommandExpander) — trust-gated composition and slash-command bridge.internal/app/catalog.go(catalogAssets,assembleCatalog,registerSkillFamily) — shared assets and canonical registration path.internal/adapter/server/service.go(engineAndEnvironmentFor, session engine replacement) — run-safe engine lifecycle.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with internal/app/build.go and catalog.go to trace skill resolution and canonical registration, then read engine/adapter/skillfs/tool.go and internal/adapter/server/service.go for inventory coupling and session engine replacement. Use the listed acceptance criteria as the completion check: inactive sessions reload independently, failed reloads preserve the old catalog, and the model-facing Skill ToolSpec remains byte-identical while refreshed activation and user commands work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, backend, cli, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 28/100