From 60cb151061f1c7fc25e29a442c29b0c112c5ae46 Mon Sep 17 00:00:00 2001 From: atharvacoolkni Date: Thu, 2 Apr 2026 15:30:45 +0530 Subject: [PATCH] update skill doc --- docs/Tutorial/skills.md | 75 ++++++++++++--- .../reference/library/skills/api-reference.md | 96 +++++++------------ docs/reference/library/skills/index.md | 37 +++---- docs/reference/library/skills/skill-format.md | 23 +++-- 4 files changed, 127 insertions(+), 104 deletions(-) diff --git a/docs/Tutorial/skills.md b/docs/Tutorial/skills.md index fd011f8..6bbc286 100644 --- a/docs/Tutorial/skills.md +++ b/docs/Tutorial/skills.md @@ -256,8 +256,7 @@ agent = Agent( "You have access to specialized skill modes that give you " "deeper expertise in specific domains.\n" "When the user's request clearly matches a skill, activate " - "it immediately by calling set_skill() before doing anything else.\n" - "When the task is done, call clear_skill() to return to general mode." + "it immediately by calling set_skill() before doing anything else." ), } ], @@ -265,12 +264,11 @@ agent = Agent( skills_dir=SKILLS_DIR, inject_trigger_table=True, # Auto-appends skill table to system prompt hot_reload=True, # Re-reads SKILL.md on every call (great for dev) - auto_deactivate=True, # Activating new skill clears the old one ), trim_context=True, # Safe with skills - they survive trimming! ) -# Get the tool node - already includes set_skill and clear_skill +# Get the tool node - includes set_skill tool tool_node = agent.get_tool_node() @@ -402,28 +400,75 @@ You: What's the average of these numbers: 10, 20, 30 ## How It Works -1. **Startup**: The agent discovers skills from `./skills/` and registers `set_skill` and `clear_skill` tools. +1. **Startup**: The agent discovers skills from `./skills/` and registers the `set_skill` tool. 2. **System Prompt**: Each LLM call includes: - Your base system prompt - - A trigger table listing all skills - - Active skill content (if a skill is active) + - A trigger table listing all skills with their triggers and resources 3. **Skill Activation**: When the LLM calls `set_skill("code-review")`: - - The tool returns `"SKILL_ACTIVATED:code-review"` - - The framework stores this in `state.execution_meta.internal_data` - - On the next LLM call, the skill's instructions are injected + - The tool returns the full skill content in format: `## SKILL: CODE-REVIEW\n\n{skill instructions}` -4. **Context Trimming**: Skills survive `trim_context=True` because: - - The active skill name is stored in `internal_data`, not message history - - Skill content is re-injected fresh on every call +4. **Resource Loading**: To load a specific resource file: + - Call `set_skill("code-review", "style-guide.md")` + - The tool returns: `## Resource: style-guide.md\n\n{file content}` + +5. **Context Trimming**: Skills survive `trim_context=True` because: + - The skill content is returned as a tool result + - The LLM uses this content directly in its response + - Content is re-loaded fresh on each call when needed + +## Resources Feature + +Skills can include additional reference files (resources) that can be loaded on-demand: + +### Adding Resources to a Skill + +In your SKILL.md frontmatter, add a `resources` list: + +```markdown +--- +name: code-review +description: Perform thorough code reviews +metadata: + triggers: + - review my code + - check this code + resources: + - style-guide.md + - security-checklist.md +--- +``` + +### Loading Resources + +The LLM can load specific resources during a conversation: + +```python +# Call set_skill with resource name to load that specific file +# The tool returns the resource content directly +set_skill("code-review", "style-guide.md") +# Returns: ## Resource: style-guide.md\n\n{content of style-guide.md} +``` + +The trigger table shows available resources, and the LLM knows to call `set_skill(name, resource)` to load them. + +### Example: Code Review with Resources + +Here's how resources work in practice: + +1. User asks: "Review my Python code" +2. LLM calls `set_skill("code-review")` +3. Tool returns the skill content +4. If the user then asks about style conventions, the LLM calls `set_skill("code-review", "style-guide.md")` +5. Tool returns the style guide content, which the LLM uses to answer ## Next Steps -- Add a `style-guide.md` resource to the code-review skill +- Add resource files to your skills for reference documentation - Create custom skills for your domain -- Explore `max_active=2` to allow multiple skills at once - Use tags to organize and filter skills +- Explore the hot_reload option for development ## Full Example Code diff --git a/docs/reference/library/skills/api-reference.md b/docs/reference/library/skills/api-reference.md index 3e9b22b..ffb120f 100644 --- a/docs/reference/library/skills/api-reference.md +++ b/docs/reference/library/skills/api-reference.md @@ -11,8 +11,6 @@ from agentflow.skills import SkillConfig config = SkillConfig( skills_dir="./skills/", - max_active=1, - auto_deactivate=True, inject_trigger_table=True, hot_reload=True, ) @@ -28,19 +26,15 @@ agent = Agent( | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `skills_dir` | `str \| None` | `None` | Path to folder containing skill subdirectories. If `None`, no skills are discovered from disk. | -| `max_active` | `int` | `1` | Maximum number of simultaneously active skills. | -| `auto_deactivate` | `bool` | `True` | When `True`, activating a new skill automatically clears the previous one. | | `inject_trigger_table` | `bool` | `True` | Appends a markdown table of all skills to the system prompt so the LLM knows when to use each skill. | | `hot_reload` | `bool` | `True` | Re-reads SKILL.md files when their modification time changes. Safe for production (mtime check is cheap). | -### Example: Multiple Active Skills +### Example ```python -# Allow up to 2 skills active at once +# Configure skills config = SkillConfig( skills_dir="./skills/", - max_active=2, - auto_deactivate=False, # Don't clear previous skills ) ``` @@ -163,84 +157,68 @@ table = registry.build_trigger_table() # Returns: # ## Available Skills # -# | Skill | When to use | -# |-------|-------------| -# | `code-review` | review my code; find bugs; code review | +# ### How to Use Skills +# When the user's request matches a skill: +# 1. Call `set_skill(skill_name)` to load the skill instructions +# 2. Read the loaded content — it may reference additional resources +# 3. If you need a specific resource mentioned in the skill, call `set_skill(skill_name, resource_name)` +# 4. Then provide your answer using the loaded content +# ### Skills & Resources +# +# **`code-review`** — triggers: "review my code", "find bugs", "code review" # ... ``` --- -## Tools: set_skill and clear_skill +## Tool: set_skill + +When skills are enabled, the Agent's ToolNode automatically includes the `set_skill` tool. -When skills are enabled, the Agent's ToolNode automatically includes two tools: +### set_skill(skill_name: str, resource: str | None = None) -> str -### set_skill(skill_name: str) -> str +Activates a skill or loads a specific resource. The LLM calls this when a user request matches a skill domain. -Activates a skill. The LLM calls this when a user request matches a skill domain. +**Arguments:** +- `skill_name` (required): Name of the skill to load +- `resource` (optional): If provided, loads this specific resource file instead of the skill instructions **Returns:** -- `"SKILL_ACTIVATED:"` on success +- `"## SKILL: {NAME}\n\n{skill content}"` on success +- `"## Resource: {filename}\n\n{resource content}"` when loading a resource - `"ERROR: Unknown skill ''. Available: ..."` if skill not found **Example LLM interaction:** ``` User: Can you review my Python code? Assistant: [calls set_skill("code-review")] -Tool Result: SKILL_ACTIVATED:code-review +Tool Result: ## SKILL: CODE-REVIEW + +You are now in **CODE REVIEW** mode... Assistant: [responds using code-review skill instructions] ``` -### clear_skill() -> str - -Deactivates all active skills, returning to general mode. - -**Returns:** `"SKILL_DEACTIVATED"` - ---- - -## SkillInjector - -Internal class that builds system prompt messages from active skills. You typically don't use this directly. - -```python -from agentflow.skills.injection import SkillInjector - -injector = SkillInjector(registry, config) - -# Build prompts for active skills -prompts = injector.build_skill_prompts(["code-review"]) -# Returns: [{"role": "system", "content": "## ACTIVE SKILL: CODE REVIEW\n..."}] +**Loading a resource:** ``` +Assistant: [calls set_skill("code-review", "style-guide.md")] +Tool Result: ## Resource: style-guide.md -### Methods - -#### `build_skill_prompts(active_skills: list[str]) -> list[dict[str, str]]` - -Builds system prompt dicts for each active skill. Each dict contains: -- Skill body content -- Appended resource files -- Routing note (tells LLM to check other skills on next turn) +# Style Guide +... +``` --- -## State Storage - -Active skills are stored in `state.execution_meta.internal_data["active_skills"]` as a list of strings. +## How Skills Work -```python -# Check active skills -active = state.execution_meta.internal_data.get("active_skills", []) - -# Manually set (not recommended - use set_skill tool instead) -state.execution_meta.internal_data["active_skills"] = ["code-review"] -``` +The skill system works differently from the old "active skill injection" model: -**Why this location?** +1. **Trigger Table**: The LLM sees all available skills in the system prompt +2. **Skill Activation**: When the LLM calls `set_skill("skill-name")`, the tool returns the full skill content +3. **Resource Loading**: `set_skill("skill-name", "resource.md")` loads specific resource files +4. **No State Storage**: Skills don't store state in `execution_meta` - instead, content is returned as tool results and the LLM uses it directly -- `state.context` (message history) can be trimmed by `MessageContextManager` -- `execution_meta.internal_data` is never trimmed -- Skills survive context trimming automatically +This design is simpler and works better with context trimming - skill content is re-loaded fresh when needed. --- diff --git a/docs/reference/library/skills/index.md b/docs/reference/library/skills/index.md index 233ee4b..bf96143 100644 --- a/docs/reference/library/skills/index.md +++ b/docs/reference/library/skills/index.md @@ -86,7 +86,7 @@ agent = Agent( ), ) -# The tool_node already includes set_skill and clear_skill +# The tool_node includes the set_skill tool tool_node = agent.get_tool_node() def should_use_tools(state): @@ -132,30 +132,31 @@ The agent will: │ Agent.execute() │ ├─────────────────────────────────────────────────────────────────┤ │ 1. Base system prompt │ -│ 2. Trigger table (all available skills) │ -│ 3. Active skill content (if skill is active) │ -│ 4. User messages from state.context │ +│ 2. Trigger table (all available skills with triggers/resources)│ +│ 3. User messages from state.context │ └─────────────────────────────────────────────────────────────────┘ │ ▼ LLM Response │ - ┌────────────────────┴────────────────────┐ - │ │ - Text response Tool call: set_skill() - │ │ - ▼ ▼ - END ToolNode - │ - "SKILL_ACTIVATED:code-review" - │ - State updated with active skill - │ - Back to MAIN - │ - Skill content now injected + ┌────────────────────┴────────────────────┐ + │ │ + Text response Tool call: set_skill() + │ │ + ▼ ▼ + END ToolNode + │ + "## SKILL: CODE-REVIEW\n\n{content}" + │ + Skill content returned as tool result + │ + Back to MAIN + │ + LLM uses skill content in response ``` +The `set_skill()` tool returns the full skill content directly, which the LLM uses to formulate its response. Resources can be loaded by calling `set_skill("skill-name", "resource.md")`. + ## Next Steps - [SKILL.md Format Reference](./skill-format.md) - Complete syntax guide diff --git a/docs/reference/library/skills/skill-format.md b/docs/reference/library/skills/skill-format.md index fea8fdf..d9e6e2c 100644 --- a/docs/reference/library/skills/skill-format.md +++ b/docs/reference/library/skills/skill-format.md @@ -97,13 +97,13 @@ metadata: - is this code good ``` -Only the first 3 triggers are shown in the table. Choose the most distinctive ones first. +Only the first 4 triggers are shown in the table. Choose the most distinctive ones first. **Tip:** Make triggers natural and varied. The LLM uses semantic matching, so you don't need to cover every possible phrase. ## Resources -Resources are additional files that get injected alongside the skill content. They're useful for: +Resources are additional files that can be loaded on-demand during a conversation. They're useful for: - Style guides - Reference documentation @@ -127,19 +127,18 @@ code-review/ └── other.md ✗ Won't be found (relative path doesn't traverse dirs) ``` -Resources are appended to the skill content with a clear header: +### Loading Resources -``` -## ACTIVE SKILL: CODE REVIEW - -[SKILL.md body content] - ---- -### Reference: style-guide.md +Resources are loaded via the `set_skill` tool by passing the resource filename as the second argument: -[style-guide.md content] +```python +# Load a specific resource file +set_skill("code-review", "style-guide.md") +# Returns: ## Resource: style-guide.md\n\n{content of the file} ``` +The trigger table shows available resources, and the LLM knows to call `set_skill("skill-name", "resource-name")` to load them. + ## Tags Tags are metadata for filtering skills programmatically. They're not used by the LLM. @@ -173,7 +172,7 @@ metadata: ## Skill Body (Instructions) -Everything after the closing `---` is the skill body. This content is injected as a system message when the skill is active. +Everything after the closing `---` is the skill body. This content is returned as a tool result when the LLM calls `set_skill("skill-name")`. ### Best Practices