feat(chat-workflow): port skill discovery + skillTool (PR 6, slim)
Summary
Ports the `skill` composite tool from open-agents along with the skill discovery layer it depends on. The handler now scans `${workingDirectory}/skills/` before workflow start and threads the catalog into `AgentContext.skills`. The `skill` tool registers in `buildAgentTools` only when the catalog is non-empty.
New
Skills layer (`lib/skills/`):
- `skillTypes.ts` (types + Zod schema), `parseSkillFrontmatter.ts`, `extractSkillBody.ts`, `substituteArguments.ts`, `injectSkillDirectory.ts`, `discoverSkills.ts`, `getSandboxSkillDirectories.ts`
Tool: `lib/agent/tools/skillTool.ts` — case-insensitive name match, respects `disable-model-invocation`, surfaces available-skills hint on unknown names. Loads SKILL.md → extractSkillBody → injectSkillDirectory → substituteArguments → returns to model.
Wire-up: AgentContext gains `skills?`; buildAgentTools conditional registration; handler connects sandbox + discoverSkills before `start(workflow)`.
Slim choices (follow-ups)
- Project skills only — global `~/.skills/` scan comes later, alongside short-lived token minting (the highest-value global skill, `recoup-api`, needs that token to be useful)
- No token minting — `skill` tool returns SKILL.md to the model; the recoup-api skill's curl examples wouldn't authenticate without ad-hoc credentials. Token design lands as a focused PR
Verification
- 35 new tests; full suite 3049/3049 pass
- Lint clean, production build succeeds
- E2E preview verification running now against `recoupable/org-rostrum-pacific-...`
🤖 Generated with Claude Code
Summary by cubic
Adds global skill discovery and a new skill tool to the chat workflow. The handler scans $HOME/.agents/skills before start and registers skill only when skills exist, enabling slash-command-style execution without noise.
-
New Features
- Skill discovery: reads
SKILL.md/skill.md, validates frontmatter, dedupes by name, and skips names that shadow built-ins (model,resume,new). skilltool: case-insensitive name match; blocks skills withdisable-model-invocation; loads file, strips frontmatter, injectsSkill directory: <path>, and substitutes$ARGUMENTS.- Wire-up:
AgentContext.skillsadded;buildAgentTools({ skills })conditionally includesskill;runAgentSteppasses skills;handleChatWorkflowStreamconnects sandbox, discovers skills (best-effort), and threads the catalog.
- Skill discovery: reads
-
Refactors
- Simplified discovery to global-only:
getSandboxSkillDirectoriesnow returns${HOME}/.agents/skills. - Extracted helpers for clarity and reuse:
getSkills(context accessor),findSkillFile(SKILL.md resolution),getGlobalSkillsDirectory(global path resolver).
- Simplified discovery to global-only:
Summary by CodeRabbit
- New Features
- AI agent now discovers and invokes custom project skills from workspace directories
- Model can dynamically call skills with optional arguments for flexible execution
- Skills are automatically scanned from project-level and designated global directories at workflow start
- Skill invocation includes metadata about available skills and error handling for invalid requests