Conversation
…tion, reframe validation rationale, revert unrelated example changes - Update SKILL_CATALOG_INSTRUCTION to explicitly state skills are CAO-only and must use get_skill MCP tool (comment 4) - Reframe model-level validation rationale around separation of concerns, not performance (comment 1) - Sync proposal doc example with updated instruction text - Revert unrelated content/formatting changes to example profiles, keeping only skills frontmatter additions (comments 5-6) - Update test assertions to match new instruction wording Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move skill catalog injection from pre-enriched AgentProfile objects to a simple string passed through the provider chain. The service layer builds the skill catalog text via _build_skill_catalog() and passes it as skill_prompt to providers. Each provider appends it to the system prompt using BaseProvider._apply_skill_prompt() during command construction. This addresses PR awslabs#145 comment 3: providers no longer need to know about AgentProfile enrichment or skill metadata. The contract is a plain string. Changes: - Add skill_prompt param and _apply_skill_prompt() helper to BaseProvider - Replace loaded_profile with skill_prompt in all 7 providers and manager - Remove _enrich_profile_with_skills from terminal_service - Remove AgentProfile imports from providers that no longer need them Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
E2E Test Report:
|
| Command | Status | Notes |
|---|---|---|
cao --help |
✅ | Shows skills with description "Manage installed skills." |
cao skills --help |
✅ | Shows add, list, remove subcommands with correct descriptions |
cao skills add --help |
✅ | Shows FOLDER_PATH argument, --force flag |
cao skills remove --help |
✅ | Shows NAME argument |
cao skills list --help |
✅ | Clean, no extra options |
Happy Path
| Test | Status | Output |
|---|---|---|
skills list (empty) |
✅ | "No skills found" |
skills add (built-in skill) |
✅ | "Skill 'cao-worker-protocols' installed successfully" |
skills add (second skill) |
✅ | "Skill 'cao-supervisor-protocols' installed successfully" |
skills list (2 skills) |
✅ | Sorted table with Name + Description columns, 100-char separator |
skills add --force (overwrite) |
✅ | Overwrites without error |
skills remove |
✅ | "Skill 'cao-worker-protocols' removed successfully" |
skills list (after remove) |
✅ | Shows only remaining skill |
skills add (custom skill) |
✅ | Custom SKILL.md installed to ~/.aws/cli-agent-orchestrator/skills/ |
| Filesystem verification | ✅ | SKILL.md copied to correct directory |
Error Handling
| Test | Status | Output |
|---|---|---|
Duplicate add (no --force) |
✅ | "Error: Skill '...' already exists. Use --force to overwrite it." (exit 1) |
| Remove nonexistent skill | ✅ | "Error: Skill '...' does not exist." (exit 1) |
| Add from nonexistent path | ✅ | Click validates path: "Path '...' does not exist." (exit 2) |
| Add folder without SKILL.md | ✅ | "Error: Missing SKILL.md in skill folder: ..." (exit 1) |
| Add with invalid frontmatter | ✅ | Pydantic validation error with field details (exit 1) |
| Add with name/folder mismatch | ✅ | "Error: Skill folder name '...' does not match skill name '...'" (exit 1) |
| Path traversal on remove | ✅ | "Error: Invalid skill name '...': must not contain '/', '', or '..'" (exit 1) |
Summary
18/18 tests passed. All subcommands work correctly. Help descriptions are clear and consistent. Error messages are specific and actionable. Path traversal protection works. The skill store at ~/.aws/cli-agent-orchestrator/skills/ is created on demand and cleaned up properly.
Tests verify the full skill pipeline end-to-end:
- Skill catalog text is injected into the provider CLI command (checked
by capturing the tmux scrollback after terminal creation)
- GET /skills/{name} returns installed skill content
- GET /skills/{name} returns 404 for missing skills
- GET /skills/{name} rejects path traversal attempts
For providers with full-screen TUI (Claude Code), the scrollback may
not retain the full command due to screen clearing. In those cases,
the test falls back to verifying the system prompt injection flag is
present. Codex retains the full scrollback and verifies the complete
skill catalog including skill names.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Code's full-screen TUI clears the tmux scrollback, making it impossible to assert on the tail of the long command where the skill catalog lives. Skill injection for Claude Code is covered by unit tests and validated indirectly via the Codex test which shares the same service-layer code path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Run black on manager.py, test_skills.py, test_base_provider.py - Fix test_get_skill.py to handle both FastMCP 2.x (dict) and 3.x (list) return types from get_tools(), and .fn vs direct callable Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix import ordering in test_skills.py (isort)
- Handle FastMCP 3.x removing get_tools() entirely — fall back to
get_tool("get_skill") for single tool lookup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Kiro CLI supports progressive skill loading via skill:// URIs in the resources field. Replace the baked prompt catalog with a single glob entry (skill://<SKILLS_DIR>/*/SKILL.md) so Kiro discovers skills natively. This removes the need for prompt refresh on skill changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The requests import-untyped and MCP server misc suppressions are pre-existing on main. Restore mypy.ini to match main exactly and keep the inline type: ignore comment on install.py. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Revert changes unrelated to the skills feature: - .gitignore (.worktrees/) - WebSocket terminal fixes (tmux -u, CancelledError, chunked PTY writes) - TerminalView.tsx (scrollback, paste handler) - database.py (Flow prompt_template=None) - settings_service.py (mypy cast cleanup) - terminal_service.py (terminal_id guard, allowed_tools passthrough) - test_handoff.py (event loop isolation) - code_supervisor.md (trailing newline) - install.py (_write_text_atomic, raise from e in init.py) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f476ab8 to
fa6977b
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
E2E Test Report: Provider Skill Injection (
|
| Assertion | Status |
|---|---|
JSON keys: allowedTools, description, mcpServers, name, resources, tools, useLegacyMcpJson (no prompt) |
✅ |
resources contains 1 file:// URI pointing to agent-context/developer.md |
✅ |
resources contains 1 skill:// URI ending in /**/SKILL.md |
✅ |
prompt field correctly omitted (profile.prompt is None) |
✅ |
After cao skills add: no prompt field, glob unchanged |
✅ |
After cao skills remove: no prompt field, unchanged |
✅ |
| Not included in refresh count | ✅ |
Kiro CLI — Glob Captures Multiple Skills
| Assertion | Status |
|---|---|
Glob skill://<SKILLS_DIR>/**/SKILL.md resolves to 4 matches after adding 2 test skills |
✅ |
alpha-skill/SKILL.md captured by glob |
✅ |
beta-skill/SKILL.md captured by glob |
✅ |
cao-worker-protocols/SKILL.md captured by glob |
✅ |
cao-supervisor-protocols/SKILL.md captured by glob |
✅ |
All matched SKILL.md files have valid frontmatter (name, description) and body content |
✅ |
Q CLI — Baked Prompt
| Assertion | Status |
|---|---|
JSON keys include prompt |
✅ |
resources contains file:// only, no skill:// |
✅ |
prompt starts with ## Available Skills (catalog-only) |
✅ |
prompt contains cao-worker-protocols and cao-supervisor-protocols |
✅ |
prompt contains get_skill MCP tool instruction |
✅ |
After cao skills add: e2e-test-skill appears in prompt |
✅ |
After cao skills remove: e2e-test-skill gone, cao-worker-protocols remains |
✅ |
Copilot CLI — Baked .agent.md Body
| Assertion | Status |
|---|---|
Frontmatter keys: description, name |
✅ |
Body starts with # DEVELOPER AGENT (profile system_prompt) |
✅ |
Body contains ## Available Skills after profile content |
✅ |
Body contains cao-worker-protocols and cao-supervisor-protocols |
✅ |
Body contains get_skill MCP tool instruction |
✅ |
| Profile body appears before skill catalog (correct ordering) | ✅ |
After cao skills add: e2e-test-skill appears, DEVELOPER AGENT preserved |
✅ |
After cao skills remove: e2e-test-skill gone, profile + builtins preserved |
✅ |
Non-CAO Agent Protection
| Assertion | Status |
|---|---|
| External Copilot agent body unchanged after skill add/remove cycle | ✅ |
Refresh Count
| Assertion | Status |
|---|---|
cao skills add refreshes 2 agents (Q + Copilot, not Kiro) |
✅ |
cao skills remove refreshes 2 agents (Q + Copilot, not Kiro) |
✅ |
Summary
34/34 assertions passed. Kiro uses native skill:// glob resources — verified that the glob correctly captures multiple dynamically-added skills without any agent config refresh. Q and Copilot receive baked prompt catalogs that refresh on skill changes. Non-CAO-managed agents are protected from modification.
|
hi @fanhongy , I have made numerous changes to ensure all CLI providers that do not accept prompts as a CLI flag (namely Kiro, Q, Copilot CLI) will still have access to CAO skills. Please take a look at the updated PR description for details. I have also included a user guide |
Remove references to a per-profile `skills` frontmatter field that was never implemented. All installed skills are available to all agents. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checkout main.py from upstream/main to drop out-of-scope WebSocket diffs (chunked PTY writes, CancelledError handling, -u flag), then re-apply only the skills endpoint additions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
63b10df to
3623939
Compare
3623939 to
82752d7
Compare
…estration instructions - Add "Managed Skills" section to README with cao skills CLI commands, provider delivery table, and update instructions - Restore "Multi-Agent Communication" section in developer.md that was removed by #145 when orchestration instructions were moved to builtin skills — these should remain inline in the agent profile - Update docs/skills.md: remove Q CLI references, clarify builtin skill seeding, use consistent provider update language across all sections Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Overview
Adds a skills system to CAO that enables reusable, composable blocks of instructional content that can be shared across agent profiles. Skills are lazily loaded via MCP tool calls rather than injected into the system prompt upfront, preserving context window budget.
Addresses issue #143. See
docs/skills-design.mdfor the full design document.Motivation
Agent profiles today are monolithic — when multiple agents need the same domain knowledge (testing conventions, communication protocols, coding standards), that knowledge must be duplicated across each profile. Skills solve this by separating agent identity (who the agent is) from agent capability (what the agent knows how to do). Skills are defined once, referenced by name in profile frontmatter, and loaded on-demand by the agent at runtime.
Key Changes
Skill file format and store
SKILL.mdwith YAML frontmatter (name,description) and a Markdown body~/.aws/cli-agent-orchestrator/skills/— a single user-writable store with no built-in/custom splitcao-supervisor-protocolsandcao-worker-protocolsCLI commands (
cao skills)cao skills list— lists all installed skills with name and descriptioncao skills add <folder-path>— installs a skill from a local folder (with--forceflag for overwrites)cao skills remove <name>— removes an installed skillSkill seeding via
cao initcao initnow seeds builtin skills into the user store, skipping any that already exist to preserve user editsServer-side skill retrieval
GET /skills/{name}HTTP endpoint oncao-serverreturns skill body contentload_skillMCP tool oncao-mcp-serverwraps the HTTP call for agent accessProvider skill injection
Skills are delivered to agents via three different mechanisms depending on what each provider supports natively:
Runtime prompt injection (Claude Code, Codex, Gemini CLI, Kimi CLI)
A skill catalog (names + descriptions +
load_skillusage instruction) is built at terminal creation time and appended to the system prompt via each provider's CLI flag (e.g.--append-system-prompt,-c developer_instructions). The agent then calls theload_skillMCP tool to load full skill content on demand.Native skill:// resources (Kiro CLI)
cao installwrites askill://glob URI (skill://<SKILLS_DIR>/*/SKILL.md) into the Kiro agent JSON'sresourcesfield. Kiro natively supports progressive loading — only skill metadata (name, description) is loaded at startup, with full content loaded on demand when the agent determines it's relevant. No prompt baking or refresh oncao skills add/removeis needed.Baked prompt at install time (Q CLI)
Note that there is no official documentation listing Q CLI supports
skill://as a resource, I've elected to keep the solution similar to the primitive approach done for Copilot CLI.cao installbakes the skill catalog text into the agent JSON'spromptfield viacompose_agent_prompt(). Oncao skills add/remove, installed Q agent JSONs are refreshed to reflect the updated catalog.Baked prompt at install time (Copilot CLI)
cao installbakes the skill catalog into the.agent.mdbody (appended after the profile's system prompt). Oncao skills add/remove, installed Copilot agent.agent.mdfiles are refreshed to reflect the updated catalog. Non-CAO-managed Copilot agents (no matching context file) are left untouched.load_skillMCP toolload_skillMCP toolload_skillMCP toolload_skillMCP toolskill://resourcescao skills add/removetriggers refreshload_skillMCP toolcao skills add/removetriggers refreshload_skillMCP toolTest plan
uv run pytest test/ --ignore=test/e2e -v— covers skill model, utils, CLI commands, API endpoint, MCP tool, terminal service integration, and provider changesuv run pytest -m e2e test/e2e/test_skills.py -v— covers skill catalog injection and skill API endpoint with a running servercao initseeds builtin skills,cao skills list/add/removework as expected