In the previous chapter, Context & Memory Builder, we gave our agent a personality and the ability to remember previous conversations.
However, there is still a major gap. Even if an agent knows who it is ("I am a robot") and remembers what you said ("Turn on the light"), it doesn't necessarily know how to do it.
Does "Turn on the light" mean sending an HTTP request? Toggling a hardware pin? Or sending a message to a smart home API?
This is where the Skills System comes in.
In PicoClaw, we distinguish between two concepts:
func GPIO_Write(pin int, value int)).Imagine buying a new IKEA shelf.
Without the booklet (Skill), you have the tools, but you don't know which screw goes where.
A Skill in PicoClaw is simply a folder containing a Markdown file named SKILL.md.
Instead of writing complex logic in Go, you write instructions in plain English. The agent reads this file to understand its capabilities.
Let's look at a real skill file for controlling hardware pins.
---
name: hardware
description: Control physical pins (GPIO) on the device.
---
# Hardware Control
Use this skill when the user asks to control lights or sensors.
## Configuration
- **LED Light**: Connected to Pin 14. Set to "1" to turn ON.
- **Fan**: Connected to Pin 2. Set to "1" to turn ON.
## How to use
Use the tool `gpio_write` to change the state.
What happens here?
We need a system to find all these instruction booklets and organize them. This is the Skills Loader.
It looks in three places:
~/.picoclaw/skills).The Loader scans these folders to build a catalog.
// pkg/skills/loader.go (Simplified)
func (sl *SkillsLoader) ListSkills() []SkillInfo {
var skills []SkillInfo
// 1. Check the workspace folder for "SKILL.md" files
dirs, _ := os.ReadDir(sl.workspaceSkills)
for _, dir := range dirs {
// 2. Load the metadata (name, description)
path := filepath.Join(sl.workspaceSkills, dir.Name(), "SKILL.md")
meta := sl.getSkillMetadata(path)
// 3. Add to our list
skills = append(skills, SkillInfo{Name: meta.Name, Path: path})
}
return skills
}
Explanation: The Loader acts like a librarian walking through the shelves (directories), looking at the book covers (metadata), and making a list of what is available.
We cannot feed the entire text of every skill manual into the AI at once. That would be too much text (Context Window limit) and too expensive.
Instead, we provide a Summary or a Menu.
When the agent starts thinking, the Skills System generates a list of available capabilities and injects it into the System Prompt.
<skills>
<skill>
<name>weather</name>
<description>Get current weather info.</description>
</skill>
<skill>
<name>hardware</name>
<description>Control physical pins (GPIO).</description>
</skill>
</skills>
Here is how the loader builds this summary string:
// pkg/skills/loader.go (Simplified)
func (sl *SkillsLoader) BuildSkillsSummary() string {
// Get the list of all skills
allSkills := sl.ListSkills()
var lines []string
lines = append(lines, "<skills>")
// Loop through and format them as XML
for _, s := range allSkills {
lines = append(lines, fmt.Sprintf(" <skill>"))
lines = append(lines, fmt.Sprintf(" <name>%s</name>", s.Name))
lines = append(lines, fmt.Sprintf(" <description>%s</description>", s.Description))
lines = append(lines, " </skill>")
}
lines = append(lines, "</skills>")
return strings.Join(lines, "\n")
}
How does the agent go from "List of Skills" to actually using one?
hardware skill mentions "Control physical pins".In the basic version, the summary is often enough. But sometimes, a Skill is very long (like a reference manual for a complex chip).
If the agent needs the full text of a skill, the Loader provides a function to read the specific file content.
// pkg/skills/loader.go (Simplified)
func (sl *SkillsLoader) LoadSkill(name string) (string, bool) {
// Construct the path: workspace/skills/hardware/SKILL.md
skillFile := filepath.Join(sl.workspaceSkills, name, "SKILL.md")
// Read the file from disk
content, err := os.ReadFile(skillFile)
if err != nil {
return "", false
}
// Remove the top metadata (-- name: hardware --) and return the rest
return sl.stripFrontmatter(string(content)), true
}
This allows the Context Builder (from Chapter 4) to dynamically pull in the full manual if the agent is focused on a specific task.
The beauty of the Skills System is that you don't need to be a programmer to teach the AI.
If you want to teach your agent that "Code Red" means "Turn on all lights and play a siren," you don't edit the Go code. You just edit a Markdown file:
# Emergency Procedures
If the user says "Code Red":
1. Use tool `light_control` to set brightness to 100.
2. Use tool `sound_play` to play "siren.mp3".
The Agent reads this, understands it, and executes it using the Tools it has available.
In this chapter, we learned:
Now the agent knows what it can do (via Skills) and how to plan it. But we haven't actually executed any code yet! The Agent might decide to "Use Tool: gpio_write", but how does the system actually run that function?
In the next chapter, we will dive into the engine room to see how Tools are registered and executed.
Next: Chapter 6 - Tool Registry & Execution
Generated by Code IQ