@hailer/mcp 0.0.1
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/.claude/commands/tool-builder.md +37 -0
- package/.claude/commands/ws-pull.md +44 -0
- package/.claude/settings.json +8 -0
- package/.claude/settings.local.json +49 -0
- package/.claude/skills/activity-api/SKILL.md +96 -0
- package/.claude/skills/activity-api/references/activity-endpoints.md +845 -0
- package/.claude/skills/add-app-member-skill/SKILL.md +977 -0
- package/.claude/skills/agent-building/SKILL.md +243 -0
- package/.claude/skills/agent-building/references/architecture-patterns.md +446 -0
- package/.claude/skills/agent-building/references/code-examples.md +587 -0
- package/.claude/skills/agent-building/references/implementation-guide.md +619 -0
- package/.claude/skills/app-api/SKILL.md +219 -0
- package/.claude/skills/app-api/references/app-endpoints.md +759 -0
- package/.claude/skills/building-hailer-apps-skill/SKILL.md +548 -0
- package/.claude/skills/create-app-skill/SKILL.md +1101 -0
- package/.claude/skills/create-insight-skill/SKILL.md +1317 -0
- package/.claude/skills/get-insight-data-skill/SKILL.md +1053 -0
- package/.claude/skills/hailer-api/SKILL.md +283 -0
- package/.claude/skills/hailer-api/references/activities.md +620 -0
- package/.claude/skills/hailer-api/references/authentication.md +216 -0
- package/.claude/skills/hailer-api/references/datasets.md +437 -0
- package/.claude/skills/hailer-api/references/files.md +301 -0
- package/.claude/skills/hailer-api/references/insights.md +469 -0
- package/.claude/skills/hailer-api/references/workflows.md +720 -0
- package/.claude/skills/hailer-api/references/workspaces-users.md +445 -0
- package/.claude/skills/insight-api/SKILL.md +185 -0
- package/.claude/skills/insight-api/references/insight-endpoints.md +514 -0
- package/.claude/skills/install-workflow-skill/SKILL.md +1056 -0
- package/.claude/skills/list-apps-skill/SKILL.md +1010 -0
- package/.claude/skills/list-workflows-minimal-skill/SKILL.md +992 -0
- package/.claude/skills/local-first-skill/SKILL.md +570 -0
- package/.claude/skills/mcp-tools/SKILL.md +419 -0
- package/.claude/skills/mcp-tools/references/api-endpoints.md +499 -0
- package/.claude/skills/mcp-tools/references/data-structures.md +554 -0
- package/.claude/skills/mcp-tools/references/implementation-patterns.md +717 -0
- package/.claude/skills/preview-insight-skill/SKILL.md +1290 -0
- package/.claude/skills/publish-hailer-app-skill/SKILL.md +453 -0
- package/.claude/skills/remove-app-member-skill/SKILL.md +671 -0
- package/.claude/skills/remove-app-skill/SKILL.md +985 -0
- package/.claude/skills/remove-insight-skill/SKILL.md +1011 -0
- package/.claude/skills/remove-workflow-skill/SKILL.md +920 -0
- package/.claude/skills/scaffold-hailer-app-skill/SKILL.md +1034 -0
- package/.claude/skills/skill-testing/README.md +137 -0
- package/.claude/skills/skill-testing/SKILL.md +348 -0
- package/.claude/skills/skill-testing/references/test-patterns.md +705 -0
- package/.claude/skills/skill-testing/references/testing-guide.md +603 -0
- package/.claude/skills/skill-testing/references/validation-checklist.md +537 -0
- package/.claude/skills/tool-builder/SKILL.md +328 -0
- package/.claude/skills/update-app-skill/SKILL.md +970 -0
- package/.claude/skills/update-workflow-field-skill/SKILL.md +1098 -0
- package/.env.example +81 -0
- package/.mcp.json +13 -0
- package/README.md +297 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.js +74 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +5 -0
- package/dist/client/adaptive-documentation-bot.d.ts +108 -0
- package/dist/client/adaptive-documentation-bot.js +475 -0
- package/dist/client/adaptive-documentation-types.d.ts +66 -0
- package/dist/client/adaptive-documentation-types.js +9 -0
- package/dist/client/agent-activity-bot.d.ts +51 -0
- package/dist/client/agent-activity-bot.js +166 -0
- package/dist/client/agent-tracker.d.ts +499 -0
- package/dist/client/agent-tracker.js +659 -0
- package/dist/client/description-updater.d.ts +56 -0
- package/dist/client/description-updater.js +259 -0
- package/dist/client/log-parser.d.ts +72 -0
- package/dist/client/log-parser.js +387 -0
- package/dist/client/mcp-client.d.ts +50 -0
- package/dist/client/mcp-client.js +532 -0
- package/dist/client/message-processor.d.ts +35 -0
- package/dist/client/message-processor.js +352 -0
- package/dist/client/multi-bot-manager.d.ts +24 -0
- package/dist/client/multi-bot-manager.js +74 -0
- package/dist/client/providers/anthropic-provider.d.ts +19 -0
- package/dist/client/providers/anthropic-provider.js +631 -0
- package/dist/client/providers/llm-provider.d.ts +47 -0
- package/dist/client/providers/llm-provider.js +367 -0
- package/dist/client/providers/openai-provider.d.ts +23 -0
- package/dist/client/providers/openai-provider.js +621 -0
- package/dist/client/simple-llm-caller.d.ts +19 -0
- package/dist/client/simple-llm-caller.js +100 -0
- package/dist/client/skill-generator.d.ts +81 -0
- package/dist/client/skill-generator.js +386 -0
- package/dist/client/test-adaptive-bot.d.ts +9 -0
- package/dist/client/test-adaptive-bot.js +82 -0
- package/dist/client/token-pricing.d.ts +38 -0
- package/dist/client/token-pricing.js +127 -0
- package/dist/client/token-tracker.d.ts +232 -0
- package/dist/client/token-tracker.js +457 -0
- package/dist/client/token-usage-bot.d.ts +53 -0
- package/dist/client/token-usage-bot.js +153 -0
- package/dist/client/tool-executor.d.ts +69 -0
- package/dist/client/tool-executor.js +159 -0
- package/dist/client/tool-schema-loader.d.ts +60 -0
- package/dist/client/tool-schema-loader.js +178 -0
- package/dist/client/types.d.ts +69 -0
- package/dist/client/types.js +7 -0
- package/dist/config.d.ts +162 -0
- package/dist/config.js +296 -0
- package/dist/core.d.ts +26 -0
- package/dist/core.js +147 -0
- package/dist/lib/context-manager.d.ts +111 -0
- package/dist/lib/context-manager.js +431 -0
- package/dist/lib/logger.d.ts +74 -0
- package/dist/lib/logger.js +277 -0
- package/dist/lib/materialize.d.ts +3 -0
- package/dist/lib/materialize.js +101 -0
- package/dist/lib/normalizedName.d.ts +7 -0
- package/dist/lib/normalizedName.js +48 -0
- package/dist/lib/prompt-length-manager.d.ts +81 -0
- package/dist/lib/prompt-length-manager.js +457 -0
- package/dist/lib/terminal-prompt.d.ts +9 -0
- package/dist/lib/terminal-prompt.js +108 -0
- package/dist/mcp/UserContextCache.d.ts +56 -0
- package/dist/mcp/UserContextCache.js +163 -0
- package/dist/mcp/auth.d.ts +2 -0
- package/dist/mcp/auth.js +29 -0
- package/dist/mcp/hailer-clients.d.ts +42 -0
- package/dist/mcp/hailer-clients.js +246 -0
- package/dist/mcp/signal-handler.d.ts +45 -0
- package/dist/mcp/signal-handler.js +317 -0
- package/dist/mcp/tool-registry.d.ts +100 -0
- package/dist/mcp/tool-registry.js +306 -0
- package/dist/mcp/tools/activity.d.ts +15 -0
- package/dist/mcp/tools/activity.js +955 -0
- package/dist/mcp/tools/app.d.ts +20 -0
- package/dist/mcp/tools/app.js +1488 -0
- package/dist/mcp/tools/discussion.d.ts +19 -0
- package/dist/mcp/tools/discussion.js +950 -0
- package/dist/mcp/tools/file.d.ts +15 -0
- package/dist/mcp/tools/file.js +119 -0
- package/dist/mcp/tools/insight.d.ts +17 -0
- package/dist/mcp/tools/insight.js +806 -0
- package/dist/mcp/tools/skill.d.ts +10 -0
- package/dist/mcp/tools/skill.js +279 -0
- package/dist/mcp/tools/user.d.ts +10 -0
- package/dist/mcp/tools/user.js +108 -0
- package/dist/mcp/tools/workflow-template.d.ts +19 -0
- package/dist/mcp/tools/workflow-template.js +822 -0
- package/dist/mcp/tools/workflow.d.ts +18 -0
- package/dist/mcp/tools/workflow.js +1362 -0
- package/dist/mcp/utils/api-errors.d.ts +45 -0
- package/dist/mcp/utils/api-errors.js +160 -0
- package/dist/mcp/utils/data-transformers.d.ts +102 -0
- package/dist/mcp/utils/data-transformers.js +194 -0
- package/dist/mcp/utils/file-upload.d.ts +33 -0
- package/dist/mcp/utils/file-upload.js +148 -0
- package/dist/mcp/utils/hailer-api-client.d.ts +120 -0
- package/dist/mcp/utils/hailer-api-client.js +323 -0
- package/dist/mcp/utils/index.d.ts +13 -0
- package/dist/mcp/utils/index.js +39 -0
- package/dist/mcp/utils/logger.d.ts +42 -0
- package/dist/mcp/utils/logger.js +103 -0
- package/dist/mcp/utils/types.d.ts +286 -0
- package/dist/mcp/utils/types.js +7 -0
- package/dist/mcp/workspace-cache.d.ts +42 -0
- package/dist/mcp/workspace-cache.js +97 -0
- package/dist/mcp-server.d.ts +42 -0
- package/dist/mcp-server.js +280 -0
- package/package.json +56 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# Agent Building Skill
|
|
2
|
+
|
|
3
|
+
This skill provides comprehensive guidance for building skill-based autonomous agent systems, specifically for the Hailer MCP (Model Context Protocol) server architecture.
|
|
4
|
+
|
|
5
|
+
## When to Use This Skill
|
|
6
|
+
|
|
7
|
+
Use this skill when:
|
|
8
|
+
- Building or modifying agent systems with dynamic skill loading
|
|
9
|
+
- Implementing autonomous agents that work with Hailer
|
|
10
|
+
- Adding skill-based expertise to LLM agents
|
|
11
|
+
- Understanding agent architecture patterns
|
|
12
|
+
- Troubleshooting agent concurrency or performance issues
|
|
13
|
+
|
|
14
|
+
## Core Concepts
|
|
15
|
+
|
|
16
|
+
### Skill-Based Agent Architecture
|
|
17
|
+
|
|
18
|
+
Instead of creating multiple specialized agent instances, we use **one agent with dynamic skill loading**:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
Single Agent + Dynamic Skills = Multiple Expertise Domains
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Key Principle**: The agent analyzes each request and loads relevant skills on-demand, becoming an expert in that domain for that specific request.
|
|
25
|
+
|
|
26
|
+
### Why This Approach?
|
|
27
|
+
|
|
28
|
+
✅ **One Hailer Account** - No need for multiple bot user accounts
|
|
29
|
+
✅ **Concurrent by Default** - Node.js handles multiple requests naturally
|
|
30
|
+
✅ **Cost-Effective** - Single LLM call per request (no extra analysis call)
|
|
31
|
+
✅ **Lightweight** - Rule-based skill matching (~1-5ms overhead)
|
|
32
|
+
✅ **Maintainable** - Update skills without touching agent code
|
|
33
|
+
✅ **Scalable** - Add new skills easily
|
|
34
|
+
|
|
35
|
+
### Architecture Components
|
|
36
|
+
|
|
37
|
+
1. **Skill Loader** - Reads skill files from disk, caches in memory
|
|
38
|
+
2. **Skill Manager** - Analyzes requests using keyword matching, selects skills
|
|
39
|
+
3. **Message Processor** - Integrates skill selection into message flow
|
|
40
|
+
4. **LLM Provider** - Uses skill content to enhance system prompts
|
|
41
|
+
|
|
42
|
+
## Quick Reference
|
|
43
|
+
|
|
44
|
+
### Skill System Flow
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
User Message
|
|
48
|
+
↓
|
|
49
|
+
Skill Manager Analyzes (keyword matching)
|
|
50
|
+
↓
|
|
51
|
+
Skill Loader Loads Relevant Skills (cached)
|
|
52
|
+
↓
|
|
53
|
+
Enhanced System Prompt (with skill content)
|
|
54
|
+
↓
|
|
55
|
+
LLM Responds with Expertise
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Performance Characteristics
|
|
59
|
+
|
|
60
|
+
- **Skill Analysis**: 1-5ms (keyword matching)
|
|
61
|
+
- **Skill Loading**: 10-50ms first time, 0ms cached
|
|
62
|
+
- **Total Overhead**: ~15-55ms (negligible)
|
|
63
|
+
- **LLM Calls**: 1 per request (same as without skills)
|
|
64
|
+
- **Cost**: No additional cost
|
|
65
|
+
|
|
66
|
+
### Concurrency Model
|
|
67
|
+
|
|
68
|
+
**Node.js handles concurrent requests naturally**:
|
|
69
|
+
- Each request is processed independently (async/await)
|
|
70
|
+
- No shared state between requests
|
|
71
|
+
- All requests can be in-flight simultaneously
|
|
72
|
+
- Bottleneck is LLM API, not agent code
|
|
73
|
+
|
|
74
|
+
Single agent easily handles 100+ concurrent users without issues.
|
|
75
|
+
|
|
76
|
+
## Architecture Patterns
|
|
77
|
+
|
|
78
|
+
See [architecture-patterns.md](references/architecture-patterns.md) for:
|
|
79
|
+
- Current vs Future state diagrams
|
|
80
|
+
- Component relationships
|
|
81
|
+
- Data flow patterns
|
|
82
|
+
- Integration points
|
|
83
|
+
|
|
84
|
+
## Skill System Details
|
|
85
|
+
|
|
86
|
+
See [skill-system.md](references/skill-system.md) for:
|
|
87
|
+
- How Skill Loader works
|
|
88
|
+
- Keyword mapping strategies
|
|
89
|
+
- Caching mechanisms
|
|
90
|
+
- Skill file structure
|
|
91
|
+
|
|
92
|
+
## Implementation Guide
|
|
93
|
+
|
|
94
|
+
See [implementation-guide.md](references/implementation-guide.md) for:
|
|
95
|
+
- Step-by-step build instructions
|
|
96
|
+
- File modifications required
|
|
97
|
+
- Configuration changes
|
|
98
|
+
- Testing procedures
|
|
99
|
+
|
|
100
|
+
## Code Examples
|
|
101
|
+
|
|
102
|
+
See [code-examples.md](references/code-examples.md) for:
|
|
103
|
+
- Complete working implementations
|
|
104
|
+
- Integration patterns
|
|
105
|
+
- Error handling
|
|
106
|
+
- Testing examples
|
|
107
|
+
|
|
108
|
+
## Key Design Decisions
|
|
109
|
+
|
|
110
|
+
### Why Single Agent Instead of Multiple?
|
|
111
|
+
|
|
112
|
+
**Multiple Agent Instances** (❌ Not Recommended):
|
|
113
|
+
```
|
|
114
|
+
Agent 1 (workflow-bot@company.com) → Skills A, B
|
|
115
|
+
Agent 2 (data-bot@company.com) → Skills C, D
|
|
116
|
+
Agent 3 (general-bot@company.com) → Skill E
|
|
117
|
+
|
|
118
|
+
Issues:
|
|
119
|
+
- Requires multiple Hailer accounts
|
|
120
|
+
- More complex configuration
|
|
121
|
+
- Same concurrency (Node.js handles it either way)
|
|
122
|
+
- Harder to maintain
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Single Agent with Dynamic Skills** (✅ Recommended):
|
|
126
|
+
```
|
|
127
|
+
One Agent (user@company.com)
|
|
128
|
+
- Workflow request → loads skills A, B
|
|
129
|
+
- Data request → loads skills C, D
|
|
130
|
+
- General request → loads skill E
|
|
131
|
+
|
|
132
|
+
Benefits:
|
|
133
|
+
- One Hailer account
|
|
134
|
+
- Simple configuration
|
|
135
|
+
- Natural concurrency handling
|
|
136
|
+
- Easy maintenance
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Why Rule-Based Matching Instead of LLM Analysis?
|
|
140
|
+
|
|
141
|
+
**LLM-Based Skill Selection** (❌ Expensive):
|
|
142
|
+
```
|
|
143
|
+
User message → LLM analyzes (call #1) → picks skills
|
|
144
|
+
→ Hailer Agent responds (call #2)
|
|
145
|
+
|
|
146
|
+
Cost: 2x LLM calls per message
|
|
147
|
+
Latency: 2x response time
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Rule-Based Skill Selection** (✅ Efficient):
|
|
151
|
+
```
|
|
152
|
+
User message → Keyword matching (1-5ms) → picks skills
|
|
153
|
+
→ Hailer Agent responds (call #1)
|
|
154
|
+
|
|
155
|
+
Cost: Same as before
|
|
156
|
+
Latency: +15-55ms (negligible)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Why Extend Existing Config Instead of New Files?
|
|
160
|
+
|
|
161
|
+
**Configuration should live in `.env.local`** because:
|
|
162
|
+
- Already parsed by existing config system
|
|
163
|
+
- Git-ignored (credentials safe)
|
|
164
|
+
- Single source of truth
|
|
165
|
+
- Type-safe with Zod validation
|
|
166
|
+
- No additional files to manage
|
|
167
|
+
|
|
168
|
+
## Common Pitfalls to Avoid
|
|
169
|
+
|
|
170
|
+
❌ **Don't** create multiple Hailer accounts unless you have specific reasons (rate limits, permissions)
|
|
171
|
+
❌ **Don't** use LLM for skill selection (expensive, unnecessary)
|
|
172
|
+
❌ **Don't** create separate config files (use existing `.env.local`)
|
|
173
|
+
❌ **Don't** worry about concurrency with single agent (Node.js handles it)
|
|
174
|
+
❌ **Don't** add shared state between requests (breaks concurrent processing)
|
|
175
|
+
|
|
176
|
+
✅ **Do** use keyword-based skill matching (fast, free)
|
|
177
|
+
✅ **Do** cache skills in memory (avoid repeated file reads)
|
|
178
|
+
✅ **Do** keep agents stateless (each request independent)
|
|
179
|
+
✅ **Do** use existing configuration systems
|
|
180
|
+
✅ **Do** measure performance before optimizing
|
|
181
|
+
|
|
182
|
+
## Testing Strategy
|
|
183
|
+
|
|
184
|
+
1. **Unit Tests** - Test Skill Loader and Skill Manager independently
|
|
185
|
+
2. **Integration Tests** - Test skill selection with real messages
|
|
186
|
+
3. **E2E Tests** - Test full flow from Hailer message to response
|
|
187
|
+
4. **Load Tests** - Verify concurrent request handling
|
|
188
|
+
5. **Manual Tests** - Use Claude terminal to test different requests
|
|
189
|
+
|
|
190
|
+
## Troubleshooting
|
|
191
|
+
|
|
192
|
+
**Skills not loading?**
|
|
193
|
+
- Check `.claude/skills/` directory exists
|
|
194
|
+
- Verify skill files are readable
|
|
195
|
+
- Check skill cache (may need restart)
|
|
196
|
+
|
|
197
|
+
**Wrong skills loaded?**
|
|
198
|
+
- Review keyword mappings in skill-manager.ts
|
|
199
|
+
- Add more specific keywords
|
|
200
|
+
- Check message content parsing
|
|
201
|
+
|
|
202
|
+
**Performance issues?**
|
|
203
|
+
- Verify skills are cached (shouldn't reload each time)
|
|
204
|
+
- Check LLM API response times (likely bottleneck)
|
|
205
|
+
- Monitor concurrent request counts
|
|
206
|
+
|
|
207
|
+
**Concurrency problems?**
|
|
208
|
+
- Check for shared state in agent code
|
|
209
|
+
- Verify async/await used correctly
|
|
210
|
+
- Look for blocking operations
|
|
211
|
+
|
|
212
|
+
## Next Steps
|
|
213
|
+
|
|
214
|
+
After implementing the skill system:
|
|
215
|
+
1. Monitor skill selection accuracy
|
|
216
|
+
2. Refine keyword mappings based on usage
|
|
217
|
+
3. Add new skills as needed
|
|
218
|
+
4. Consider A/B testing responses with/without skills
|
|
219
|
+
5. Collect metrics on skill usage frequency
|
|
220
|
+
|
|
221
|
+
## Related Skills
|
|
222
|
+
|
|
223
|
+
- **mcp-tools**: For understanding MCP tool development
|
|
224
|
+
- **hailer-api**: For Hailer API integration details
|
|
225
|
+
|
|
226
|
+
## Maintenance
|
|
227
|
+
|
|
228
|
+
**Adding New Skills**:
|
|
229
|
+
1. Create skill directory in `.claude/skills/`
|
|
230
|
+
2. Write SKILL.md and reference docs
|
|
231
|
+
3. Add keyword mappings to skill-manager.ts
|
|
232
|
+
4. Test with sample messages
|
|
233
|
+
5. Deploy
|
|
234
|
+
|
|
235
|
+
**Updating Skills**:
|
|
236
|
+
1. Edit skill markdown files
|
|
237
|
+
2. Restart server (clears cache)
|
|
238
|
+
3. Test changes
|
|
239
|
+
|
|
240
|
+
**Removing Skills**:
|
|
241
|
+
1. Remove directory from `.claude/skills/`
|
|
242
|
+
2. Remove keyword mappings from skill-manager.ts
|
|
243
|
+
3. Restart server
|
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
# Architecture Patterns for Skill-Based Agents
|
|
2
|
+
|
|
3
|
+
## Core Architecture Pattern
|
|
4
|
+
|
|
5
|
+
### Component Diagram
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌──────────────────────────────────────────┐
|
|
9
|
+
│ User in Hailer │
|
|
10
|
+
│ "Help me create a workflow" │
|
|
11
|
+
└─────────────────┬────────────────────────┘
|
|
12
|
+
│
|
|
13
|
+
▼
|
|
14
|
+
┌──────────────────────────────────────────┐
|
|
15
|
+
│ Hailer Socket.io Signal │
|
|
16
|
+
│ messenger.new event │
|
|
17
|
+
└─────────────────┬────────────────────────┘
|
|
18
|
+
│
|
|
19
|
+
▼
|
|
20
|
+
┌──────────────────────────────────────────┐
|
|
21
|
+
│ MCP Client │
|
|
22
|
+
│ Receives signal, extracts message │
|
|
23
|
+
└─────────────────┬────────────────────────┘
|
|
24
|
+
│
|
|
25
|
+
▼
|
|
26
|
+
┌──────────────────────────────────────────┐
|
|
27
|
+
│ Message Processor │
|
|
28
|
+
│ Parses message content │
|
|
29
|
+
└─────────────────┬────────────────────────┘
|
|
30
|
+
│
|
|
31
|
+
▼
|
|
32
|
+
┌──────────────────────────────────────────┐
|
|
33
|
+
│ Skill Manager (NEW) │
|
|
34
|
+
│ analyzeRequest(message) │
|
|
35
|
+
│ - Keywords: workflow, create │
|
|
36
|
+
│ - Selected: 'mcp-tools' │
|
|
37
|
+
│ - Confidence: 0.9 │
|
|
38
|
+
└─────────────────┬────────────────────────┘
|
|
39
|
+
│
|
|
40
|
+
▼
|
|
41
|
+
┌──────────────────────────────────────────┐
|
|
42
|
+
│ Skill Loader (NEW) │
|
|
43
|
+
│ load('mcp-tools') │
|
|
44
|
+
│ - Reads .claude/skills/mcp-tools/ │
|
|
45
|
+
│ - Returns full skill content │
|
|
46
|
+
└─────────────────┬────────────────────────┘
|
|
47
|
+
│
|
|
48
|
+
▼
|
|
49
|
+
┌──────────────────────────────────────────┐
|
|
50
|
+
│ Enhanced System Prompt │
|
|
51
|
+
│ Base prompt + skill content │
|
|
52
|
+
└─────────────────┬────────────────────────┘
|
|
53
|
+
│
|
|
54
|
+
▼
|
|
55
|
+
┌──────────────────────────────────────────┐
|
|
56
|
+
│ LLM Provider (OpenAI/Anthropic) │
|
|
57
|
+
│ Sends enhanced prompt to LLM │
|
|
58
|
+
└─────────────────┬────────────────────────┘
|
|
59
|
+
│
|
|
60
|
+
▼
|
|
61
|
+
┌──────────────────────────────────────────┐
|
|
62
|
+
│ LLM Response │
|
|
63
|
+
│ Expert answer about workflows │
|
|
64
|
+
└─────────────────┬────────────────────────┘
|
|
65
|
+
│
|
|
66
|
+
▼
|
|
67
|
+
┌──────────────────────────────────────────┐
|
|
68
|
+
│ Posted to Hailer │
|
|
69
|
+
│ User sees response │
|
|
70
|
+
└──────────────────────────────────────────┘
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Data Flow Patterns
|
|
74
|
+
|
|
75
|
+
### Request Processing Flow
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
// 1. Message arrives
|
|
79
|
+
const signal = { type: 'messenger.new', data: {...} };
|
|
80
|
+
|
|
81
|
+
// 2. Extract message
|
|
82
|
+
const message = {
|
|
83
|
+
content: "Help me create a workflow",
|
|
84
|
+
userId: "user123",
|
|
85
|
+
discussionId: "disc456"
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// 3. Analyze with Skill Manager
|
|
89
|
+
const guidance = {
|
|
90
|
+
skills: ['mcp-tools'],
|
|
91
|
+
confidence: 0.9,
|
|
92
|
+
guidance: "Workflow creation request",
|
|
93
|
+
recommendedTools: ['install_workflow'],
|
|
94
|
+
skillContent: "...full mcp-tools skill content..."
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// 4. Build enhanced prompt
|
|
98
|
+
const systemPrompt = `
|
|
99
|
+
You are an AI assistant...
|
|
100
|
+
|
|
101
|
+
DOMAIN EXPERTISE:
|
|
102
|
+
${guidance.skillContent}
|
|
103
|
+
|
|
104
|
+
GUIDANCE:
|
|
105
|
+
${guidance.guidance}
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
// 5. Send to LLM
|
|
109
|
+
const response = await llm.chat({
|
|
110
|
+
messages: [
|
|
111
|
+
{ role: 'system', content: systemPrompt },
|
|
112
|
+
{ role: 'user', content: message.content }
|
|
113
|
+
]
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 6. Post response
|
|
117
|
+
await hailer.postMessage(response);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Concurrency Pattern
|
|
121
|
+
|
|
122
|
+
### How Multiple Requests are Handled
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
// Time: 0ms
|
|
126
|
+
handleMessage(userA, "create workflow")
|
|
127
|
+
↓ starts async execution
|
|
128
|
+
↓ skill analysis: 5ms
|
|
129
|
+
↓ skill loading: 10ms (cached after first)
|
|
130
|
+
↓ LLM call starts...
|
|
131
|
+
⏳ waiting for LLM (2000ms)
|
|
132
|
+
|
|
133
|
+
// Time: 100ms (while A is waiting for LLM)
|
|
134
|
+
handleMessage(userB, "list activities")
|
|
135
|
+
↓ starts async execution (doesn't block A!)
|
|
136
|
+
↓ skill analysis: 5ms
|
|
137
|
+
↓ skill loading: 0ms (cached)
|
|
138
|
+
↓ LLM call starts...
|
|
139
|
+
⏳ waiting for LLM (2000ms)
|
|
140
|
+
|
|
141
|
+
// Time: 200ms (while A and B waiting)
|
|
142
|
+
handleMessage(userC, "analyze data")
|
|
143
|
+
↓ starts async execution (doesn't block!)
|
|
144
|
+
↓ skill analysis: 5ms
|
|
145
|
+
↓ skill loading: 0ms (cached)
|
|
146
|
+
↓ LLM call starts...
|
|
147
|
+
⏳ waiting for LLM (2000ms)
|
|
148
|
+
|
|
149
|
+
// All 3 requests processed concurrently!
|
|
150
|
+
// Responses arrive as LLMs complete
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Key Points
|
|
154
|
+
|
|
155
|
+
- **Async/Await**: Each request is independent
|
|
156
|
+
- **No Blocking**: Requests don't wait for each other
|
|
157
|
+
- **Stateless**: No shared state between requests
|
|
158
|
+
- **Concurrent LLM Calls**: All 3 LLM calls happen simultaneously
|
|
159
|
+
|
|
160
|
+
## Integration Points
|
|
161
|
+
|
|
162
|
+
### Existing Components (Don't Modify)
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
✅ MCP Client (mcp-client.ts)
|
|
166
|
+
- Receives Hailer signals
|
|
167
|
+
- Manages bot lifecycle
|
|
168
|
+
|
|
169
|
+
✅ Multi-Bot Manager (multi-bot-manager.ts)
|
|
170
|
+
- Manages bot connections
|
|
171
|
+
- Already supports multiple bots
|
|
172
|
+
|
|
173
|
+
✅ Signal Handler (signal-handler.ts)
|
|
174
|
+
- Handles socket.io signals
|
|
175
|
+
- Subscription management
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Components to Modify
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
📝 Message Processor (message-processor.ts)
|
|
182
|
+
ADD: Skill manager calls
|
|
183
|
+
ADD: Pass skill context to provider
|
|
184
|
+
|
|
185
|
+
📝 LLM Providers (openai-provider.ts, anthropic-provider.ts)
|
|
186
|
+
ADD: Accept skill guidance parameter
|
|
187
|
+
MODIFY: Build enhanced system prompts
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Components to Create
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
✨ Skill Loader (skill-loader.ts)
|
|
194
|
+
NEW: Load skill files from disk
|
|
195
|
+
NEW: Cache skills in memory
|
|
196
|
+
|
|
197
|
+
✨ Skill Manager (skill-manager.ts)
|
|
198
|
+
NEW: Analyze requests
|
|
199
|
+
NEW: Select appropriate skills
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Design Patterns Used
|
|
203
|
+
|
|
204
|
+
### 1. Strategy Pattern (Skill Selection)
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
interface SkillMatcher {
|
|
208
|
+
match(message: string): boolean;
|
|
209
|
+
getSkillName(): string;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Different matching strategies
|
|
213
|
+
class KeywordMatcher implements SkillMatcher { ... }
|
|
214
|
+
class RegexMatcher implements SkillMatcher { ... }
|
|
215
|
+
class MLMatcher implements SkillMatcher { ... }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 2. Cache Pattern (Skill Loading)
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
class SkillLoader {
|
|
222
|
+
private cache = new Map<string, LoadedSkill>();
|
|
223
|
+
|
|
224
|
+
async load(name: string): Promise<LoadedSkill> {
|
|
225
|
+
if (this.cache.has(name)) {
|
|
226
|
+
return this.cache.get(name)!; // O(1) retrieval
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const skill = await this.loadFromDisk(name);
|
|
230
|
+
this.cache.set(name, skill);
|
|
231
|
+
return skill;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 3. Decorator Pattern (Enhanced Prompts)
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
// Base prompt
|
|
240
|
+
const basePrompt = "You are an AI assistant...";
|
|
241
|
+
|
|
242
|
+
// Decorated with skill content
|
|
243
|
+
const enhancedPrompt = `
|
|
244
|
+
${basePrompt}
|
|
245
|
+
|
|
246
|
+
DOMAIN EXPERTISE:
|
|
247
|
+
${skillContent}
|
|
248
|
+
`;
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### 4. Factory Pattern (Provider Selection)
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
// Already exists in current architecture
|
|
255
|
+
class ProviderFactory {
|
|
256
|
+
createProvider(type: string): LlmProvider {
|
|
257
|
+
switch(type) {
|
|
258
|
+
case 'openai': return new OpenAIProvider();
|
|
259
|
+
case 'anthropic': return new AnthropicProvider();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Error Handling Patterns
|
|
266
|
+
|
|
267
|
+
### Graceful Degradation
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
async analyzeRequest(message: string): Promise<SkillGuidance> {
|
|
271
|
+
try {
|
|
272
|
+
// Try to load skill
|
|
273
|
+
const skill = await this.skillLoader.load(skillName);
|
|
274
|
+
return { ...guidance, skillContent: skill.content };
|
|
275
|
+
} catch (error) {
|
|
276
|
+
// Skill loading failed - degrade gracefully
|
|
277
|
+
logger.error('Skill loading failed', error);
|
|
278
|
+
return { ...guidance, skillContent: undefined };
|
|
279
|
+
// Agent still works, just without skill enhancement
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Fallback Pattern
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
async analyzeRequest(message: string): Promise<SkillGuidance> {
|
|
288
|
+
const primarySkill = this.selectPrimarySkill(message);
|
|
289
|
+
|
|
290
|
+
if (!primarySkill) {
|
|
291
|
+
// No skill matched - use default
|
|
292
|
+
return this.getDefaultGuidance();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
return await this.loadSkillGuidance(primarySkill);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
// Primary skill failed - try fallback
|
|
299
|
+
logger.warn('Primary skill failed, using fallback');
|
|
300
|
+
return this.getDefaultGuidance();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Performance Patterns
|
|
306
|
+
|
|
307
|
+
### Lazy Loading
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// Skills only loaded when needed
|
|
311
|
+
class SkillManager {
|
|
312
|
+
async analyzeRequest(message: string) {
|
|
313
|
+
// 1. Quick keyword analysis (1-5ms)
|
|
314
|
+
const skillName = this.selectSkill(message);
|
|
315
|
+
|
|
316
|
+
// 2. Only load if skill selected
|
|
317
|
+
if (skillName) {
|
|
318
|
+
const skill = await this.skillLoader.load(skillName);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Eager Caching
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
// Preload common skills on startup
|
|
328
|
+
class SkillLoader {
|
|
329
|
+
async preloadCommonSkills() {
|
|
330
|
+
await Promise.all([
|
|
331
|
+
this.load('mcp-tools'),
|
|
332
|
+
this.load('hailer-api')
|
|
333
|
+
]);
|
|
334
|
+
// Now cached for instant retrieval
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Scalability Patterns
|
|
340
|
+
|
|
341
|
+
### Horizontal Scaling
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
Load Balancer
|
|
345
|
+
├─ Server 1 (Agent + Skills)
|
|
346
|
+
├─ Server 2 (Agent + Skills)
|
|
347
|
+
└─ Server 3 (Agent + Skills)
|
|
348
|
+
|
|
349
|
+
Each server:
|
|
350
|
+
- Has its own skill cache
|
|
351
|
+
- Handles subset of users
|
|
352
|
+
- Shares same skill files (via NFS/S3)
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Vertical Scaling
|
|
356
|
+
|
|
357
|
+
```
|
|
358
|
+
Single Server
|
|
359
|
+
├─ Agent Instance (handles all requests)
|
|
360
|
+
├─ Skill Cache (shared in memory)
|
|
361
|
+
└─ LLM Provider (concurrent API calls)
|
|
362
|
+
|
|
363
|
+
Handles 100+ concurrent users easily
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Testing Patterns
|
|
367
|
+
|
|
368
|
+
### Unit Testing
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
describe('SkillManager', () => {
|
|
372
|
+
it('selects correct skill', async () => {
|
|
373
|
+
const manager = new SkillManager(mockLoader);
|
|
374
|
+
const guidance = await manager.analyzeRequest("create workflow");
|
|
375
|
+
expect(guidance.skills).toContain('mcp-tools');
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Integration Testing
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
describe('Message Flow', () => {
|
|
384
|
+
it('enhances prompts with skills', async () => {
|
|
385
|
+
const processor = new MessageProcessor(mockManager);
|
|
386
|
+
const result = await processor.process(mockMessage);
|
|
387
|
+
expect(result.systemPrompt).toContain('DOMAIN EXPERTISE');
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### E2E Testing
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
describe('Hailer Integration', () => {
|
|
396
|
+
it('responds with skill-enhanced answers', async () => {
|
|
397
|
+
await sendHailerMessage("create workflow");
|
|
398
|
+
const response = await waitForResponse();
|
|
399
|
+
expect(response).toContain('install_workflow');
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Monitoring Patterns
|
|
405
|
+
|
|
406
|
+
### Skill Usage Metrics
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
class SkillManager {
|
|
410
|
+
private metrics = new Map<string, number>();
|
|
411
|
+
|
|
412
|
+
async analyzeRequest(message: string) {
|
|
413
|
+
const guidance = ...;
|
|
414
|
+
|
|
415
|
+
// Track usage
|
|
416
|
+
for (const skill of guidance.skills) {
|
|
417
|
+
this.metrics.set(skill, (this.metrics.get(skill) || 0) + 1);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return guidance;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
getMetrics() {
|
|
424
|
+
return Array.from(this.metrics.entries())
|
|
425
|
+
.sort(([,a], [,b]) => b - a);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Performance Tracking
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
async analyzeRequest(message: string) {
|
|
434
|
+
const start = Date.now();
|
|
435
|
+
const guidance = await this.doAnalysis(message);
|
|
436
|
+
const duration = Date.now() - start;
|
|
437
|
+
|
|
438
|
+
this.logger.info('Skill analysis complete', {
|
|
439
|
+
duration,
|
|
440
|
+
selectedSkills: guidance.skills,
|
|
441
|
+
confidence: guidance.confidence
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
return guidance;
|
|
445
|
+
}
|
|
446
|
+
```
|