363 lines
9.2 KiB
Markdown
363 lines
9.2 KiB
Markdown
# Skill Registry Design
|
|
|
|
## Overview
|
|
|
|
Skills are distributable capability packages for Ollama agents. They can be:
|
|
- Bundled with agents at creation time (local paths)
|
|
- Pulled from the registry (skill references)
|
|
- Pushed to the registry for sharing
|
|
|
|
## User Experience
|
|
|
|
### Push a Skill
|
|
|
|
```bash
|
|
# Push a local skill directory to the registry
|
|
ollama skill push myname/calculator:1.0.0 ./skills/calculator-skill
|
|
|
|
# Output:
|
|
# Creating skill layer for skill/myname/calculator:1.0.0
|
|
# pushing sha256:abc123... 1.2KB
|
|
# pushing sha256:def456... 220B
|
|
# pushing manifest
|
|
# Successfully pushed skill/myname/calculator:1.0.0
|
|
```
|
|
|
|
### Pull a Skill
|
|
|
|
```bash
|
|
# Pull a skill from the registry
|
|
ollama skill pull calculator:1.0.0
|
|
|
|
# Output:
|
|
# pulling manifest
|
|
# pulling sha256:abc123... 1.2KB
|
|
# extracting skill...
|
|
# Successfully pulled skill/calculator:1.0.0
|
|
```
|
|
|
|
### List Installed Skills
|
|
|
|
```bash
|
|
ollama skill list
|
|
|
|
# Output:
|
|
# NAME TAG SIZE MODIFIED
|
|
# skill/calculator 1.0.0 1.2 KB 2 hours ago
|
|
# skill/myname/hello latest 0.8 KB 1 day ago
|
|
```
|
|
|
|
### Remove a Skill
|
|
|
|
```bash
|
|
ollama skill rm calculator:1.0.0
|
|
# Deleted 'skill/calculator:1.0.0'
|
|
```
|
|
|
|
### Use Skills in Agentfile
|
|
|
|
```dockerfile
|
|
FROM llama3.2:3b
|
|
|
|
AGENT_TYPE conversational
|
|
SKILL skill/calculator:1.0.0 # Registry reference
|
|
SKILL ./local-skill # Local path (for development)
|
|
|
|
SYSTEM You are a helpful assistant.
|
|
```
|
|
|
|
## Technical Implementation
|
|
|
|
### Skill Manifest Format
|
|
|
|
```json
|
|
{
|
|
"schemaVersion": 2,
|
|
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
|
"config": {
|
|
"mediaType": "application/vnd.docker.container.image.v1+json",
|
|
"digest": "sha256:config...",
|
|
"size": 220
|
|
},
|
|
"layers": [
|
|
{
|
|
"mediaType": "application/vnd.ollama.image.skill",
|
|
"digest": "sha256:skill...",
|
|
"size": 1234
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Skill Config Format
|
|
|
|
```json
|
|
{
|
|
"name": "calculator",
|
|
"description": "A skill for performing calculations",
|
|
"architecture": "amd64",
|
|
"os": "linux"
|
|
}
|
|
```
|
|
|
|
### Storage Layout
|
|
|
|
Skills use a 5-part manifest structure: `host/namespace/kind/model/tag`
|
|
|
|
```
|
|
~/.ollama/models/
|
|
├── blobs/
|
|
│ └── sha256-<skill-digest> # Skill tar.gz blob
|
|
├── manifests/
|
|
│ └── registry.ollama.ai/
|
|
│ └── library/
|
|
│ └── skill/ # Kind = skill
|
|
│ └── calculator/
|
|
│ └── 1.0.0
|
|
│ └── myname/
|
|
│ └── skill/ # User skills
|
|
│ └── my-skill/
|
|
│ └── latest
|
|
└── skills/
|
|
└── sha256-<digest>/ # Extracted skill cache
|
|
├── SKILL.md
|
|
└── scripts/
|
|
```
|
|
|
|
### Name Structure
|
|
|
|
Skills use a 5-part name structure with `kind` to distinguish from models:
|
|
|
|
| Skill Reference | Namespace | Kind | Model | Tag |
|
|
|-----------------|-----------|------|-------|-----|
|
|
| `skill/calculator:1.0.0` | library | skill | calculator | 1.0.0 |
|
|
| `myname/skill/calc:latest` | myname | skill | calc | latest |
|
|
|
|
### Media Type
|
|
|
|
```go
|
|
const MediaTypeSkill = "application/vnd.ollama.image.skill"
|
|
```
|
|
|
|
### Key Types
|
|
|
|
```go
|
|
// SkillRef represents a skill reference in agent config
|
|
type SkillRef struct {
|
|
Name string `json:"name,omitempty"` // "calculator-skill" or "myname/skill/calc:1.0.0"
|
|
Digest string `json:"digest,omitempty"` // "sha256:abc..." (set when bundled)
|
|
}
|
|
|
|
// model.Name represents a parsed 5-part name
|
|
type Name struct {
|
|
Host string // "registry.ollama.ai"
|
|
Namespace string // "library" or "myname"
|
|
Kind string // "skill" or "agent" or "" for models
|
|
Model string // "calculator"
|
|
Tag string // "1.0.0"
|
|
}
|
|
```
|
|
|
|
## Implementation Files
|
|
|
|
### Client (ollama)
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `server/skill.go` | Skill blob handling, path parsing, extraction |
|
|
| `cmd/skill_cmd.go` | CLI commands (push, pull, list, rm, show) |
|
|
| `cmd/skills.go` | Skill loading and catalog management |
|
|
| `server/create.go` | Skill layer creation during agent create |
|
|
| `server/images.go` | Skill extraction during pull |
|
|
| `types/model/config.go` | SkillRef type definition |
|
|
|
|
### Registry (ollama.com)
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `ollamadotcom/registry/store.go` | MediaTypeSkill constant |
|
|
| `ollamadotcom/store/store.go` | RecordPush handles skill layers |
|
|
|
|
## Registry Integration
|
|
|
|
### What Works
|
|
|
|
- Blob uploads (content-addressable, no auth required)
|
|
- Layer indexing (skill layers stored with mediatype)
|
|
- Manifest structure (4-part path compatible)
|
|
|
|
### What's Needed
|
|
|
|
1. **Namespace Configuration**: The `skill` namespace needs to be configured with:
|
|
- Public read access
|
|
- Authenticated write access
|
|
|
|
2. **Permission Model**: Decide who can push to `skill/` namespace:
|
|
- Only Ollama team (curated library)
|
|
- Verified publishers
|
|
- Anyone (open registry)
|
|
|
|
## Pull Flow
|
|
|
|
### Agent with Bundled Skills
|
|
|
|
```
|
|
ollama pull my-agent
|
|
→ GET manifest (includes skill layers)
|
|
→ Download all blobs (model + skills)
|
|
→ Extract skill blobs to ~/.ollama/models/skills/
|
|
→ Ready to run
|
|
```
|
|
|
|
### Standalone Skill
|
|
|
|
```
|
|
ollama skill pull calculator:1.0.0
|
|
→ Parse as skill/calculator:1.0.0
|
|
→ Convert to model.Name{Namespace: "skill", Model: "calculator", Tag: "1.0.0"}
|
|
→ GET manifest from registry
|
|
→ Download skill blob
|
|
→ Extract to ~/.ollama/models/skills/sha256-<digest>/
|
|
→ Available for agents to reference
|
|
```
|
|
|
|
## Push Flow
|
|
|
|
```
|
|
ollama skill push myname/calculator:1.0.0 ./my-skill
|
|
→ Validate SKILL.md exists
|
|
→ Create tar.gz of skill directory
|
|
→ Compute SHA256 digest
|
|
→ Store blob locally
|
|
→ Create skill manifest with config layer
|
|
→ Store manifest locally
|
|
→ Push blobs to registry
|
|
→ Push manifest to registry
|
|
```
|
|
|
|
## Backward Compatibility
|
|
|
|
- Old agents with `Skills: []string` (paths) continue to work
|
|
- New agents use `Skills: []SkillRef` with name and digest
|
|
- Parser detects format and handles both
|
|
|
|
## Local Registry Testing
|
|
|
|
To test push/pull locally, you need MinIO and the Docker registry running:
|
|
|
|
```bash
|
|
# 1. Start MinIO (for blob storage)
|
|
minio server ~/.minio-data --console-address ':9001' &
|
|
|
|
# 2. Create the ollama-dev bucket (first time only)
|
|
mc config host add local http://localhost:9000 minioadmin minioadmin
|
|
mc mb local/ollama-dev
|
|
|
|
# 3. Start the registry (from ollama.com repo)
|
|
cd /path/to/ollama.com/registry
|
|
go run cmd/registry/main.go serve config-dev.yml &
|
|
|
|
# 4. Verify registry is running
|
|
curl http://localhost:6000/v2/
|
|
```
|
|
|
|
**Important:** The `config-dev.yml` must have matching ports:
|
|
```yaml
|
|
http:
|
|
addr: :6000
|
|
host: http://localhost:6000 # Must match addr!
|
|
```
|
|
|
|
### Test Commands
|
|
|
|
```bash
|
|
# Push skill from local folder
|
|
ollama skill push localhost:6000/testuser/skill/calculator:1.0.0 ./skills/calculator-skill --insecure
|
|
|
|
# Pull skill from registry
|
|
ollama skill pull localhost:6000/testuser/skill/calculator:1.0.0 --insecure
|
|
|
|
# List skills
|
|
ollama skill list
|
|
|
|
# Show skill
|
|
ollama skill show localhost:6000/testuser/skill/calculator:1.0.0
|
|
```
|
|
|
|
## Architecture Diagram
|
|
|
|
```mermaid
|
|
graph TB
|
|
subgraph "Skill Naming Structure"
|
|
A["skill/calculator:1.0.0"] --> B["host: registry.ollama.ai"]
|
|
A --> C["namespace: library"]
|
|
A --> D["kind: skill"]
|
|
A --> E["model: calculator"]
|
|
A --> F["tag: 1.0.0"]
|
|
end
|
|
|
|
subgraph "Storage Layout"
|
|
G["~/.ollama/models/"]
|
|
G --> H["blobs/"]
|
|
H --> I["sha256-<skill-digest>"]
|
|
G --> J["manifests/"]
|
|
J --> K["registry.ollama.ai/"]
|
|
K --> L["library/skill/calculator/1.0.0"]
|
|
K --> M["myname/skill/my-skill/latest"]
|
|
G --> N["skills/"]
|
|
N --> O["sha256-<digest>/"]
|
|
O --> P["SKILL.md"]
|
|
O --> Q["scripts/"]
|
|
end
|
|
|
|
subgraph "Push Flow"
|
|
R["User Command: ollama skill push"]
|
|
R --> S["Validate SKILL.md"]
|
|
S --> T["Create tar.gz of skill dir"]
|
|
T --> U["Compute SHA256 digest"]
|
|
U --> V["Store blob locally"]
|
|
V --> W["Create skill manifest"]
|
|
W --> X["Store manifest locally"]
|
|
X --> Y["Push blobs to registry"]
|
|
Y --> Z["Push manifest to registry"]
|
|
end
|
|
|
|
subgraph "Pull Flow - Standalone Skill"
|
|
AA["User Command: ollama skill pull"]
|
|
AA --> AB["Parse name structure"]
|
|
AB --> AC["GET manifest from registry"]
|
|
AC --> AD["Download skill blob"]
|
|
AD --> AE["Extract to skills/ directory"]
|
|
AE --> AF["Available for agents"]
|
|
end
|
|
|
|
subgraph "Pull Flow - Agent with Skills"
|
|
AG["Pull Agent: ollama pull my-agent"]
|
|
AG --> AH["GET manifest (includes skill layers)"]
|
|
AH --> AI["Download all blobs (model + skills)"]
|
|
AI --> AJ["Extract skill blobs"]
|
|
AJ --> AK["Ready to run"]
|
|
end
|
|
|
|
subgraph "Agentfile Integration"
|
|
AL["Agentfile"]
|
|
AL --> AM["FROM llama3.2:3b"]
|
|
AL --> AN["SKILL skill/calculator:1.0.0"]
|
|
AL --> AO["SKILL ./local-skill"]
|
|
AO --> AP["Local path (development)"]
|
|
AN --> AQ["Registry reference"]
|
|
end
|
|
|
|
subgraph "Registry Components"
|
|
AR["Registry Server"]
|
|
AR --> AS["Blob Storage (MinIO)"]
|
|
AR --> AT["Layer Indexing"]
|
|
AR --> AU["Manifest Storage"]
|
|
AR --> AV["Namespace Config"]
|
|
end
|
|
|
|
Z --> AR
|
|
AC --> AR
|
|
AH --> AR
|
|
```
|