feat(skills): add manage-skills skill (RES-793)#37
Conversation
CRUD workflow for the orq.ai Skills entity (list/get/create/update/delete
via list_skills, get_skill, create_skill, update_skill, delete_skill — backed
by /v2/skills REST endpoints), plus authoring guidance, governance, and
workarounds for known platform caveats.
Includes:
- SKILL.md with 5 phases (list / get / create / update / delete + orphan
cleanup). Phase 5 uses a warn-then-offer flow with two explicit consents
(one for delete, one for the orphan-cleanup pass) — never auto-prunes.
- resources/authoring-guide.md — naming, description, tags, project scoping
- resources/governance-guide.md — wiring Skills to agents via agent.skills[],
ownership, lifecycle, audit checklist
- resources/known-caveats.md — INN-2861 (orphaned skill ids in agent.skills[]
after DELETE /v2/skills/{id}), INN-2836 (empty skill.version AND unstamped
skill.doc after snippet→skill migration), ENG-1604 (+NEVER+ prose
constraints treated as soft suggestions; recommends MCP tool gates)
- /manage-skills slash command — routes to phases by argument
- AGENTS.md, README.md skills table, and tests/skills.md + tests/commands.md
smoke-test scenarios
Version bumped 0.0.2 → 0.1.0 across all 4 plugin manifests (MINOR per
CLAUDE.md rules for a new skill). CHANGELOG.md entry added.
PR Review —
|
…ma, disambiguate
- Remove all internal ticket references (Linear IDs/URLs) from SKILL.md,
resources/, tests/, AGENTS.md, and CHANGELOG.md. Replace with
behavior-only descriptions.
- Switch to real /v2/skills field names: display_name, instructions,
project_id, skill_id, path. Drop name / body / doc / id_or_key
throughout.
- Drop the doc-field caveat entirely (the field does not exist in the
Skill schema). Empty-version-on-migration caveat retained.
- Document GET /v2/skills cursor pagination (limit / starting_after /
ending_before). Push project_id / tags / display_name filtering to
the client. Add explicit pagination loop pseudocode.
- Add POST /v2/skills:checkDisplayNameAvailability for pre-create
uniqueness checks; demote list_skills scan to fallback.
- Replace fabricated/wrong doc URLs:
* docs/skills/overview -> docs/prompt-snippets/overview
* drop /reference/skills
* docs/agents/skills -> docs/agents/build#skills
* add docs/integrations/code-assistants/skills for disambiguation
- Add top-of-SKILL.md disambiguation: platform Skill entity vs. this
repo's code-assistant Orq Skills vs. the Agent Skills standard.
- Document the {{skill.<key>}} static-template inlining path alongside
agent.skills[] runtime selection.
- Replace speculative agent-wiring snippet with a "mirror what
get_agent returned" pattern that handles both string-id and object
entries; flag the schema-version uncertainty explicitly.
- Soften display_name guidance — recommend the repo convention,
reference the API regex, do not enforce.
- Add path field guidance to authoring guide.
- Reframe optimize-prompt as heuristics-to-reuse (Skill instructions
are typically shorter / more capability-scoped than a system prompt).
- Replace allowed-tools glob with explicit MCP tool names.
- Note version is server-side only (do not pass in update_skill).
- Tests/skills.md updated to assert real field names and behaviors.
…ntax
Verified against orquesta-web apps/platform-api/skills (Go connect-rpc service),
apps/orq-mcp/src/tools/skills.tools.ts (MCP tool definitions), and
.openapi/fragments/platform-api/skills.json. Discovered several invented
endpoints/fields in the prior commit and a fictional consumption model.
Factual corrections:
- Drop {{skill.<key>}} template syntax. The real syntax is
{{snippet.<display_name>}} -- the Snippets->Skills rename kept the legacy
"snippet." prefix for backwards compatibility. There is no
{{skill.<...>}} placeholder anywhere in libs/go/template-parser or the
Studio UI.
- Drop the entire agent.skills[] orphan-cleanup workflow. Verified that
agent.skills[] is the AI-generated A2A AgentCardSkill[] field
(libs/models/agents/src/utils/index.ts -- generateAgentSkills), NOT a
list of platform Skill references. Deleting a platform Skill does not
orphan anything in agent.skills[]. The whole Phase 5 update_agent
fan-out targeted a non-existent relationship.
- Replace Phase 5 with a reference scan: paginate search_entities, fetch
each candidate's body with get_deployment / get_agent / get_skill, and
substring-match {{snippet.<display_name>}} (case-sensitive) to find
consumers before delete. Default to enabled: false (soft disable) when
references are found.
- Drop POST /v2/skills:checkDisplayNameAvailability. No such endpoint
exists on the SkillsService (verified all 5 methods in
apps/platform-api/skills/connect_routes.go: CreateSkill, ListSkills,
GetSkill, UpdateSkill, DeleteSkill). Replaced with: call create_skill
and handle the AlreadyExists error.
- Drop the version field. The Skill openapi schema has no version
property. Versioning is recorded as separate activity-log entries
(recordVersionActivity in connect_routes.go), not as a field. Drop the
empty-version migration caveat too -- no field to be empty.
- Add the enabled boolean field. It is on the real schema and surfaces
the soft-disable lever. Now documented in the field reference, in
Phase 4, and as a default-first-step alternative to delete in Phase 5.
- Add display_name rename warning to Phase 4. Renaming silently breaks
every {{snippet.<old-name>}} reference -- same failure mode as delete.
Same reference scan applies.
- Replace docs.orq.ai/docs/agents/build#skills (no such page) with
docs.orq.ai/docs/agents/agent-studio (where the snippet/skill section
actually lives).
Code hygiene:
- commands/manage-skills.md: replace allowed-tools: orq* glob with
explicit MCP tool names; add disable as an action; drop update_agent
references.
- Drop the "Why these constraints" generic justification paragraph.
- Add Scenario 5 to tests/skills.md covering AlreadyExists handling and
the disable-vs-delete decision.
- Add error-handling guidance for create_skill failures (AlreadyExists,
invalid project/path).
- /orq:quickstart reference updated to mention it is the Claude Code
invocation; other assistants run the equivalent onboarding flow.
…g caveat
Verified end-to-end against orquesta-web that two soft claims in the
prior commit needed harder hedges:
1. The /v2/skills CRUD API and the *_skill MCP tools live only on the
feature branch origin/thedevtoni/snippets-to-skills (a677849318,
19c26518f4, eedf87c1ca, c13f227567). They are NOT on
origin/main yet. A workspace pinned to a release without that branch
merged will not have list_skills / create_skill / etc. Added a
preflight check at the top of Prerequisites that probes list_skills
once and falls back to managing the entity under its legacy name
(Prompt Snippet via /v2/prompts/snippets) when the new tools are
missing.
2. The {{snippet.<display_name>}} renderer reads from the
PROMPT_SNIPPETS_KV Redis cache (libs/go/response-executor/snippets.go,
libs/platform/prompts/prompts-manager/src/lib/prompts-manager.ts).
That cache is populated only by the legacy
apps/workspaces-api/src/handlers/prompts-snippets/* handlers. The new
apps/platform-api/skills/connect_routes.go writes to MongoDB, records
a semantic-version activity, and publishes a NATS entity event -- but
nothing in the codebase consumes that event to update the snippet KV.
The only NATS consumer (apps/responses-api/consumers/entity_event_consumer.go)
handles agent.deleted only. So a Skill created via the new API may
not be reachable via {{snippet.<display_name>}} until a bridge lands.
Added a "Renderer wiring lag" caveat in known-caveats.md plus a
test-render verification step, and softened the enabled-field row in
the SKILL.md field reference to flag the same gap.
Both findings come from tracing the resolver code; if the wiring lands
later (NATS subscriber that mirrors skill.* events into the KV, or the
resolver moved to read MongoDB directly), the caveats can be removed.
Closes RES-793 (sub-issue of RES-790).
Summary
Adds the
manage-skillsskill — a full CRUD workflow for the orq.ai Skills entity, plus authoring guidance, governance, and documented workarounds for three known platform issues.What's in this PR
New files
skills/manage-skills/SKILL.md— 5-phase workflow:list_skills)get_skill) — defensively handles INN-2836 emptyversionanddoccreate_skill) — gathers name/description/tags/project scope/body with validation, flags+NEVER+prose constraints (ENG-1604)update_skill) — alwaysget_skillfirst, patches explicit fields, routes body rewrites throughoptimize-promptdelete_skill) — warn → confirm delete → offer prune separately with two explicit consents; never auto-prunesagent.skills[](INN-2861 workaround)skills/manage-skills/resources/authoring-guide.md— naming, description, tags, project scopingskills/manage-skills/resources/governance-guide.md— wiring Skills to agents viaagent.skills[], ownership conventions, lifecycle, quarterly audit checklistskills/manage-skills/resources/known-caveats.md— INN-2861, INN-2836, ENG-1604 with workaroundscommands/manage-skills.md—/manage-skills [list|get|create|update|delete] [name-or-id]slash commandModified files
agents/AGENTS.md— registered skill in path list +<available_skills>blockREADME.md— added row to skills tabletests/skills.md— 4 smoke-test scenarios + Critical Files entriestests/commands.md— slash-command smoke tests.claude-plugin/plugin.json,.codex-plugin/plugin.json,.cursor-plugin/plugin.json— bumped 0.0.2 → 0.1.0 (MINOR per CLAUDE.md rules for a new skill;plugins/orq/.codex-plugin/plugin.jsonis a symlink and inherits)CHANGELOG.md—## [0.1.0] - 2026-05-14entryTicket criteria coverage
list_skills,get_skill,create_skill,update_skill,delete_skill/v2/skillsendpoints) documented for workspaces where the MCP tools aren't exposedresources/authoring-guide.md(all 4 sections) + Phase 3 step 1 enforces themagent.skills[])resources/governance-guide.md"Wiring Skills to Agents" + Phase 3 step 4 offers to wire after createagent.skills[]afterDELETE /v2/skills/{id}resources/known-caveats.mddocuments workaround; SKILL.md Phase 5 implements warn-then-offer flow (never auto-prunes)skill.versionempty +skill.docnever stampedresources/known-caveats.mdcovers BOTH fields; Phase 2 displays(unset)for either+NEVER+prose constraints → ENG-1604 (treated as soft suggestions)resources/known-caveats.mdexplains why prose constraints fail and recommends MCP tool gates / upstream validators / post-output filters; SKILL.md constraints + Phase 3 validation + Phase 4 body-rewrite flow all flag thisVerification
tests/scripts/validate-plugin-manifests.shpasses0.1.0agents/AGENTS.mdlists the skill in both the path list and<available_skills>blockREADME.mdskills table includes the new rowtests/skills.mdincludes 4 smoke-test scenarios (list, create with authoring guidance, delete with orphan handling, update without blind overwrite) and Critical Files entriestests/commands.mdincludes slash-command smoke testsTest plan
list_skillsis called (or/v2/skillsREST fallback) and output is a scannable table, not raw JSONtest-skill" → verify Phase 3 asks for description, tags, project scope; rejects descriptions without a trigger phrase; flags any+NEVER+in the proposed bodytest-skill" → verify Phase 5 lists referencing agents BEFORE deleting, asks for delete consent, then asks SEPARATELY for orphan-cleanup consent; verify it never auto-prunes/orq:manage-skills listruns the list flow end-to-end*_skillMCP tools are exposed onhttps://my.orq.ai/v2/mcp— if not, the REST fallback path is documented and works today