toolpack-sdk 1.4.0 → 2.0.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Toolpack SDK
2
2
 
3
- A unified TypeScript/Node.js SDK for building AI-powered applications with multiple providers, 90 built-in tools, a workflow engine, and a flexible mode system — all through a single API.
3
+ A unified TypeScript/Node.js SDK for building AI-powered applications with multiple providers, 100+ built-in tools, a workflow engine, and a flexible mode system — all through a single API.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/toolpack-sdk.svg)](https://www.npmjs.com/package/toolpack-sdk)
6
6
  [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
@@ -9,31 +9,34 @@ A unified TypeScript/Node.js SDK for building AI-powered applications with multi
9
9
 
10
10
  ## Features
11
11
 
12
- - **Unified API** — Single interface for OpenAI, Anthropic, Google Gemini, Ollama, and custom providers
12
+ - **Unified API** — Single interface for OpenAI, Anthropic, Google Gemini, Ollama, OpenRouter, and custom providers
13
13
  - **Streaming** — Real-time response streaming across all providers
14
14
  - **Type-Safe** — Comprehensive TypeScript types throughout
15
15
  - **Multimodal** — Text and image inputs (vision) across all providers
16
16
  - **Embeddings** — Vector generation for RAG applications (OpenAI, Gemini, Ollama)
17
- - **Workflow Engine** — AI-driven planning and step-by-step task execution with progress events
17
+ - **Workflow Engine** — AI-driven planning with plan-direct execution and parallel tool orchestration
18
18
  - **Mode System** — Built-in Agent and Chat modes, plus `createMode()` for custom modes with tool filtering
19
19
  - **HITL Confirmation** — Human-in-the-loop approval for high-risk operations with configurable bypass rules
20
20
  - **Custom Providers** — Bring your own provider by implementing the `ProviderAdapter` interface
21
- - **90 Built-in Tools** across 11 categories:
21
+ - **101 Built-in Tools** across 14 categories (including 4 skill-tools and 2 mcp-tools):
22
22
  - **MCP Tool Server Integration** — dynamically bridge external Model Context Protocol servers into Toolpack as first-class tools via `createMcpToolProject()` and `disconnectMcpToolProject()`.
23
23
 
24
24
  | Category | Tools | Description |
25
25
  |----------|-------|-------------|
26
26
  | **`fs-tools`** | 18 | File system operations — read, write, search, tree, glob, batch read/write, etc. |
27
27
  | **`coding-tools`** | 12 | Code analysis — AST parsing, go to definition, find references, rename symbols, extract function |
28
- | **`git-tools`** | 9 | Version control — status, diff, log, blame, branch, commit, checkout |
28
+ | **`git-tools`** | 10 | Version control — status, diff, log, blame, branch, commit, checkout, clone |
29
29
  | **`db-tools`** | 7 | Database operations — query, schema, tables, count, insert, update, delete (SQLite, PostgreSQL, MySQL) |
30
30
  | **`exec-tools`** | 6 | Command execution — run, run shell, background processes, kill, read output |
31
31
  | **`http-tools`** | 5 | HTTP requests — GET, POST, PUT, DELETE, download |
32
32
  | **`web-tools`** | 9 | Web interaction — fetch, search (Tavily/Brave/DuckDuckGo), scrape, extract links, map, metadata, sitemap, feed, screenshot |
33
33
  | **`system-tools`** | 5 | System info — env vars, cwd, disk usage, system info, set env |
34
+ | **`github-tools`** | 9 | GitHub operations — PR reviews, review threads, file diffs, issue comments, GraphQL, repo contents |
35
+ | **`slack-tools`** | 6 | Slack messaging — post messages, ephemeral messages, channel history, thread replies, reactions |
34
36
  | **`diff-tools`** | 3 | Patch operations — create, apply, and preview diffs |
35
37
  | **`cloud-tools`** | 3 | Deployments — deploy, status, list (via Netlify) |
36
38
  | **`k8s-tools`** | 11 | Kubernetes cluster inspection and management via kubectl |
39
+ | **`skill-tools`** | 4 | Skill management — skill.create, skill.read, skill.update, skill.list |
37
40
  | **`mcp-tools`** | 2 | MCP integration — createMcpToolProject, disconnectMcpToolProject |
38
41
 
39
42
  ## Quick Start
@@ -60,7 +63,7 @@ const sdk = await Toolpack.init({
60
63
  anthropic: {}, // Reads ANTHROPIC_API_KEY from env
61
64
  },
62
65
  defaultProvider: 'openai',
63
- tools: true, // Load all 90 built-in tools
66
+ tools: true, // Load all 100+ built-in tools
64
67
  defaultMode: 'agent', // Agent mode with workflow engine
65
68
  });
66
69
 
@@ -78,7 +81,7 @@ for await (const chunk of sdk.stream({
78
81
 
79
82
  // Switch providers on the fly
80
83
  const anthropicResponse = await sdk.generate({
81
- model: 'claude-sonnet-4-20250514',
84
+ model: 'your-model',
82
85
  messages: [{ role: 'user', content: 'Hello from Anthropic!' }],
83
86
  }, 'anthropic');
84
87
  ```
@@ -104,7 +107,7 @@ const sdk = await Toolpack.init({
104
107
  });
105
108
 
106
109
  const podsResponse = await sdk.generate({
107
- model: 'gpt-4o',
110
+ model: 'your-model',
108
111
  messages: [
109
112
  {
110
113
  role: 'user',
@@ -115,7 +118,7 @@ const podsResponse = await sdk.generate({
115
118
  console.log(podsResponse.content);
116
119
 
117
120
  const applyResponse = await sdk.generate({
118
- model: 'gpt-4o',
121
+ model: 'your-model',
119
122
  messages: [
120
123
  {
121
124
  role: 'user',
@@ -140,19 +143,20 @@ See `packages/toolpack-sdk/docs/examples/kubernetes-usage.ts` for a complete exa
140
143
  | **Anthropic** | Claude Sonnet 4, Claude 3.5 Haiku, Claude 3 Opus | No embeddings support |
141
144
  | **Google Gemini** | Gemini 2.0 Flash, Gemini 1.5 Pro, Gemini 1.5 Flash | Synthetic tool call IDs |
142
145
  | **Ollama** | Auto-discovered from locally pulled models | Capability detection via probing |
146
+ | **OpenRouter** | All models at openrouter.ai (auto-discovered) | Access to 300+ models via OpenAI-compatible API |
143
147
 
144
148
  ### Provider Comparison
145
149
 
146
- | Capability | OpenAI | Anthropic | Gemini | Ollama |
147
- |------------|--------|-----------|--------|--------|
148
- | Chat completions | ✅ | ✅ | ✅ | ✅ |
149
- | Streaming | ✅ | ✅ | ✅ | ✅ |
150
- | Tool/function calling | ✅ | ✅ | ✅ | ✅ |
151
- | Multi-round tool loop | ✅ | ✅ | ✅ | ✅ |
152
- | Embeddings | ✅ | ❌ | ✅ | ✅ |
153
- | Vision/images | ✅ | ✅ | ✅ | ✅ (model-dependent) |
154
- | Tool name sanitization | ✅ (auto) | ✅ (auto) | ✅ (auto) | ✅ (auto) |
155
- | Model discovery | Static list | Static list | Static list | Dynamic (`/api/tags` + `/api/show`) |
150
+ | Capability | OpenAI | Anthropic | Gemini | Ollama | OpenRouter |
151
+ |------------|--------|-----------|--------|--------|------------|
152
+ | Chat completions | ✅ | ✅ | ✅ | ✅ | ✅ |
153
+ | Streaming | ✅ | ✅ | ✅ | ✅ | ✅ |
154
+ | Tool/function calling | ✅ | ✅ | ✅ | ✅ | ✅ |
155
+ | Multi-round tool loop | ✅ | ✅ | ✅ | ✅ | ✅ |
156
+ | Embeddings | ✅ | ❌ | ✅ | ✅ | ❌ |
157
+ | Vision/images | ✅ | ✅ | ✅ | ✅ (model-dependent) | ✅ (model-dependent) |
158
+ | Tool name sanitization | ✅ (auto) | ✅ (auto) | ✅ (auto) | ✅ (auto) | ✅ (auto) |
159
+ | Model discovery | Static list | Static list | Static list | Dynamic (`/api/tags` + `/api/show`) | Dynamic (`/models` endpoint) |
156
160
 
157
161
  #### Provider-Specific Notes
158
162
 
@@ -201,6 +205,7 @@ const sdk = await Toolpack.init({
201
205
  See `docs/MCP_INTEGRATION.md` and `docs/examples/mcp-integration-example.ts` for full instructions and best practices.
202
206
  - **Gemini**: Uses synthetic tool call IDs (`gemini_<timestamp>_<random>`) since the Gemini API doesn't return tool call IDs natively. Tool results are converted to `functionResponse` parts in chat history automatically. API key read from `GOOGLE_GENERATIVE_AI_KEY` or `TOOLPACK_GEMINI_KEY`.
203
207
  - **Ollama**: Auto-discovers all locally pulled models when registered as `{ ollama: {} }`. Uses `/api/show` and tool probing to detect capabilities (tool calling, vision, embeddings) per model. Models without tool support are automatically stripped of tools and given a system instruction to prevent hallucinated tool usage. Uses synthetic tool call IDs (`ollama_<timestamp>_<random>`). Embeddings use the modern `/api/embed` batch endpoint. Legacy per-model registration (`{ 'ollama-llama3': {} }`) is also supported.
208
+ - **OpenRouter**: Routes requests to any of the 300+ models available on [openrouter.ai](https://openrouter.ai) via an OpenAI-compatible API. Models are discovered dynamically from the `/models` endpoint. Tool calling is fully supported; models that reject `tool_choice: 'none'` have tools stripped gracefully instead. No embeddings support. Optional `siteUrl` and `siteName` config for OpenRouter's attribution leaderboard. API key read from `OPENROUTER_API_KEY` or `TOOLPACK_OPENROUTER_KEY`.
204
209
 
205
210
  ### Custom Providers
206
211
 
@@ -276,8 +281,8 @@ Modes control AI behavior by setting a system prompt, filtering available tools,
276
281
 
277
282
  | Mode | Tools | Workflow | Description |
278
283
  |------|-------|----------|-------------|
279
- | **Agent** | All tools | Planning + step execution + dynamic steps | Full autonomous access — read, write, execute, browse |
280
- | **Coding** | All tools | Concise planning + step execution | Optimized for coding tasks — minimal text, file operations |
284
+ | **Agent** | All tools | Plan-direct execution | Full autonomous access — read, write, execute, browse |
285
+ | **Coding** | All tools | Plan-direct execution | Optimized for coding tasks — minimal text, file operations |
281
286
  | **Chat** | Web/HTTP only | Direct execution (no planning) | Conversational assistant with web access |
282
287
 
283
288
  ### Custom Modes
@@ -298,7 +303,6 @@ const reviewMode = createMode({
298
303
  },
299
304
  workflow: {
300
305
  planning: { enabled: true },
301
- steps: { enabled: true, retryOnFailure: true },
302
306
  progress: { enabled: true },
303
307
  },
304
308
  });
@@ -338,19 +342,17 @@ sdk.cycleMode(); // Cycles through all registered modes
338
342
  | `blockedTools` | string[] | `[]` | Specific tools to block. Overrides allowed |
339
343
  | `blockAllTools` | boolean | `false` | If `true`, disables all tools (pure conversation) |
340
344
  | `baseContext` | object/false | `undefined` | Controls working directory and tool category injection |
341
- | `workflow` | WorkflowConfig | `undefined` | Planning, step execution, and progress configuration |
345
+ | `workflow` | WorkflowConfig | `undefined` | Planning, execution mode, and progress configuration |
342
346
 
343
347
  ## Workflow Engine
344
348
 
345
- The workflow engine enables AI agents to plan and execute complex tasks step-by-step, with progress tracking, retries, and dynamic step additions.
349
+ The workflow engine enables AI agents to plan and execute complex tasks with parallel tool orchestration.
346
350
 
347
351
  ### How It Works
348
352
 
349
- 1. **Planning** — The AI generates a structured step-by-step plan from the user's request
350
- 2. **Execution** — Each step is executed sequentially with tool access
351
- 3. **Dynamic Steps** — New steps can be added during execution based on results
352
- 4. **Retries** — Failed steps are retried automatically (configurable)
353
- 5. **Progress** — Events are emitted at each stage for UI integration
353
+ 1. **Planning** — The AI generates a structured plan from the user's request
354
+ 2. **Execution** — The plan is injected as context and executed in a single call with parallel tool orchestration
355
+ 3. **Progress** — Events are emitted at each stage for UI integration
354
356
 
355
357
  ### Using the Workflow
356
358
 
@@ -361,7 +363,7 @@ const sdk = await Toolpack.init({
361
363
  defaultMode: 'agent', // Agent mode has workflow enabled
362
364
  });
363
365
 
364
- // Complex tasks are automatically planned and executed step-by-step
366
+ // Complex tasks are automatically planned (plan-direct) with parallel tool execution
365
367
  const result = await sdk.generate('Build me a REST API with user authentication');
366
368
 
367
369
  // Or stream the response
@@ -383,35 +385,18 @@ const executor = sdk.getWorkflowExecutor();
383
385
  // Progress updates (ideal for status bars / shimmer text)
384
386
  executor.on('workflow:progress', (progress) => {
385
387
  // progress.status: 'planning' | 'awaiting_approval' | 'executing' | 'completed' | 'failed'
386
- // progress.currentStep, progress.totalSteps, progress.percentage
387
- // progress.currentStepDescription — includes retry info if retrying
388
- console.log(`[${progress.percentage}%] Step ${progress.currentStep}/${progress.totalSteps}: ${progress.currentStepDescription}`);
388
+ // progress.percentage, progress.currentStepDescription
389
+ console.log(`[${progress.percentage}%] ${progress.currentStepDescription}`);
389
390
  });
390
391
 
391
- // Step lifecycle
392
- executor.on('workflow:step_start', (step, plan) => {
393
- console.log(`Starting: ${step.description}`);
394
- });
395
-
396
- executor.on('workflow:step_complete', (step, plan) => {
397
- console.log(`Completed: ${step.description}`);
398
- });
399
-
400
- executor.on('workflow:step_failed', (step, error, plan) => {
401
- console.log(`Failed: ${step.description} — ${error.message}`);
402
- });
403
-
404
- executor.on('workflow:step_retry', (step, attempt, plan) => {
405
- console.log(`Retrying: ${step.description} (attempt ${attempt})`);
406
- });
407
-
408
- executor.on('workflow:step_added', (step, plan) => {
409
- console.log(`Dynamic step added: ${step.description}`);
392
+ // Plan created
393
+ executor.on('workflow:plan_created', (plan) => {
394
+ console.log('Plan:', plan.steps.map(s => s.description));
410
395
  });
411
396
 
412
397
  // Workflow completion
413
398
  executor.on('workflow:completed', (plan, result) => {
414
- console.log(`Done! ${result.metrics.stepsCompleted} steps in ${result.metrics.totalDuration}ms`);
399
+ console.log(`Done in ${result.metrics.totalDuration}ms`);
415
400
  });
416
401
 
417
402
  executor.on('workflow:failed', (plan, error) => {
@@ -430,22 +415,10 @@ interface WorkflowConfig {
430
415
  maxSteps?: number; // Max steps in a plan (default: 20)
431
416
  };
432
417
 
433
- steps?: {
434
- enabled: boolean; // Enable step-by-step execution
435
- retryOnFailure?: boolean; // Retry failed steps (default: true)
436
- maxRetries?: number; // Max retries per step (default: 3)
437
- allowDynamicSteps?: boolean; // Allow adding steps during execution
438
- maxTotalSteps?: number; // Max total steps including dynamic (default: 50)
439
- };
440
-
441
418
  progress?: {
442
419
  enabled: boolean; // Emit progress events (default: true)
443
420
  reportPercentage?: boolean; // Include completion percentage
444
421
  };
445
-
446
- onFailure?: {
447
- strategy: 'abort' | 'skip' | 'ask_user';
448
- };
449
422
  }
450
423
  ```
451
424
 
@@ -457,12 +430,12 @@ The SDK provides built-in workflow presets for common use cases:
457
430
  import { DEFAULT_WORKFLOW, AGENT_WORKFLOW, CODING_WORKFLOW, CHAT_WORKFLOW } from 'toolpack-sdk';
458
431
  ```
459
432
 
460
- | Preset | Planning | Steps | Description |
461
- |--------|----------|-------|-------------|
462
- | `DEFAULT_WORKFLOW` | Disabled | Disabled | Direct execution, no planning |
463
- | `AGENT_WORKFLOW` | Enabled (detailed) | Enabled | Full autonomous agent with 11 planning rules |
464
- | `CODING_WORKFLOW` | Enabled (concise) | Enabled | Minimal prompts optimized for coding tasks |
465
- | `CHAT_WORKFLOW` | Disabled | Disabled | Simple conversational mode |
433
+ | Preset | Planning | Description |
434
+ |--------|----------|-------------|
435
+ | `DEFAULT_WORKFLOW` | Disabled | Direct execution, no planning |
436
+ | `AGENT_WORKFLOW` | Enabled (detailed) | Full autonomous agent with plan-direct execution |
437
+ | `CODING_WORKFLOW` | Enabled (concise) | Minimal prompts optimized for coding tasks |
438
+ | `CHAT_WORKFLOW` | Disabled | Simple conversational mode |
466
439
 
467
440
  ### Creating Custom Workflows
468
441
 
@@ -485,15 +458,6 @@ Rules:
485
458
  3. Generate docs in consistent format
486
459
  4. Output JSON: {"summary": "...", "steps": [...]}`,
487
460
  },
488
- steps: {
489
- ...AGENT_WORKFLOW.steps,
490
- stepPrompt: `Execute step {stepNumber}: {stepDescription}
491
-
492
- Analyze code and write clear documentation.
493
- Focus on: purpose, parameters, return values, examples.
494
-
495
- Previous: {previousStepsResults}`,
496
- },
497
461
  };
498
462
 
499
463
  // Use in a custom mode
@@ -508,23 +472,11 @@ const docMode = createMode({
508
472
  });
509
473
  ```
510
474
 
511
- ### Step Prompt Template Variables
512
-
513
- When using custom `stepPrompt`, these variables are automatically substituted:
514
-
515
- | Variable | Description |
516
- |----------|-------------|
517
- | `{stepNumber}` | Current step number (1-indexed) |
518
- | `{planSummary}` | Summary of the overall plan |
519
- | `{stepDescription}` | Description of the current step |
520
- | `{previousStepsResults}` | Output from completed steps (truncated to 2000 chars) |
521
-
522
475
  ### Workflow Prompt Tips
523
476
 
524
477
  - **Keep planning prompts concise** — LLMs perform better with 5-7 clear rules
525
478
  - **Use JSON schema examples** — Include the exact expected output format
526
- - **Avoid meta-commentary in step prompts** — The AI should just execute, not discuss
527
- - **Leverage previous results** — The `{previousStepsResults}` variable provides context
479
+ - **Keep prompts task-oriented** — The AI should execute, not discuss
528
480
 
529
481
  ## Tool Call Events
530
482
 
@@ -548,7 +500,7 @@ client.on('tool:failed', (event) => { /* ... */ });
548
500
 
549
501
  ## Custom Tools
550
502
 
551
- In addition to the 90 built-in tools, you can create and register your own custom tool projects using `createToolProject()`:
503
+ In addition to the 100+ built-in tools, you can create and register your own custom tool projects using `createToolProject()`:
552
504
 
553
505
  ```typescript
554
506
  import { Toolpack, createToolProject } from 'toolpack-sdk';
@@ -644,7 +596,424 @@ const response = await toolpack.chat('How do I configure authentication?');
644
596
  - **Progress Events**: Track embedding progress with `onEmbeddingProgress`
645
597
  - **Metadata Filtering**: Query with filters like `{ hasCode: true, category: 'api' }`
646
598
 
647
- See the [Knowledge package README](../toolpack-knowledge/README.md) for full documentation.
599
+ See the [Knowledge package README](./packages/toolpack-knowledge/README.md) for full documentation.
600
+
601
+ ## Skills
602
+
603
+ The skills system lets you define **reusable behavioral instructions** in `.skill.md` files and automatically inject them into requests based on message relevance — no agent code changes required.
604
+
605
+ ### Quick Start
606
+
607
+ ```typescript
608
+ import { Toolpack, createSkillInterceptor, createSkillTools } from 'toolpack-sdk';
609
+
610
+ const toolpack = await Toolpack.init({
611
+ provider: 'anthropic',
612
+ interceptors: [
613
+ createSkillInterceptor({ dir: '.toolpack/skills', maxSkills: 3, minScore: 0.3 }),
614
+ ],
615
+ customTools: [
616
+ createSkillTools({ dir: '.toolpack/skills' }),
617
+ ],
618
+ });
619
+ ```
620
+
621
+ Create a skill file at `.toolpack/skills/code-review.skill.md`:
622
+
623
+ ```markdown
624
+ ---
625
+ name: code-review
626
+ title: Code Review
627
+ version: 1.0.0
628
+ tags: ["coding", "quality"]
629
+ updated: 2026-01-15T10:00:00.000Z
630
+ ---
631
+
632
+ ## Description
633
+
634
+ Guides the agent through a structured code review process.
635
+
636
+ ## Triggers
637
+
638
+ - "review this code"
639
+ - "check my pull request"
640
+ - "code review"
641
+
642
+ ## Instructions
643
+
644
+ When reviewing code:
645
+ 1. Check for security vulnerabilities first
646
+ 2. Verify test coverage exists
647
+ 3. Flag naming inconsistencies
648
+ 4. Be constructive — suggest improvements, not just problems
649
+ ```
650
+
651
+ When a user sends "review this PR", the interceptor automatically injects the `## Instructions` block before the LLM sees the message.
652
+
653
+ ### How It Works
654
+
655
+ - **`createSkillInterceptor`** — An SDK interceptor that runs BM25 search on every user message and prepends matching skill instructions as a `<skill-instructions>` block. Validates all files at `Toolpack.init()` time.
656
+ - **`createSkillTools`** — Four LLM-callable tools (`skill.create`, `skill.read`, `skill.update`, `skill.list`) for managing the skill library at runtime.
657
+
658
+ ### `createSkillInterceptor` Options
659
+
660
+ | Option | Type | Default | Description |
661
+ |--------|------|---------|-------------|
662
+ | `dir` | string | `.toolpack/skills` | Path to the skill files directory |
663
+ | `maxSkills` | number | `3` | Maximum number of skills injected per message |
664
+ | `minScore` | number | `0.3` | BM25 relevance threshold |
665
+ | `onValidationError` | `'fail'` \| `'warn'` | `'fail'` | How to handle invalid skill files at startup |
666
+
667
+ See the [Skills guide](https://toolpacksdk.com/guides/skills) and [Skill Tools reference](https://toolpacksdk.com/tools/skills) for full documentation.
668
+
669
+ ## AI Agents (@toolpack-sdk/agents)
670
+
671
+ Build production-ready AI agents with channels, workflows, and event-driven architecture using the companion `@toolpack-sdk/agents` package:
672
+
673
+ ```bash
674
+ npm install @toolpack-sdk/agents
675
+ ```
676
+
677
+ ### What are Agents?
678
+
679
+ Agents are autonomous AI systems that:
680
+ - **Listen** for events from channels (Slack, webhooks, schedules, etc.)
681
+ - **Process** messages using the Toolpack SDK
682
+ - **Execute** tasks with full tool access
683
+ - **Respond** back through the same or different channels
684
+ - **Remember** conversations using knowledge bases
685
+
686
+ ### Quick Start
687
+
688
+ ```typescript
689
+ import { Toolpack } from 'toolpack-sdk';
690
+ import { BaseAgent, AgentRegistry, SlackChannel } from '@toolpack-sdk/agents';
691
+
692
+ // 1. Create a custom agent
693
+ class SupportAgent extends BaseAgent {
694
+ name = 'support-agent';
695
+ description = 'Customer support agent that answers questions';
696
+ mode = 'chat';
697
+
698
+ async invokeAgent(input) {
699
+ const result = await this.run(input.message);
700
+ await this.sendTo('slack-support', result.output);
701
+ return result;
702
+ }
703
+ }
704
+
705
+ // 2. Set up channels
706
+ const slackChannel = new SlackChannel({
707
+ name: 'slack-support',
708
+ token: process.env.SLACK_BOT_TOKEN,
709
+ signingSecret: process.env.SLACK_SIGNING_SECRET,
710
+ });
711
+
712
+ // 3. Register agent and channels
713
+ const registry = new AgentRegistry([
714
+ { agent: SupportAgent, channels: [slackChannel] },
715
+ ]);
716
+
717
+ // 4. Initialize Toolpack with agents
718
+ const sdk = await Toolpack.init({
719
+ provider: 'openai',
720
+ tools: true,
721
+ agents: registry,
722
+ });
723
+
724
+ // Agents now listen and respond automatically!
725
+ ```
726
+
727
+ ### Built-in Agents
728
+
729
+ The package includes 4 production-ready agents you can use directly or extend:
730
+
731
+ #### ResearchAgent
732
+ ```typescript
733
+ import { ResearchAgent } from '@toolpack-sdk/agents';
734
+
735
+ const agent = new ResearchAgent(sdk);
736
+ const result = await agent.invokeAgent({
737
+ message: 'Summarize recent developments in edge AI',
738
+ });
739
+ ```
740
+ - **Mode:** `agent`
741
+ - **Tools:** web.search, web.fetch, web.scrape
742
+ - **Use Cases:** Market research, competitive analysis, trend monitoring
743
+
744
+ #### CodingAgent
745
+ ```typescript
746
+ import { CodingAgent } from '@toolpack-sdk/agents';
747
+
748
+ const agent = new CodingAgent(sdk);
749
+ const result = await agent.invokeAgent({
750
+ message: 'Refactor the auth module to use the new SDK pattern',
751
+ });
752
+ ```
753
+ - **Mode:** `coding`
754
+ - **Tools:** fs.*, coding.*, git.*, exec.*
755
+ - **Use Cases:** Code generation, refactoring, debugging, test writing
756
+
757
+ #### DataAgent
758
+ ```typescript
759
+ import { DataAgent } from '@toolpack-sdk/agents';
760
+
761
+ const agent = new DataAgent(sdk);
762
+ const result = await agent.invokeAgent({
763
+ message: 'Generate a weekly summary of signups by region',
764
+ });
765
+ ```
766
+ - **Mode:** `agent`
767
+ - **Tools:** db.*, fs.*, http.*
768
+ - **Use Cases:** Database queries, reporting, data analysis, CSV generation
769
+
770
+ #### BrowserAgent
771
+ ```typescript
772
+ import { BrowserAgent } from '@toolpack-sdk/agents';
773
+
774
+ const agent = new BrowserAgent(sdk);
775
+ const result = await agent.invokeAgent({
776
+ message: 'Extract all product prices from acme.com/products',
777
+ });
778
+ ```
779
+ - **Mode:** `chat`
780
+ - **Tools:** web.fetch, web.screenshot, web.extract_links
781
+ - **Use Cases:** Web scraping, form filling, content extraction
782
+
783
+ ### Channels
784
+
785
+ Channels connect agents to the outside world. The package includes 7 built-in channels:
786
+
787
+ #### SlackChannel (Two-way)
788
+ ```typescript
789
+ import { SlackChannel } from '@toolpack-sdk/agents';
790
+
791
+ const slack = new SlackChannel({
792
+ name: 'slack-support',
793
+ token: process.env.SLACK_BOT_TOKEN,
794
+ signingSecret: process.env.SLACK_SIGNING_SECRET,
795
+ });
796
+ ```
797
+ - ✅ Receives messages from Slack
798
+ - ✅ Replies in threads
799
+ - ✅ Supports `ask()` for human input
800
+
801
+ #### TelegramChannel (Two-way)
802
+ ```typescript
803
+ import { TelegramChannel } from '@toolpack-sdk/agents';
804
+
805
+ const telegram = new TelegramChannel({
806
+ name: 'telegram-bot',
807
+ token: process.env.TELEGRAM_BOT_TOKEN,
808
+ });
809
+ ```
810
+ - ✅ Receives messages from Telegram
811
+ - ✅ Replies to users
812
+ - ✅ Supports `ask()` for human input
813
+
814
+ #### WebhookChannel (Two-way)
815
+ ```typescript
816
+ import { WebhookChannel } from '@toolpack-sdk/agents';
817
+
818
+ const webhook = new WebhookChannel({
819
+ name: 'github-webhook',
820
+ path: '/webhook/github',
821
+ port: 3000,
822
+ secret: process.env.WEBHOOK_SECRET,
823
+ });
824
+ ```
825
+ - ✅ Receives HTTP POST webhooks
826
+ - ✅ Signature verification
827
+ - ✅ Supports `ask()` for human input
828
+
829
+ #### ScheduledChannel (Trigger-only)
830
+ ```typescript
831
+ import { ScheduledChannel } from '@toolpack-sdk/agents';
832
+
833
+ const scheduler = new ScheduledChannel({
834
+ name: 'daily-report',
835
+ cron: '0 9 * * 1-5', // 9am weekdays
836
+ notify: 'webhook:https://hooks.example.com/daily-report',
837
+ message: 'Generate the daily sales report',
838
+ });
839
+ // For Slack delivery, attach a named SlackChannel to the same agent and
840
+ // call `this.sendTo('<slackChannelName>', output)` from within `run()`.
841
+ ```
842
+ - ⏰ Triggers agents on cron schedules
843
+ - ✅ Full cron expression support (ranges, steps, lists, combinations)
844
+ - ❌ No `ask()` support (no human recipient)
845
+
846
+ #### DiscordChannel (Two-way)
847
+ ```typescript
848
+ import { DiscordChannel } from '@toolpack-sdk/agents';
849
+
850
+ const discord = new DiscordChannel({
851
+ name: 'discord-bot',
852
+ token: process.env.DISCORD_BOT_TOKEN,
853
+ guildId: 'your-guild-id',
854
+ channelId: 'your-channel-id',
855
+ });
856
+ ```
857
+ - ✅ Receives messages from Discord
858
+ - ✅ Replies in threads
859
+ - ✅ Supports `ask()` for human input
860
+
861
+ #### EmailChannel (Outbound-only)
862
+ ```typescript
863
+ import { EmailChannel } from '@toolpack-sdk/agents';
864
+
865
+ const email = new EmailChannel({
866
+ name: 'email-alerts',
867
+ from: 'bot@acme.com',
868
+ to: 'team@acme.com',
869
+ smtp: {
870
+ host: 'smtp.gmail.com',
871
+ port: 587,
872
+ auth: { user: 'bot@acme.com', pass: process.env.SMTP_PASSWORD },
873
+ },
874
+ });
875
+ ```
876
+ - 📧 Sends emails via SMTP
877
+ - ❌ No `ask()` support (outbound-only)
878
+
879
+ #### SMSChannel (Configurable)
880
+ ```typescript
881
+ import { SMSChannel } from '@toolpack-sdk/agents';
882
+
883
+ // Two-way with webhook
884
+ const sms = new SMSChannel({
885
+ name: 'sms-alerts',
886
+ accountSid: process.env.TWILIO_ACCOUNT_SID,
887
+ authToken: process.env.TWILIO_AUTH_TOKEN,
888
+ from: '+1234567890',
889
+ webhookPath: '/sms/webhook', // Enables two-way
890
+ port: 3000,
891
+ });
892
+
893
+ // Outbound-only
894
+ const smsOutbound = new SMSChannel({
895
+ name: 'sms-notifications',
896
+ accountSid: process.env.TWILIO_ACCOUNT_SID,
897
+ authToken: process.env.TWILIO_AUTH_TOKEN,
898
+ from: '+1234567890',
899
+ to: '+0987654321', // Fixed recipient
900
+ });
901
+ ```
902
+ - 📱 Twilio SMS integration
903
+ - ✅ Two-way when `webhookPath` is set
904
+ - ❌ Outbound-only without webhook
905
+
906
+ ### Agent Lifecycle & Events
907
+
908
+ Agents emit events at each stage of execution:
909
+
910
+ ```typescript
911
+ const agent = new MyAgent(sdk);
912
+
913
+ agent.on('agent:start', (input) => {
914
+ console.log('Agent started:', input.message);
915
+ });
916
+
917
+ agent.on('agent:complete', (result) => {
918
+ console.log('Agent completed:', result.output);
919
+ });
920
+
921
+ agent.on('agent:error', (error) => {
922
+ console.error('Agent error:', error);
923
+ });
924
+ ```
925
+
926
+ ### Knowledge Integration
927
+
928
+ Agents can use knowledge bases for conversation memory and RAG:
929
+
930
+ ```typescript
931
+ import { Knowledge, MemoryProvider, OllamaEmbedder } from '@toolpack-sdk/knowledge';
932
+ import { BaseAgent } from '@toolpack-sdk/agents';
933
+
934
+ class SmartAgent extends BaseAgent {
935
+ name = 'smart-agent';
936
+ description = 'Agent with memory';
937
+ mode = 'chat';
938
+
939
+ constructor(toolpack) {
940
+ super(toolpack);
941
+ // Set up knowledge base
942
+ this.knowledge = await Knowledge.create({
943
+ provider: new MemoryProvider(),
944
+ embedder: new OllamaEmbedder({ model: 'nomic-embed-text' }),
945
+ });
946
+ }
947
+
948
+ async invokeAgent(input) {
949
+ // Conversation history is automatically loaded from knowledge
950
+ const result = await this.run(input.message);
951
+ return result;
952
+ }
953
+ }
954
+ ```
955
+
956
+ ### Multi-Channel Routing
957
+
958
+ Agents can send output to different channels:
959
+
960
+ ```typescript
961
+ class MultiChannelAgent extends BaseAgent {
962
+ name = 'multi-agent';
963
+ description = 'Routes to multiple channels';
964
+ mode = 'agent';
965
+
966
+ async invokeAgent(input) {
967
+ const result = await this.run(input.message);
968
+
969
+ // Send to multiple channels
970
+ await this.sendTo('slack:#general', result.output);
971
+ await this.sendTo('email-team', result.output);
972
+ await this.sendTo('sms-alerts', 'Task completed!');
973
+
974
+ return result;
975
+ }
976
+ }
977
+ ```
978
+
979
+ ### Extending Built-in Agents
980
+
981
+ ```typescript
982
+ import { ResearchAgent } from '@toolpack-sdk/agents';
983
+
984
+ class FintechResearchAgent extends ResearchAgent {
985
+ systemPrompt = `You are a research agent focused on fintech.
986
+ Always cite sources and flag regulatory implications.`;
987
+ provider = 'anthropic';
988
+ model = 'your-model';
989
+
990
+ async onComplete(result) {
991
+ // Store research in knowledge base
992
+ if (this.knowledge) {
993
+ await this.knowledge.add(result.output, {
994
+ category: 'research',
995
+ topic: 'fintech',
996
+ });
997
+ }
998
+
999
+ // Send to Slack
1000
+ await this.sendTo('slack-research', result.output);
1001
+ }
1002
+ }
1003
+ ```
1004
+
1005
+ ### Features
1006
+
1007
+ - ✅ **7 Built-in Channels** — Slack, Telegram, Discord, Email, SMS, Webhook, Scheduled
1008
+ - ✅ **4 Built-in Agents** — Research, Coding, Data, Browser
1009
+ - ✅ **Event-Driven** — Full lifecycle events for monitoring
1010
+ - ✅ **Knowledge Integration** — Conversation memory and RAG
1011
+ - ✅ **Multi-Channel Routing** — Send to any registered channel
1012
+ - ✅ **Human-in-the-Loop** — `ask()` support for two-way channels
1013
+ - ✅ **Type-Safe** — Full TypeScript support
1014
+ - ✅ **199 Tests Passing** — Production-ready
1015
+
1016
+ See the [Agents package README](./packages/toolpack-agents/README.md) for full documentation.
648
1017
 
649
1018
  ## Multimodal Support
650
1019
 
@@ -704,6 +1073,7 @@ const response = await sdk.generate({
704
1073
  export OPENAI_API_KEY="sk-..."
705
1074
  export ANTHROPIC_API_KEY="sk-ant-..."
706
1075
  export GOOGLE_GENERATIVE_AI_KEY="AIza..."
1076
+ export OPENROUTER_API_KEY="sk-or-..."
707
1077
 
708
1078
  # SDK logging (override — prefer toolpack.config.json instead)
709
1079
  export TOOLPACK_SDK_LOG_FILE="./toolpack.log" # Log file path (also enables logging)
@@ -926,6 +1296,7 @@ interface CompletionRequest {
926
1296
  temperature?: number;
927
1297
  max_tokens?: number;
928
1298
  tools?: ToolCallRequest[];
1299
+ requestTools?: RequestToolDefinition[]; // Request-scoped tools
929
1300
  tool_choice?: 'auto' | 'none' | 'required';
930
1301
  }
931
1302
 
@@ -956,6 +1327,115 @@ interface ProviderModelInfo {
956
1327
  }
957
1328
  ```
958
1329
 
1330
+ ### Request-Scoped Tools
1331
+
1332
+ Request-scoped tools are dynamic tools attached to a single completion request. Unlike globally registered tools in the ToolRegistry, they:
1333
+
1334
+ - **Don't pollute the shared registry** — Each request can have its own tools
1335
+ - **Can close over request-specific state** — e.g., `conversationId`, user context
1336
+ - **Are safe for multi-agent/multi-request usage** — No cross-request contamination
1337
+ - **Execute through the same SDK orchestration** — Events, logging, HITL all work
1338
+
1339
+ #### Built-in Request-Scoped Tools
1340
+
1341
+ **Knowledge Tools** (when `knowledge` is configured):
1342
+ - `knowledge_search` — Search the knowledge base for relevant information
1343
+ - `knowledge_add` — Add new content to the knowledge base at runtime
1344
+
1345
+ **Conversation Tools** (when using `ConversationHistory`):
1346
+ - `conversation_search` — Search conversation history for past messages
1347
+
1348
+ #### Creating Custom Request Tools
1349
+
1350
+ ```typescript
1351
+ import { RequestToolDefinition, ConversationHistory } from 'toolpack-sdk';
1352
+
1353
+ // Example: Session-specific calculator
1354
+ const createCalculatorTool = (sessionId: string): RequestToolDefinition => ({
1355
+ name: 'calculate',
1356
+ displayName: 'Calculator',
1357
+ description: 'Perform mathematical calculations',
1358
+ category: 'math',
1359
+ parameters: {
1360
+ type: 'object',
1361
+ properties: {
1362
+ expression: { type: 'string', description: 'Math expression to evaluate' },
1363
+ },
1364
+ required: ['expression'],
1365
+ },
1366
+ execute: async (args) => {
1367
+ // Can safely close over sessionId
1368
+ console.log(`Session ${sessionId}: calculating ${args.expression}`);
1369
+
1370
+ // Simple eval (use a proper math library in production)
1371
+ const result = eval(args.expression);
1372
+ return { result, sessionId };
1373
+ },
1374
+ });
1375
+
1376
+ // Use in a request
1377
+ const result = await sdk.generate({
1378
+ messages: [{ role: 'user', content: 'What is 15 * 23?' }],
1379
+ model: 'gpt-4',
1380
+ requestTools: [createCalculatorTool('user-123')],
1381
+ });
1382
+ ```
1383
+
1384
+ #### Using ConversationHistory with Request Tools
1385
+
1386
+ ```typescript
1387
+ import { ConversationHistory } from 'toolpack-sdk';
1388
+
1389
+ const history = new ConversationHistory('./chat.db');
1390
+
1391
+ // Add some messages
1392
+ await history.addUserMessage('conv-1', 'What is the API rate limit?');
1393
+ await history.addAssistantMessage('conv-1', 'The rate limit is 100 requests per minute.');
1394
+
1395
+ // Use conversation search in a request
1396
+ const result = await sdk.generate({
1397
+ messages: [
1398
+ { role: 'user', content: 'What did we discuss about rate limits?' }
1399
+ ],
1400
+ model: 'gpt-4',
1401
+ requestTools: [
1402
+ history.toTool('conv-1'), // Scoped to conversation 'conv-1'
1403
+ ],
1404
+ });
1405
+
1406
+ // AI can now call conversation_search to find the earlier discussion
1407
+ ```
1408
+
1409
+ #### Request Tools vs Registry Tools
1410
+
1411
+ | Feature | Request Tools | Registry Tools |
1412
+ |---------|---------------|----------------|
1413
+ | **Scope** | Single request | All requests |
1414
+ | **State** | Can close over request state | Stateless |
1415
+ | **Registration** | Per-request via `requestTools` | Global via `ToolRegistry` |
1416
+ | **Use Case** | Dynamic, stateful tools | Reusable, static tools |
1417
+ | **Priority** | Higher (checked first) | Lower |
1418
+ | **Examples** | `conversation_search`, `knowledge_add` | `fs.read_file`, `web.search` |
1419
+
1420
+ #### Automatic Guidance Injection
1421
+
1422
+ When request-scoped tools are present, the SDK automatically injects usage guidance into the system prompt:
1423
+
1424
+ ```
1425
+ Knowledge Base:
1426
+ - Use `knowledge_search` when you need factual or domain-specific information.
1427
+ - Use `knowledge_add` when you learn durable information that should be saved.
1428
+
1429
+ Conversation History:
1430
+ - Only recent messages may be present in context.
1431
+ - Use `conversation_search` to find details from earlier in this conversation.
1432
+ ```
1433
+
1434
+ This guidance is:
1435
+ - **Per-request** — Only injected when tools are actually present
1436
+ - **Derived from effective tool set** — Reflects the actual tools available
1437
+ - **Idempotent** — Won't duplicate if already present
1438
+
959
1439
  ## Error Handling
960
1440
 
961
1441
  The SDK provides typed error classes for common failure scenarios:
@@ -1008,21 +1488,25 @@ toolpack-sdk/
1008
1488
  │ │ ├── openai/ # OpenAI adapter
1009
1489
  │ │ ├── anthropic/ # Anthropic adapter
1010
1490
  │ │ ├── gemini/ # Google Gemini adapter
1491
+ │ │ ├── openrouter/ # OpenRouter adapter (OpenAI-compatible, dynamic model discovery)
1011
1492
  │ │ └── ollama/ # Ollama adapter + provider (auto-discovery)
1012
1493
  │ ├── modes/ # Mode system (Agent, Chat, createMode)
1013
- │ ├── workflows/ # Workflow engine (planner, step executor, progress)
1014
- │ ├── tools/ # 90 built-in tools + registry + router + BM25 search
1494
+ │ ├── workflows/ # Workflow engine (planner, executor, progress)
1495
+ │ ├── tools/ # 100+ built-in tools + registry + router + BM25 search
1015
1496
  │ │ ├── fs-tools/ # File system (18 tools)
1016
1497
  │ │ ├── coding-tools/ # Code analysis (12 tools)
1017
- │ │ ├── git-tools/ # Git operations (9 tools)
1018
- │ │ ├── db-tools/ # Database operations (6 tools)
1498
+ │ │ ├── git-tools/ # Git operations (10 tools)
1499
+ │ │ ├── db-tools/ # Database operations (7 tools)
1019
1500
  │ │ ├── exec-tools/ # Command execution (6 tools)
1020
1501
  │ │ ├── http-tools/ # HTTP requests (5 tools)
1021
- │ │ ├── web-tools/ # Web interaction (5 tools)
1502
+ │ │ ├── web-tools/ # Web interaction (9 tools)
1022
1503
  │ │ ├── system-tools/ # System info (5 tools)
1504
+ │ │ ├── github-tools/ # GitHub API (9 tools)
1505
+ │ │ ├── slack-tools/ # Slack messaging (6 tools)
1023
1506
  │ │ ├── diff-tools/ # Patch operations (3 tools)
1024
1507
  │ │ ├── cloud-tools/ # Deployments (3 tools)
1025
1508
  │ │ ├── k8s-tools/ # Kubernetes management (11 tools)
1509
+ │ │ ├── skill-tools/ # Skill management (4 tools)
1026
1510
  │ │ ├── registry.ts # Tool registry and loading
1027
1511
  │ │ ├── router.ts # Tool routing and filtering
1028
1512
  │ │ └── search/ # BM25 tool discovery engine (internal)
@@ -1037,9 +1521,9 @@ toolpack-sdk/
1037
1521
 
1038
1522
  **Current Version:** 0.1.0
1039
1523
 
1040
- - ✓ **4 Built-in Providers** — OpenAI, Anthropic, Gemini, Ollama (+ custom provider API)
1041
- - ✓ **90 Built-in Tools** — fs, exec, git, diff, web, coding, db, cloud, http, system, Kubernetes
1042
- - ✓ **Workflow Engine** — AI-driven planning, step execution, retries, dynamic steps, progress events
1524
+ - ✓ **5 Built-in Providers** — OpenAI, Anthropic, Gemini, Ollama, OpenRouter (+ custom provider API)
1525
+ - ✓ **100+ Built-in Tools** — fs, exec, git, diff, web, coding, db, cloud, http, system, Kubernetes, GitHub, Slack, Skills
1526
+ - ✓ **Workflow Engine** — AI-driven planning, plan-direct execution, parallel tool orchestration, progress events
1043
1527
  - ✓ **Mode System** — Agent, Coding, Chat, and custom modes via `createMode()` with `blockAllTools` support
1044
1528
  - ✓ **Tool Search** — BM25-based on-demand tool discovery for large tool libraries
1045
1529
  - ✓ **545 Tests** passing across 81 test files