Skip to content

Code Mode

Code Mode is the default Caplets surface. Instead of showing an agent every downstream tool up front, Caplets gives the agent typed caplets.<id> handles inside one TypeScript run.

Agents should use Code Mode to discover, call, filter, join, and summarize capability data without filling the visible tool list.

Ask the agent for the outcome you need and name the Caplet when it matters:

Use Caplets Code Mode to query OSV for npm react 18.2.0. Return package,
version, vulnerability count, and advisory IDs as compact JSON.

The visible MCP tool should be caplets__code_mode. Inside that tool, the agent runs TypeScript against generated handles such as caplets.osv.

A configured OSV Caplet appears as a handle such as:

const h = caplets.osv;

The handle supports discovery and execution:

const h = caplets.osv;
const tools = await h.searchTools("package version");
const details = await h.describeTool("query_package_version");
const result = await h.callTool("query_package_version", {
ecosystem: "npm",
name: "react",
version: "18.2.0",
});
return { tools: tools.items.map((tool) => tool.name), result };

In MCP clients the visible tool is caplets__code_mode; the TypeScript inside that tool uses handles such as caplets.osv.searchTools(...) and caplets.osv.callTool(...).

For most tasks, keep bulky raw payloads inside the Code Mode script and return compact JSON with the evidence the user needs.

Code Mode accepts an optional sessionId. Omit it to create a fresh session. Successful fresh runs and reused runs include meta.sessionId; pass that value to a nearby follow-up call when you want to reuse helper functions, variables, or cached discovery results in the same QuickJS heap.

const first = await caplets__code_mode({
code: `
var pickNames = (items) => items.map((item) => item.name);
return pickNames((await caplets.osv.searchTools("package")).items);
`,
});
const sessionId = first.meta?.sessionId;
const second = await caplets__code_mode({
sessionId,
code: `
const tools = await caplets.osv.searchTools("version");
return { names: pickNames(tools.items) };
`,
});

Unknown or expired session IDs fail before submitted code runs, using structured session errors such as SESSION_NOT_FOUND. Heap state is live runtime state only; it is not durable across process restarts or TTL eviction. Ordinary CLI calls such as caplets code-mode 'return 1' are one-shot and do not share heap with later CLI invocations.

When a Code Mode session is created, successful metadata can include a recoveryRef. Agents that already possess that reference can call caplets.debug.readRecovery(...) to read redacted, bounded summaries of prior session runs. Recovery history helps reconstruct safe setup code manually; it does not restore heap values, closures, timers, promises, or host handles. A stale or unknown sessionId alone does not grant access to recovery history, and there is no recent-session lookup.

Code Mode also installs standard JavaScript platform globals at runtime so scripts can shape data without reaching for direct I/O:

  • Pure utilities: atob, btoa, a documented Buffer subset, and structuredClone.
  • Web data objects: URL, URLSearchParams, TextEncoder, TextDecoder, Headers, Blob, File, FormData, ReadableStream, WritableStream, TransformStream, AbortController, AbortSignal, Request, and Response.
  • Scheduling: queueMicrotask, setTimeout, clearTimeout, setInterval, and clearInterval.
  • Randomness: crypto.randomUUID() and crypto.getRandomValues(...).

These are runtime globals for JavaScript muscle memory. They are intentionally not enumerated in the generated Code Mode declaration payload or tool prompt, which stays focused on Caplet handles, debug helpers, and console to avoid token bloat.

Direct I/O is intentionally unavailable. fetch is blocked; use Caplet handles for network, tool, resource, prompt, or command I/O. Node and module APIs such as process, require, imports, filesystem access, child processes, and direct network access are not available inside Code Mode scripts.

Prefer compact decision-ready data:

{
"package": "react",
"version": "18.2.0",
"vulnerabilityCount": 0,
"advisoryIds": []
}

If a call fails, return the Caplets result envelope so the next repair step has the exact error:

{
"ok": false,
"error": {
"code": "DOWNSTREAM_TOOL_NOT_FOUND",
"message": "Tool query_package_version was not found."
}
}
  • Do search or list first when you do not know the exact downstream tool name.
  • Do call describeTool(...) before constructing non-trivial arguments.
  • Do keep joins, filters, and bulky raw payloads inside the Code Mode script.
  • Avoid returning full tool lists, full schemas, or raw API responses unless the user asks for them.
  • Avoid inventing Caplet IDs, tool names, resource URIs, prompt names, or argument shapes.
  • Avoid using Code Mode as a security boundary; it is a context-management surface.

Run inline TypeScript:

Terminal window
caplets code-mode 'return Object.keys(caplets)'

Print the generated declarations:

Terminal window
caplets code-mode types

If a run behaves unexpectedly, check config and runtime state:

Terminal window
caplets doctor

Use progressive or direct exposure only when a client cannot run Code Mode or a workflow needs a small visible tool surface. Code Mode is a context-management surface, not a security boundary.