Skip to main content

v2.3.0

Released: June 13, 2026

Highlights

  • Mode race fix (toolpack-sdk) — concurrent agents sharing a Toolpack instance no longer corrupt each other's tool filtering, system prompt, or response format
  • Per-request mode override (toolpack-sdk) — pin a mode for a single generate()/stream() call without touching instance state
  • reSync data-loss fix (@toolpack-sdk/knowledge) — reSync: false on either Knowledge.create() or PersistentKnowledgeProvider is now sufficient; previously both had to be set or runtime-added chunks were silently wiped on every restart
  • Full ToolpackInitConfig on BaseAgent (@toolpack-sdk/agents) — agents can now configure interceptors, knowledge, customModes, and all other init options at construction time

Breaking changes

None.


toolpack-sdk

Bug fix: mode race condition in shared Toolpack instances

In multi-agent setups where several agents share one Toolpack instance (via AgentRegistry), a concurrent setMode() call from a delegated sub-agent could change the active mode between tool-loop rounds of the parent's in-flight request — causing the wrong tools, system prompt, and response format to be applied to later rounds.

AIClient.generate() and AIClient.stream() now snapshot the effective mode at the very start of each request and pass it explicitly through every internal call. A setMode() from any source after the snapshot has no effect on that request.

New: per-request mode on CompletionRequest

// Pin a mode for a single call — instance activeMode is not changed
await toolpack.generate({ messages, mode: 'publisher' });

// Pass a ModeConfig directly
await toolpack.generate({ messages, mode: myModeConfig });

// Explicitly run without any mode
await toolpack.generate({ messages, mode: null });

mode accepts a ModeConfig, a string name (resolved from the registry), null (no mode), or can be omitted to snapshot the current active mode.


@toolpack-sdk/knowledge

Bug fix: reSync: false had to be set in two places

Setting reSync: false only on Knowledge.create() options (the intuitive place) still triggered a full sync on restart, silently clearing all runtime-added chunks. The same bug existed in the reverse direction — setting it only on PersistentKnowledgeProvider also failed.

Both cases are now fixed. A single reSync: false in either place is sufficient:

// Knowledge-level only — now works correctly
await Knowledge.create({ provider, sources, embedder, description, reSync: false });

// Provider-level only — also now works correctly
const provider = new PersistentKnowledgeProvider({ namespace: 'my-kb', reSync: false });
await Knowledge.create({ provider, sources, embedder, description });

First-run behavior is unchanged: when the store is empty, the initial sync from sources always runs regardless of the flag.


@toolpack-sdk/agents

Full ToolpackInitConfig on BaseAgent

BaseAgentOptions now accepts the full ToolpackInitConfig instead of the narrow { apiKey, provider?, model? } shape:

class MyAgent extends BaseAgent {
constructor() {
super({
apiKey: process.env.ANTHROPIC_KEY!,
interceptors: [createSkillInterceptor({ dir: './skills', minScore: 1.0 })],
knowledge: [myKnowledgeBase],
customModes: [publisherMode],
});
}
}

Previously interceptors, knowledge, and customModes could only be set on agents that received a pre-configured shared toolpack instance.

Bug fix: mode not forwarded per-request in BaseAgent.run()

BaseAgent.run() now passes mode: this.mode on every generate() call so the mode is snapshotted at request start and cannot be overridden by a concurrently executing sub-agent.


Install

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