Skip to main content

v3.2.0

Released: September 6, 2026

Highlights

  • File attachments (toolpack-sdk) — new FilePart type and FILE_LIMITS constant; all five providers updated to handle documents and images via URL or data URI
  • registerRequestTools / loadRequestToolProject (toolpack-sdk) — public methods to register tools that bypass mode filtering entirely
  • Improved knowledge and mind tool guidance (toolpack-sdk) — AIClient generates richer instructions that differentiate personal user memory from shared knowledge
  • ChatChannel (@toolpack-sdk/agents) — new externally-driven channel for HTTP-server use cases
  • Agent file attachments (@toolpack-sdk/agents) — AgentInput.attachments and BaseChannel.validateAttachments() for all channels
  • VertexAIEmbedder inline credentials (@toolpack-sdk/knowledge) — pass a service account JSON key directly instead of relying on Application Default Credentials
  • Breaking: createSkillInterceptor removed — use createSkillTools instead

Breaking changes

ChangePackageMigration
createSkillInterceptor removedtoolpack-sdkRemove from interceptors config; use createSkillTools with ModeConfig.customTools
SkillInterceptorOptions type removedtoolpack-sdkNo replacement needed
skillInterceptor?: boolean removed from ModeConfigtoolpack-sdkRemove the field from custom mode definitions
RunContext.tools removed from AgentMind@toolpack-sdk/agentsOnly affects custom AgentMind consumers; BaseAgent handles this automatically

Migrating away from createSkillInterceptor

Before:

import { Toolpack, createSkillInterceptor } from 'toolpack-sdk';

const toolpack = await Toolpack.init({
provider: 'anthropic',
interceptors: [
createSkillInterceptor({ dir: '.toolpack/skills', maxSkills: 3, minScore: 0.3 }),
],
});

After: use createSkillTools — the agent calls skill.read explicitly when it needs instructions:

import { createSkillTools } from 'toolpack-sdk';

const skillTools = createSkillTools({ dir: '.toolpack/skills' });
// agent.mode = { ...agentMode, customTools: [...skillTools.tools] };

toolpack-sdk

FilePart and FILE_LIMITS

Attach non-image files (PDFs, spreadsheets, etc.) to any message using a public URL or data URI:

import { FilePart, FILE_LIMITS } from 'toolpack-sdk';

const doc: FilePart = {
type: 'file',
file: {
url: 'https://example.com/report.pdf',
mimeType: 'application/pdf',
name: 'report.pdf', // optional, display only
size: 204800, // optional bytes, used for client-side limit checks
},
};

const response = await toolpack.generate({
messages: [{ role: 'user', content: [{ type: 'text', text: 'Summarise this' }, doc] }],
model: 'claude-sonnet-5',
});

// FILE_LIMITS.image.maxBytes → 10 MB
// FILE_LIMITS.document.maxBytes → 10 MB
// FILE_LIMITS.document.maxPages → 20 pages

FilePart joins the MessageContent union alongside the existing image types. A data URI (data:<mime>;base64,<data>) is also accepted in file.url.

Provider support

ProviderURLInline base64 (data: URI)
Anthropicimages and documentsauto-routed to image or document block
Anthropic Verteximages and documentsauto-routed to image or document block
GeminifileDatainlineData
VertexAIfileDatainlineData
OpenAIimages and documentsImages only (non-image base64 is dropped)

registerRequestTools() and loadRequestToolProject()

Register tools that bypass mode filtering and are always passed to the model regardless of allowedToolCategories. This is the same mechanism used internally by knowledge and mind tools.

// From a ToolProject:
toolpack.loadRequestToolProject(myProject);

// From raw definitions:
toolpack.registerRequestTools([{ name: 'my_tool', ... }]);

Tools are deduplicated by name — registering the same name twice replaces the existing entry. Knowledge tools are now registered this way at Toolpack.init() time rather than rebuilt on every request.


Improved knowledge and mind tool guidance

When both knowledge_add and mind_believe are available, AIClient now generates distinct guidance:

  • knowledge_search — search proactively before concluding you do not know something
  • knowledge_add — factual domain knowledge (documents, research, organizational data) only; not for personal user facts
  • mind_believe — preferred for personal user facts and preferences
  • mind_reflect — for lessons learned and standing rules
  • mind_recall — for searching personal memory before answering questions about the user

@toolpack-sdk/agents

AgentInput.attachments

All agents now accept image and file attachments alongside the message:

const result = await agent.invokeAgent({
message: 'Review this contract',
attachments: [{
type: 'file',
file: { url: 'https://example.com/contract.pdf', mimeType: 'application/pdf' },
}],
conversationId: 'conv-123',
});

BaseAgent.run() builds a multipart user message when attachments are present. All built-in agents (CodingAgent, ResearchAgent, DataAgent, BrowserAgent, EphemeralAgent) forward input.attachments automatically.


ChatChannel

A non-trigger channel driven directly by your HTTP server. listen() and send() are no-ops — the caller drives the agent via agent.invokeAgent().

import { BaseAgent, ChatChannel } from '@toolpack-sdk/agents';

class MyAgent extends BaseAgent {
name = 'my-agent';
channels = [new ChatChannel({ name: 'chat' })];

async invokeAgent(input) {
return this.run(input.message, undefined, { conversationId: input.conversationId }, input.attachments);
}
}

// In your HTTP handler:
const result = await agent.invokeAgent({
message: req.body.message,
attachments: req.body.attachments,
conversationId: req.body.conversationId,
participant: { id: req.body.userId },
});

normalize() parses the body, validates attachment sizes via validateAttachments(), and sets context.source = 'chat'.


BaseChannel.validateAttachments()

Protected helper for channel implementations. For FilePart, picks FILE_LIMITS.image.maxBytes or FILE_LIMITS.document.maxBytes based on MIME type and only checks when size is supplied. For inline image_data, the limit is always checked via a base64-length estimate. image_url and image_file parts are skipped.


@toolpack-sdk/knowledge

VertexAIEmbedder inline credentials

import { VertexAIEmbedder } from '@toolpack-sdk/knowledge';
import serviceAccount from './service-account.json';

const embedder = new VertexAIEmbedder({
project: 'my-gcp-project',
location: 'us-central1',
credentials: serviceAccount,
});

Pass a parsed service account JSON key via credentials instead of relying on Application Default Credentials. Mirrors the googleAuthOptions.credentials pattern already on VertexAIAdapter.


Install

npm install toolpack-sdk@3.2.0
npm install @toolpack-sdk/knowledge@3.2.0
npm install @toolpack-sdk/agents@3.2.0