Skill Architecture
Skill Architecture
How skills are structured, wired, and extended in Skillful Alhazen.
What is a skill?
A skill is a complete vertical slice that enables the agent to work with a specific knowledge domain. Each skill consists of:
skills/<name>/
├── SKILL.md — Short selection guide (~30 lines): when to use, prerequisites, quick start
├── USAGE.md — Full reference (on-demand): all commands, workflows, data model, examples
├── skill.yaml — Structured metadata (name, description, license, dashboard config)
├── <name>.py — CLI entry point with argparse subcommands
└── schema.tql — TypeDB schema extension (auto-discovered on make build-db)
An optional dashboard/ directory contributes UI components to the Next.js dashboard:
skills/<name>/dashboard/
├── lib.ts → dashboard/src/lib/<name>.ts (API client helpers)
├── components/ → dashboard/src/components/<name>/ (React components)
├── pages/ → dashboard/src/app/(<name>)/ (Next.js pages)
└── routes/ → dashboard/src/app/api/<name>/ (API routes)
SKILL.md / USAGE.md Split
This two-file convention controls context loading:
| File | Size | When loaded | Contents |
|---|---|---|---|
SKILL.md |
~30 lines | Every conversation | Frontmatter (name, description), triggers, prerequisites, one quick-start example, pointer to USAGE.md |
USAGE.md |
Any length | On demand when skill is active | All commands, workflows, data model, TypeDB pitfalls, full examples |
The description field in SKILL.md frontmatter is the primary triggering mechanism — Claude reads it to decide whether to consult the skill. Make it specific and include context phrases, not just a definition.
Core vs. External Skills
Core skills (path: entries in skills-registry.yaml) live in the skills/ directory and are symlinked into local_skills/ on make build-skills. They are committed to this repository.
External skills (git: or subdir: entries) are cloned from sciknow-io/alhazen-skill-examples (or other git URLs) into local_skills/. They are gitignored build artifacts — edit them in their upstream repositories, not in local_skills/.
skills-registry.yaml — Single Source of Truth
All skills are registered here. make build-skills resolves the registry into local_skills/ and wires .claude/skills/ symlinks.
defaults:
git: https://github.com/sciknow-io/alhazen-skill-examples
branch: main
skills:
- name: typedb-notebook
path: skills/typedb-notebook # core: path-based
- name: scientific-literature
subdir: skills/biomed/scientific-literature # external: from defaults.git
- name: dismech
git: https://github.com/sciknow-io/alhazen-skill-dismech
subdir: skills/dismech # external: from custom git repo
Schema Loading
make build-db auto-discovers local_skills/*/schema.tql and loads them in order after the core schema (local_resources/typedb/alhazen_notebook.tql). No manual registration is required.
TypeDB 3.x syntax conventions:
# Attributes
attribute my-attr, value string; # NOT: my-attr sub attribute, value string;
# Entities (entity keyword required)
entity my-thing sub domain-thing,
owns my-attr;
# Relations (no sub relation needed)
relation my-rel,
relates subject,
relates object;
Adding a New Skill
- Copy the template:
cp -r skills/_template skills/<skill-name> - Implement:
SKILL.md(triggers + quick start),USAGE.md(full reference),skill.yaml,<skill-name>.py,schema.tql - Register: add a
path:entry toskills-registry.yaml - Wire:
make build-skills(symlinks) +make build-db(loads schema) - Test:
claude→ talk to the agent using your skill’s trigger phrases
Schema Design Conventions
Skills extend the Alhazen schema hierarchy:
identifiable-entity (abstract)
├── domain-thing ← base for real-world objects (papers, diseases, jobs)
│ └── scilit-paper ← example namespace entity
├── collection ← base for typed sets (corpora, campaigns)
│ └── scilit-corpus
└── information-content-entity (abstract)
├── artifact ← raw captured content
├── fragment ← extracted pieces
└── note ← agent analysis
Key rules:
- Domain objects (genes, papers, diseases) → sub
domain-thing - Typed groupings → sub
collection - Content-bearing entities → sub
artifact,fragment, ornote - Define relations before entities that use
playsclauses - No
@keyon custom attributes — only the inheritedid @keyworks
Gap-Driven Evolution
When the agent tries to represent a concept that has no place in the schema, that’s a schema gap — the primary signal for schema evolution. See Gap Architecture for how gaps are detected, filed, and fixed.