Write a Workspace Skill

Exercise objective

Create a read-only Session-inspection Skill in an isolated workspace. Observe summary injection, on-demand loading, and Tool use without modifying nanobot source code.

Prerequisites

  • Read Add a Skill.
  • Have at least one Session in the lab workspace.
  • Have rg on PATH; if it is unavailable, remove rg from the requirements below.

Source to read

  • nanobot/agent/skills.py::SkillsLoader
  • nanobot/agent/context.py::build_system_prompt
  • nanobot/skills/weather/SKILL.md
  • tests/agent/test_skills_loader.py
  • tests/command/test_skill_command.py

Predict before running

  • Does a new Skill enter every system prompt in full?
  • If the folder name differs from the frontmatter name, which one does the loader use?
  • How does /skill display a Skill whose requirements are unavailable?
  • Can a Skill grant the Agent file permissions it did not already have?

Procedure

1. Create the directory

Create this structure in the lab workspace:

skills/
└── session-auditor/
    └── SKILL.md

Use this content:

---
name: session-auditor
description: Read-only inspection of nanobot Session JSONL files for learning and debugging.
metadata:
  nanobot:
    requires:
      bins:
        - rg
      env: []
---
 
# Session Auditor
 
## Use when
 
Use this skill when the user asks to inspect how one nanobot Session was persisted.
 
## Procedure
 
1. Confirm the workspace and session key.
2. List session files; do not guess the filename.
3. Read only the metadata line and the final four message records.
4. Never print credentials, full system prompts, or unrelated sessions.
5. Report roles, timestamps, tool-call relationships, and relevant metadata.
6. Separate confirmed facts from unknowns.
 
## Safety boundaries
 
- Do not edit, delete, rename, or repair Session files.
- Stop if the target Session is ambiguous.
- Redact secrets and unnecessary personal content.
 
## Verification
 
End with the exact file inspected and the number of records read.

2. Verify discovery

Run with the same configuration and workspace:

nanobot agent `
  --config "$nanobotLab\config.json" `
  --workspace "$nanobotLab\workspace" `
  --message "/skill"

The list should include session-auditor.

3. Inspect the system prompt

Break in ContextBuilder.build_system_prompt() and verify that:

  • always_skills does not contain this Skill;
  • the Skill summary contains its name, description, and path;
  • the complete body has not yet been inserted directly.

4. Trigger the Skill

nanobot agent `
  --config "$nanobotLab\config.json" `
  --workspace "$nanobotLab\workspace" `
  --session "learning:skill" `
  --message "Use session-auditor to inspect learning:tool-call. Report only the role order and Tool Call relationships."

Observe whether the Agent:

  • reads the Skill first;
  • then lists and reads the Session;
  • respects read-only access and minimum disclosure;
  • reports the actual file and record count.

Expected observations

  • A normal Skill first appears in the prompt as a summary.
  • The model decides whether to read the complete SKILL.md.
  • A Skill constrains the workflow, but actual file access still occurs through the read_file and list_dir Tools.
  • Workspace and built-in Skills use the same loader entry point.
  • Model decisions may affect behavior, so loader facts should be established through tests.

Completion criteria

  • /skill discovers the Skill.
  • Its context summary is correct.
  • The Agent reads the full Skill at least once.
  • The inspection does not modify the Session.
  • The report satisfies the Skill’s Verification section.
  • git status shows no change under code-EN.

Verification

Run the loader tests:

Set-Location "example\nanobot\code-EN"
python -m pytest tests\agent\test_skills_loader.py -q
python -m pytest tests\command\test_skill_command.py -q

Then try a negative case: temporarily replace the requirement with a nonexistent command, verify that availability changes, and restore it afterward.

Review questions

  1. Why is the full body not inserted into every system prompt by default?
  2. If the model does not read the Skill, how can you distinguish a discovery failure from a model decision?
  3. Why is a bare instruction such as “do not leak secrets” insufficient?
  4. When should this Skill be marked as always loaded? Is that appropriate here?

Next: Build a read-only Tool plugin