@agenticforge/skills 1.1.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +275 -231
- package/README.zh_CN.md +227 -218
- package/dist/cjs/index.cjs +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/types/AgentSkill.d.ts +1 -2
- package/dist/types/AgentSkill.d.ts.map +1 -1
- package/dist/types/MarkdownSkill.d.ts.map +1 -1
- package/dist/types/SkillDispatcher.d.ts +57 -0
- package/dist/types/SkillDispatcher.d.ts.map +1 -0
- package/dist/types/SkillLoader.d.ts.map +1 -1
- package/dist/types/SkillRegistry.d.ts.map +1 -1
- package/dist/types/SkillRunner.d.ts +20 -24
- package/dist/types/SkillRunner.d.ts.map +1 -1
- package/dist/types/SkillTool.d.ts +105 -0
- package/dist/types/SkillTool.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,231 +1,275 @@
|
|
|
1
|
-
# @agenticforge/skills
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@agenticforge/skills)
|
|
4
|
-
[](https://creativecommons.org/licenses/by-nc-sa/4.0/)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const runner = new SkillRunner({ llm, skills
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
|
186
|
-
|
|
187
|
-
| `
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
`
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
1
|
+
# @agenticforge/skills
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@agenticforge/skills)
|
|
4
|
+
[](https://creativecommons.org/licenses/by-nc-sa/4.0/)
|
|
5
|
+
|
|
6
|
+
<p><a href="./README.zh_CN.md">中文</a> | <strong>English</strong></p>
|
|
7
|
+
|
|
8
|
+
Composable, routable agent capabilities for AgenticFORGE. Define each capability as a focused **Skill** — in Markdown or TypeScript — and let the framework automatically route user queries to the right one.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @agenticforge/skills
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## What is a Skill?
|
|
19
|
+
|
|
20
|
+
A Skill is a named, self-contained capability unit. Think of it as a specialized expert your agent can delegate to:
|
|
21
|
+
|
|
22
|
+
- A **weather skill** that only handles weather questions
|
|
23
|
+
- A **code review skill** that critiques TypeScript code
|
|
24
|
+
- A **stock lookup skill** that queries real-time market data
|
|
25
|
+
|
|
26
|
+
Each skill owns its system prompt, its tools, and its execution logic. When a user query arrives, the framework routes it to the best-matching skill automatically.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Defining Skills
|
|
31
|
+
|
|
32
|
+
### Option 1 — Markdown (recommended for most cases)
|
|
33
|
+
|
|
34
|
+
Create a `SKILL.md` file. The frontmatter defines routing metadata; the body becomes the system prompt.
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+
---
|
|
38
|
+
name: code-reviewer
|
|
39
|
+
description: Review TypeScript and JavaScript code for bugs, type safety issues, and performance problems.
|
|
40
|
+
triggerHint: When the user asks to review, check, or improve code quality
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
# Code Reviewer
|
|
44
|
+
|
|
45
|
+
You are a senior TypeScript engineer doing a thorough code review.
|
|
46
|
+
Focus on correctness first, then performance, then style.
|
|
47
|
+
|
|
48
|
+
## Review checklist
|
|
49
|
+
- Type safety: no implicit `any`, proper return types
|
|
50
|
+
- Error handling: no unhandled promise rejections
|
|
51
|
+
- Edge cases: null/undefined, empty arrays
|
|
52
|
+
- Performance: unnecessary loops, memory leaks
|
|
53
|
+
|
|
54
|
+
## Output format
|
|
55
|
+
1. **Summary** — one sentence overall verdict
|
|
56
|
+
2. **Issues** — each with severity (critical / warning / suggestion) and a suggested fix
|
|
57
|
+
3. **Improved code** — rewrite the problematic sections
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Load and run it:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { SkillLoader, SkillRunner } from "@agenticforge/skills";
|
|
64
|
+
|
|
65
|
+
const skills = await SkillLoader.fromDirectory("./skills");
|
|
66
|
+
const runner = new SkillRunner({ llm, skills });
|
|
67
|
+
|
|
68
|
+
const result = await runner.run(`
|
|
69
|
+
Review this function:
|
|
70
|
+
async function fetchUser(id) {
|
|
71
|
+
const res = await fetch('/api/users/' + id);
|
|
72
|
+
return res.json();
|
|
73
|
+
}
|
|
74
|
+
`);
|
|
75
|
+
console.log(result.output);
|
|
76
|
+
// => "**Summary**: Function lacks error handling and has unsafe type usage..."
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Option 2 — TypeScript class (for custom execution logic)
|
|
80
|
+
|
|
81
|
+
Use `AgentSkill` directly when the skill needs to call external APIs, run custom logic, or orchestrate its own tools:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { AgentSkill } from "@agenticforge/skills";
|
|
85
|
+
import type { SkillContext, SkillResult } from "@agenticforge/skills";
|
|
86
|
+
import type { LLMClient } from "@agenticforge/core";
|
|
87
|
+
|
|
88
|
+
// A stock lookup skill that fetches real-time prices and formats a response
|
|
89
|
+
class StockSkill extends AgentSkill {
|
|
90
|
+
constructor() {
|
|
91
|
+
super({
|
|
92
|
+
name: "stock-query",
|
|
93
|
+
description: "Look up real-time stock prices and market data for any ticker symbol.",
|
|
94
|
+
triggerHint: "When the user asks about stock prices, market cap, ticker, or trading data",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
override async execute(ctx: SkillContext, llm: LLMClient): Promise<SkillResult> {
|
|
99
|
+
// Fetch from your data provider
|
|
100
|
+
const price = await fetchStockPrice(extractTicker(ctx.query));
|
|
101
|
+
// Ask the LLM to format a natural response
|
|
102
|
+
const output = await llm.think([
|
|
103
|
+
{ role: "system", content: "Format the stock data as a brief, friendly response." },
|
|
104
|
+
{ role: "user", content: `Ticker data: ${JSON.stringify(price)}\nUser asked: ${ctx.query}` },
|
|
105
|
+
]);
|
|
106
|
+
return { output };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For simpler cases, instantiate `AgentSkill` directly without extending:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
const translatorSkill = new AgentSkill({
|
|
115
|
+
name: "translator",
|
|
116
|
+
description: "Translate text between any two languages.",
|
|
117
|
+
triggerHint: "When the user wants to translate text or asks how to say something in another language",
|
|
118
|
+
systemPrompt: "You are a professional translator. Output only the translated text, nothing else.",
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Routing Multiple Skills
|
|
125
|
+
|
|
126
|
+
The real power of the skill system shows when you have many capabilities and want the agent to pick the right one automatically.
|
|
127
|
+
|
|
128
|
+
`SkillRunner` (and `SkillAgent`) use a **two-level routing strategy** that balances speed and accuracy:
|
|
129
|
+
|
|
130
|
+
| Level | How it works | LLM calls |
|
|
131
|
+
|-------|-------------|----------|
|
|
132
|
+
| **Rule routing** | Matches `triggerHint` keywords against the query | 0 |
|
|
133
|
+
| **LLM routing** | Sends all skill descriptions to the LLM for intent classification | 1 |
|
|
134
|
+
|
|
135
|
+
Rule routing runs first. If no keyword matches, the LLM router takes over.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { SkillLoader, SkillRunner } from "@agenticforge/skills";
|
|
139
|
+
|
|
140
|
+
// A personal assistant with multiple capabilities
|
|
141
|
+
const skills = await SkillLoader.fromDirectory("./skills");
|
|
142
|
+
const runner = new SkillRunner({
|
|
143
|
+
llm,
|
|
144
|
+
skills: [...skills, new StockSkill(), new CalendarSkill()],
|
|
145
|
+
fallbackPrompt: "You are a helpful general assistant.", // used when no skill matches
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Each query is routed automatically
|
|
149
|
+
await runner.run("What's the weather in Berlin tomorrow?"); // => weather skill
|
|
150
|
+
await runner.run("Review my TypeScript function above."); // => code-reviewer skill
|
|
151
|
+
await runner.run("What is Tesla's current stock price?"); // => StockSkill
|
|
152
|
+
await runner.run("Schedule a meeting for Friday at 3pm."); // => CalendarSkill
|
|
153
|
+
|
|
154
|
+
// Skip routing and call a specific skill directly
|
|
155
|
+
await runner.runSkill("stock-query", "AAPL vs MSFT performance this week");
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Advanced: SkillDispatcher
|
|
161
|
+
|
|
162
|
+
If you need routing without a full `SkillRunner`, use `SkillDispatcher` directly:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
import { SkillDispatcher, SkillRegistry } from "@agenticforge/skills";
|
|
166
|
+
|
|
167
|
+
const registry = new SkillRegistry();
|
|
168
|
+
registry.register(weatherSkill);
|
|
169
|
+
registry.register(stockSkill);
|
|
170
|
+
registry.register(codeReviewerSkill);
|
|
171
|
+
|
|
172
|
+
const dispatcher = new SkillDispatcher(registry, llm);
|
|
173
|
+
|
|
174
|
+
// Returns the matched skill, or undefined if nothing matched
|
|
175
|
+
const skill = await dispatcher.dispatch("Is it going to rain in Tokyo?");
|
|
176
|
+
if (skill) {
|
|
177
|
+
const result = await skill.execute({ query }, llm);
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**SkillDispatcher options:**
|
|
182
|
+
|
|
183
|
+
| Option | Default | Description |
|
|
184
|
+
|--------|---------|-------------|
|
|
185
|
+
| `routerPromptTemplate` | Built-in prompt | Custom routing prompt with `{skills}` and `{query}` placeholders |
|
|
186
|
+
| `triggerHintSeparator` | `/[,,、]/` | Regex to split `triggerHint` into individual keywords |
|
|
187
|
+
| `disableRuleRouting` | `false` | Skip keyword matching, always use LLM routing |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Skill File Naming
|
|
192
|
+
|
|
193
|
+
`SkillLoader` picks up:
|
|
194
|
+
- `SKILL.md` — recommended, mirrors Cursor / Claude skills layout
|
|
195
|
+
- `*.skill.md` — alternative flat naming
|
|
196
|
+
|
|
197
|
+
Other `.md` files (`README.md`, `examples.md`, etc.) are ignored.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## API Reference
|
|
202
|
+
|
|
203
|
+
### `SkillRunner`
|
|
204
|
+
|
|
205
|
+
| Method | Description |
|
|
206
|
+
|--------|-------------|
|
|
207
|
+
| `run(query, options?)` | Route query to best skill and execute |
|
|
208
|
+
| `runSkill(name, query, options?)` | Execute a named skill directly (bypasses routing) |
|
|
209
|
+
| `addSkill(skill)` | Register a skill at runtime |
|
|
210
|
+
| `removeSkill(name)` | Unregister a skill |
|
|
211
|
+
| `listSkills()` | List all registered skill names |
|
|
212
|
+
|
|
213
|
+
### `AgentSkill`
|
|
214
|
+
|
|
215
|
+
| Member | Description |
|
|
216
|
+
|--------|-------------|
|
|
217
|
+
| `name` | Unique skill identifier used for routing and direct calls |
|
|
218
|
+
| `description` | One-line summary — this is what the LLM reads to make routing decisions |
|
|
219
|
+
| `triggerHint` | Keywords for rule routing (comma-separated) |
|
|
220
|
+
| `systemPrompt` | System prompt injected at execution time |
|
|
221
|
+
| `tools` | Tools available exclusively to this skill |
|
|
222
|
+
| `execute(ctx, llm)` | Override to implement custom execution logic |
|
|
223
|
+
|
|
224
|
+
### `SkillLoader`
|
|
225
|
+
|
|
226
|
+
| Method | Description |
|
|
227
|
+
|--------|-------------|
|
|
228
|
+
| `fromDirectory(dir)` | Scan recursively for `SKILL.md` and `*.skill.md` files |
|
|
229
|
+
| `fromFiles(paths[])` | Load from explicit file paths |
|
|
230
|
+
| `fromSources(sources[])` | Parse from raw markdown strings (useful for testing) |
|
|
231
|
+
| `registryFromDirectory(dir)` | `fromDirectory` + wrap in `SkillRegistry` in one call |
|
|
232
|
+
|
|
233
|
+
### `SkillRegistry`
|
|
234
|
+
|
|
235
|
+
| Method | Description |
|
|
236
|
+
|--------|-------------|
|
|
237
|
+
| `register(skill)` | Add a skill |
|
|
238
|
+
| `get(name)` | Look up by name |
|
|
239
|
+
| `list()` | All registered skill names |
|
|
240
|
+
| `visible()` | Skills visible to the LLM router (`visible: true`) |
|
|
241
|
+
| `describeAll()` | Formatted skill list for use in routing prompts |
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Using with SkillAgent
|
|
246
|
+
|
|
247
|
+
For a stateful agent experience with conversation history and structured output, use `SkillAgent` from `@agenticforge/agents`:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
import { SkillAgent } from "@agenticforge/agents";
|
|
251
|
+
import { SkillLoader } from "@agenticforge/skills";
|
|
252
|
+
|
|
253
|
+
const skills = await SkillLoader.fromDirectory("./skills");
|
|
254
|
+
|
|
255
|
+
const agent = new SkillAgent({
|
|
256
|
+
name: "personal-assistant",
|
|
257
|
+
llm,
|
|
258
|
+
skills,
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Conversation history is automatically maintained between calls
|
|
262
|
+
await agent.run("What's the weather in London?");
|
|
263
|
+
await agent.run("And in Tokyo?"); // knows context from previous turn
|
|
264
|
+
await agent.run("Which city is warmer?"); // routes to weather skill again
|
|
265
|
+
|
|
266
|
+
agent.clearHistory(); // reset between sessions
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Links
|
|
272
|
+
|
|
273
|
+
- [GitHub](https://github.com/LittleBlacky/AgenticFORGE/tree/main/packages/skills)
|
|
274
|
+
- [npm](https://www.npmjs.com/package/@agenticforge/skills)
|
|
275
|
+
- [Root README](https://github.com/LittleBlacky/AgenticFORGE)
|