Skip to main content

v2.7.0

Released: July 27, 2026

Highlights

  • Rules system (toolpack-sdk) — inject always-on behavioral constraints from Markdown files into the system prompt, scoped per mode with an optional __global__/ folder that applies across all modes sharing the same rules directory
  • Anthropic on Vertex AI provider (toolpack-sdk) — run Claude Sonnet 4.5 and Haiku 4.5 through Google Cloud Vertex AI with no API key required; uses Application Default Credentials
  • BaseAgent: concurrent conversation safety (@toolpack-sdk/agents) — channel context (conversation ID, triggering channel) is now stored in AsyncLocalStorage so two conversations arriving at the same agent simultaneously can no longer clobber each other's values
  • BaseAgent: per-request mode (@toolpack-sdk/agents) — mode is now snapshotted per generate() call instead of calling setMode() on every run, eliminating a race condition when multiple agents share one Toolpack instance
  • Scheduler: run history (@toolpack-sdk/agents) — completed and failed job executions are recorded in a job_runs table; retrieve them with getHistory(jobId)
  • Parallel agent spawning (@toolpack-sdk/agents) — new spawn_agents_parallel tool lets the LLM instantiate multiple helper agents simultaneously and wait for all results

Breaking changes

None.


toolpack-sdk

Rules system

Rules are always-on behavioral constraints loaded from Markdown files and appended to the system prompt on every request. Unlike Skills (which are conditionally matched), Rules are always injected.

Set rulesDir on any mode to enable:

const analystMode = createMode({
name: 'equity-analyst',
systemPrompt: 'You are an Indian equity market analyst.',
rulesDir: '.warren/rules', // auto-discovers __global__/ and equity-analyst/
});

Directory layout:

.warren/rules/
__global__/
compliance.md ← injected for all modes pointing to this directory
equity-analyst/
india-only.md ← injected for this mode only

Rules are injected last in the system prompt chain (base → override → mode → rules), placing them closest to the conversation for maximum recency weight.

  • __global__/ applies to every mode that shares the same rulesDir
  • Files are scanned recursively; only .md files are loaded
  • Two-level cache (fileCache per path, modeCache per modeName:dir) means each file is read from disk at most once per process
  • Duplicate files (same resolved absolute path) are deduplicated — first-seen wins
  • RuleLoader is exported from toolpack-sdk for custom use

Default path: .toolpack/rules (used when rulesDir is not set on the mode).

See the Rules guide for the full reference.

Anthropic on Vertex AI provider

Run Claude models through Google Cloud Vertex AI without an Anthropic API key. Authentication uses Application Default Credentials (gcloud auth application-default login).

import { Toolpack } from 'toolpack-sdk';
import { AnthropicVertexAdapter } from 'toolpack-sdk/providers';

const sdk = await Toolpack.init({
provider: new AnthropicVertexAdapter({
projectId: 'my-gcp-project',
region: 'us-east5', // optional, defaults to us-east5
}),
tools: true,
});

Supported models: claude-sonnet-4-5@20250929, claude-haiku-4-5@20251001, claude-3-5-sonnet-v2@20241022, claude-3-5-haiku@20241022.

Environment variable fallbacks: ANTHROPIC_VERTEX_PROJECT_ID / GOOGLE_CLOUD_PROJECT for project, ANTHROPIC_VERTEX_REGION for region.

VertexAI: new models and thinking budget

Two new Gemini models are registered: gemini-3.5-flash and gemini-3.1-pro-preview (1M token context window, 65 536 max output tokens).

VertexAIAdapter now accepts a thinkingBudget option for Gemini 2.5+ models. Set to 0 to disable thinking entirely:

new VertexAIAdapter({ thinkingBudget: 8192 });

Internal rawContentCache stores Vertex AI Content objects keyed by tool call ID, preserving thought_signature fields required by Gemini thinking models across multi-turn tool-calling loops.

Skills: mode-gated auto-injection

Skill auto-injection is now opt-in per mode. The skill interceptor only runs when the active mode has skillInterceptor: true set. Modes without this flag are unaffected — no BM25 overhead on every request.

const myMode = createMode({
name: 'research',
skillInterceptor: true, // opt in to automatic skill injection
});

@toolpack-sdk/agents

BaseAgent: concurrent conversation safety

Channel context fields (conversationId, triggeringChannel, isTriggerChannel) are now stored in AsyncLocalStorage instead of instance-level fields. Each inbound message gets its own isolated async context, so two conversations processed concurrently by the same agent instance can no longer clobber each other's values.

The legacy instance fields (_conversationId, _triggeringChannel, _isTriggerChannel) remain for backward compatibility but are now only used as a final fallback when no async-local context is present.

BaseAgent: per-request mode (no more setMode() on every run)

run() previously called this.toolpack.setMode() on every invocation, mutating shared AIClient.activeMode. This caused a race condition when two agents shared one Toolpack instance — a setMode() from one run could override the mode of a concurrent run.

Mode is now passed as a per-request parameter to generate() and stream(), where it is snapshotted for the entire request. setMode() is only called once in start() for backward compatibility.

BaseAgent: parallel agent spawning

When spawn is configured, the LLM now has access to a spawn_agents_parallel tool in addition to the existing spawn_agent tool. It accepts an array of { template, task } entries and runs all of them concurrently with Promise.all:

// LLM call
{
"tool": "spawn_agents_parallel",
"input": {
"tasks": [
{ "template": "researcher", "task": "Find recent news on HDFC Bank" },
{ "template": "researcher", "task": "Find recent news on Infosys" }
]
}
}

BaseAgent: streaming mode

run() now checks mode.streaming and, when true, switches to toolpack.stream() instead of generate(). No config change needed — set streaming: true on the mode:

const streamingMode = createMode({
name: 'live-agent',
streaming: true,
});

AgentMind: concurrent belief deduplication

AgentMind now maintains a shared _inFlightBeliefs set across all DraftBuffer instances for the same agent. When two concurrent runs produce the same belief content, only the first one is written — the second is detected as an in-flight duplicate and skipped, preventing duplicate entries in the belief store.

Scheduler: job run history

SchedulerStore now maintains a job_runs table (SQLite). Every completed or failed execution is recorded automatically.

New type:

interface JobRun {
id: number;
jobId: string;
outcome: 'completed' | 'failed';
ranAt: number; // Unix timestamp ms
durationMs?: number;
error?: string;
}

New methods on SchedulerStore:

MethodDescription
markCompleted(id, ranAt?)Record a successful execution
markFailed(id, error, ranAt?)Record a failed execution with the error message
getHistory(id, limit?)Return execution records, newest first (default limit: 20)
const runs = store.getHistory('job-abc', 10);
runs.forEach(r => console.log(r.outcome, r.durationMs));