Deferred items
The workshop intentionally keeps the notebook implementation small. These are the pieces that belong in the prototype, in a real implementation, or in a follow-up exercise.
Tool-description skill injection
OpenCode communicates available skills through the skill tool description.
The tool description contains the list of skill names and descriptions, so the
system prompt can stay focused on behavior rules.
The notebook injects the skill list into the prompt instead. That is easier to implement in ToyAIKit during the workshop, and it works well for the small models used here.
If you build your own agent, try both. Tool-description injection keeps capabilities closer to the tool schema. Prompt injection is simpler and often works well enough.
Command interception
The notebook exposes commands through an execute_command tool. This is the
simpler path because it avoids modifying the runner.
For a real product, command interception is usually cleaner:
- Read the user's raw input.
- If it starts with
/, parse the command name and arguments. - Load the command markdown.
- Render the template.
- Send the rendered prompt to the agent.
The prototype implements this in RealAgent.chat().
Full template rendering
The notebook's process_template() returns the template unchanged. Command
templates can use placeholders such as $1, $2, $3, and $ARGUMENTS, but
the notebook does not implement them.
The prototype does implement positional and all-argument substitution in
prototype/src/commands.py. Use that version if you want commands like:
/review src/agent.py
to become:
Review the code at src/agent.py for:
Skill validation
The notebook loader assumes that every subdirectory under skills/ contains a
valid SKILL.md. That keeps the workshop code short.
A real loader should validate:
SKILL.mdexists.nameis present.descriptionis present.- The directory name matches the skill name.
- The description is short enough to include in the prompt or tool schema.
- Disabled skills are skipped.
The OpenCode-style rules require name and description, allow optional
metadata, and support a disabled flag.
Extra skill files
The notebook reads only SKILL.md. The examples show that useful skills often
include scripts/ and templates/.
The prototype resolves @scripts/deploy.sh and similar references into paths.
It still leaves the agent to read or run those files with normal tools. That is
the right boundary: the skill loader gives the agent instructions and paths,
while file and shell tools perform the work.
Permissions
OpenCode-style skill permissions let a config allow, deny, or ask before loading a skill. The prototype in this workshop does not include a separate permission module.
If you add permissions, keep them in the tool execution layer. The model should not be trusted to decide whether it is allowed to load a restricted skill.
Benchmarks for skill adherence
The Q&A includes a question about whether skill steps are followed 100 percent of the time. The workshop does not include a benchmark.
The prototype gives you the starting point for testing: look at the recorded tool calls and assert that the expected skill was loaded. For stricter evaluation, collect multiple prompts per skill and measure:
- Whether the correct skill was called.
- Whether the wrong skill was avoided.
- Whether referenced files were read.
- Whether required scripts were run.
- Whether the final answer followed the skill instructions.
Framework choice
We use ToyAIKit because it is interactive and clear for teaching. It is a good fit for a workshop notebook, not a full production agent framework.
For production, use a framework that fits your application. PydanticAI is a good default option, and the concepts here still carry over: tools, prompts, lazy-loaded skill instructions, and command rendering.
Continue with Appendix: workshop files for the file list.