Phase 02 — Agents
Module 05 of 12 · 8 min read · Free

Module 5: Skills and Tools

A tool is a function. A skill is a reusable capability package. Understanding the difference is how you build agents that scale.

This is Module 5 of a 12-part curriculum: Build Software Products with AI — From First Principles to Production Pipeline.


In Module 3 we established that tools are what give an agent the ability to act. In this module we go deeper: how tools actually work at a technical level, and how to organise them into reusable skill packages that compose cleanly.

This is the engineering layer of agent development. Get it right and you’ll build agents that are capable, maintainable, and extensible. Get it wrong and you’ll have a mess of one-off implementations that break whenever anything changes.


How Tool Calling Works

When you define a tool for an agent, you’re giving the model three things:

  1. A name — how the model refers to the tool
  2. A description — natural language explanation of what the tool does, when to use it, and any important constraints
  3. A parameter schema — the structured definition of what inputs the tool accepts

Here’s a concrete example — a tool that reads a file:

{
  "name": "read_file",
  "description": "Read the full text contents of a file at the specified path. Use this when you need to examine the current state of a file before modifying it, or when you need to reference file contents in your reasoning.",
  "input_schema": {
    "type": "object",
    "properties": {
      "path": {
        "type": "string",
        "description": "Absolute path to the file to read"
      },
      "offset": {
        "type": "integer",
        "description": "Line number to start reading from (1-indexed). Optional."
      },
      "limit": {
        "type": "integer",
        "description": "Maximum number of lines to return. Optional."
      }
    },
    "required": ["path"]
  }
}

When the model decides to use this tool, it generates a structured tool call:

{
  "name": "read_file",
  "input": {
    "path": "/Users/niko/project/src/api/users.ts",
    "offset": 1,
    "limit": 50
  }
}

Your agent runtime intercepts this, executes the actual file read (the model cannot do this itself — it can only describe what to call), and feeds the result back into the context window as a tool result message. The model then continues reasoning with the file contents available.

The critical point: the model decides when and what to call; your code executes it. This separation is what keeps the system safe and auditable.


Writing Good Tool Descriptions

The description field is more important than most people realise. The model uses it to decide whether and when to call the tool. Vague descriptions lead to the model calling tools at the wrong times or not calling them when it should.

Good tool descriptions answer:

  • What does this tool do? Be specific. “Executes a shell command” is better than “runs code.”
  • When should the model use it? Give concrete examples or conditions.
  • When should it NOT use it? Constraints and limitations.
  • What does it return? So the model knows how to interpret the result.

Example of a weak description:

Runs a command on the system.

Example of a strong description:

Execute a shell command in the user's terminal. Use this to run scripts, check file system state, execute tests, install packages, or call CLI tools. Returns stdout and stderr combined. Avoid commands that require interactive input — they will hang. For long-running commands, prefer background=true to avoid blocking.

The extra detail costs you almost nothing in tokens. It pays back significantly in reliability.


The Skill Pattern

Tools are the atoms. Skills are the molecules.

A skill is a reusable, self-contained capability package that bundles:

  • A set of related tools
  • A SKILL.md file with instructions for the agent on how and when to use them
  • Any configuration or context the agent needs to operate in that domain

The skill pattern solves a real problem: as you add more tools and capabilities to an agent, the system prompt grows until it’s unwieldy. The agent has to juggle too much context about too many tools simultaneously.

Skills solve this with lazy loading. Instead of including all tool instructions in the main system prompt, you include brief skill descriptions. When the agent needs a specific capability, it reads the relevant SKILL.md first, then operates with that context loaded.

A skill directory typically looks like:

skills/
  github/
    SKILL.md          # Instructions for how to use GitHub tools
    README.md         # Human-readable documentation
  obsidian/
    SKILL.md          # Instructions for Obsidian vault operations
  meeting-scribe/
    SKILL.md          # Instructions for processing meeting transcripts

A SKILL.md might look like:

# GitHub Skill

## When to use this skill
Use when the task involves GitHub: reading issues, viewing PRs, checking CI status, 
commenting, or making API calls via the gh CLI.

## Setup
The `gh` CLI is authenticated. Use it directly.

## Key commands
- `gh pr list --state open` — list open PRs
- `gh pr view [number] --json reviews,files,body` — get PR details
- `gh issue create --title "..." --body "..."` — create issue
- `gh run list --branch [branch]` — check CI status

## Conventions
- Never push directly to main
- Always check CI status before summarising a PR as ready to merge
- When creating issues, use the project's label taxonomy

The agent reads this before acting in the GitHub domain. It has all the context it needs without that context polluting the main prompt.


Building a Skill from Scratch

Here’s the process for creating a new skill:

1. Identify the capability boundary. What is the agent trying to do? What external system or domain does it need to interact with? One skill = one coherent capability area.

2. List the tools. What functions does the agent need to accomplish tasks in this domain? Start with the minimum set — you can always add more.

3. Write the tool schemas. Name, description, parameter schema for each tool.

4. Write the SKILL.md. Instructions for the agent: when to use this skill, setup notes, key commands or patterns, conventions to follow.

5. Register the skill. In your agent runtime, make the skill discoverable — either through the main system prompt’s skill registry or through auto-discovery from a standard directory structure.

6. Test it. Give the agent tasks that require the skill and verify it behaves correctly. Check that it calls the right tools at the right times, handles errors gracefully, and follows the conventions you specified.


Tool Design Principles

A few principles that produce better tools:

Prefer granular tools over monolithic ones. A read_file and write_file tool are easier to reason about than a single file_operation tool that does both. The model reasons better with clear, single-purpose tools.

Build in safe defaults. For potentially destructive operations (deleting files, sending messages, making API calls), require explicit confirmation or add an --dry-run mode. Design for safety.

Return rich context. Don’t just return success/failure. Return information the model can use to continue reasoning: file contents, API response bodies, error messages with context. The richer the tool result, the better the agent’s next step.

Handle errors explicitly. If a tool fails, return a structured error with enough information for the model to understand what went wrong and decide what to do next. Silent failures are debugging nightmares.

Document side effects. If a tool writes to a file, sends a message, or modifies external state — say so clearly in the description. The model needs to understand the consequences of calling a tool.


Tools vs Prompting

A common mistake: trying to do with prompting what should be done with tools.

If you’re asking the model to “imagine what the file contains” or “estimate what the test output would be” — you need a tool. Prompting the model to reason about external state it can’t see produces hallucinations. Give it the tool to check the actual state.

Conversely, don’t create tools for things prompting handles well. You don’t need a “summarise_text” tool — that’s what the model does natively. Tools are for actions that require interacting with the world outside the model: file systems, APIs, shells, databases.

The right mental model: tools extend the model’s perception and action capabilities; prompting shapes how it reasons.


What’s Next

You have a complete picture of the tool layer: how tools work, how to write them well, and how to organise them into reusable skills. Now we go up a level: what happens when you need one agent to direct the work of others? That’s the orchestration problem — and it’s Module 6.


Further Reading

Referenced from @nikovijay

“Claude Code + Figma is the future of design ✅” — @_heyrico

N+1 Newsletter
Enjoyed this module?

Subscribe to get notified when new modules and courses drop. No drip — just updates when there's something worth reading.

Subscribe on Substack →