v3.2.0
Released: September 6, 2026
Highlights
- File attachments (
toolpack-sdk) — newFileParttype andFILE_LIMITSconstant; 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) —AIClientgenerates 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.attachmentsandBaseChannel.validateAttachments()for all channels VertexAIEmbedderinline credentials (@toolpack-sdk/knowledge) — pass a service account JSON key directly instead of relying on Application Default Credentials- Breaking:
createSkillInterceptorremoved — usecreateSkillToolsinstead
Breaking changes
| Change | Package | Migration |
|---|---|---|
createSkillInterceptor removed | toolpack-sdk | Remove from interceptors config; use createSkillTools with ModeConfig.customTools |
SkillInterceptorOptions type removed | toolpack-sdk | No replacement needed |
skillInterceptor?: boolean removed from ModeConfig | toolpack-sdk | Remove the field from custom mode definitions |
RunContext.tools removed from AgentMind | @toolpack-sdk/agents | Only 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
| Provider | URL | Inline base64 (data: URI) |
|---|---|---|
| Anthropic | images and documents | auto-routed to image or document block |
| Anthropic Vertex | images and documents | auto-routed to image or document block |
| Gemini | fileData | inlineData |
| VertexAI | fileData | inlineData |
| OpenAI | images and documents | Images 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 somethingknowledge_add— factual domain knowledge (documents, research, organizational data) only; not for personal user factsmind_believe— preferred for personal user facts and preferencesmind_reflect— for lessons learned and standing rulesmind_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