Lazy Code Mode tools load a type stub only when the program imports that tool. The system prompt stays small when you register many tools.
Mark the rarely used tools lazy: true. The prompt then lists only their names. When the model needs one, it calls discover_tools to get the signature, then uses the tool in execute_typescript.
You need the route from the Code Mode quick setup first.
import { toolDefinition } from "@tanstack/ai";
import { z } from "zod";
// Eager: the full type stub is in the system prompt
const fetchWeather = toolDefinition({
name: "fetchWeather",
description: "Get current weather for a city",
inputSchema: z.object({ location: z.string() }),
outputSchema: z.object({ temperature: z.number(), condition: z.string() }),
}).server(async ({ location }) => ({
temperature: location.length + 10,
condition: "sunny",
}));
// Lazy: only the name is in the system prompt, until the model discovers it
const fetchArchive = toolDefinition({
name: "fetchArchive",
description: "Retrieve historical weather archive data for a date range",
inputSchema: z.object({
location: z.string(),
from: z.string(),
to: z.string(),
}),
outputSchema: z.array(z.object({ date: z.string(), temperature: z.number() })),
lazy: true,
}).server(async ({ from, to }) => [
{ date: from, temperature: 14 },
{ date: to, temperature: 16 },
]);import {
chat,
chatParamsFromRequest,
maxIterations,
toServerSentEventsResponse,
} from "@tanstack/ai";
import { createCodeMode } from "@tanstack/ai-code-mode";
import { createNodeIsolateDriver } from "@tanstack/ai-isolate-node";
import { openaiText } from "@tanstack/ai-openai";
const { tools, systemPrompt } = createCodeMode({
driver: createNodeIsolateDriver(),
tools: [fetchWeather, fetchArchive],
});
// tools is [execute_typescript, discover_tools]
export async function POST(request: Request) {
const { messages, threadId, runId } = await chatParamsFromRequest(request);
const stream = chat({
adapter: openaiText("gpt-6.1-sol"),
systemPrompts: ["You are a helpful weather assistant.", systemPrompt],
tools,
messages,
threadId,
runId,
agentLoopStrategy: maxIterations(10),
});
return toServerSentEventsResponse(stream);
}The system prompt lists the lazy tools in a "Discoverable APIs" catalog, with names only:
### Discoverable APIs
- external_fetchArchive
- external_runReport
- external_exportDataThen the model:
Lazy hides only the documentation. Every tool is always a function in the sandbox. The model can call external_fetchArchive with no discovery, but then it writes the call without the type signature.
To give the model a hint about each lazy tool before it discovers one, set lazyToolsConfig.includeDescription:
const { tools, systemPrompt } = createCodeMode({
driver: createNodeIsolateDriver(),
tools: [fetchWeather, fetchArchive],
lazyToolsConfig: {
includeDescription: "first-sentence",
},
});| Value | What the catalog shows |
|---|---|
| 'none' (default) | Names only. This is the smallest prompt. |
| 'first-sentence' | The name and the first sentence of the description. |
| 'full' | The name and the full description. |
includeDescription changes only the catalog. A discover_tools call always returns the full type stub.
chat() also takes lazyToolsConfig, for lazy tools that you give to chat() directly. The includeDescription values work the same way:
const stream = chat({
adapter: openaiText("gpt-6.1-sol"),
messages,
threadId: "thread-1",
tools: [fetchWeather, fetchArchive],
lazyToolsConfig: { includeDescription: "first-sentence" },
});For the full setup without Code Mode, see Lazy Tool Discovery.
| Field | Type | Description |
|---|---|---|
| tool | ServerTool | The execute_typescript tool. |
| discoveryTool | ServerTool | null | The discover_tools tool, or null when no tool is lazy. |
| tools | Array<ServerTool> | [tool], or [tool, discoveryTool]. Give this array to chat({ tools }). |
| systemPrompt | string | The matching system prompt. |
If no tool is lazy, tools holds only execute_typescript. So you can always pass tools, with or without lazy tools.
discover_tools is a separate tool call. It is not a function inside execute_typescript.