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 for Code Mode
Section titled “Ask for Code Mode”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.
What agents see
Section titled “What agents see”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.
Reuse a live session
Section titled “Reuse a live session”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.
Recovery history
Section titled “Recovery history”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.
Platform globals
Section titled “Platform globals”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 documentedBuffersubset, andstructuredClone. - Web data objects:
URL,URLSearchParams,TextEncoder,TextDecoder,Headers,Blob,File,FormData,ReadableStream,WritableStream,TransformStream,AbortController,AbortSignal,Request, andResponse. - Scheduling:
queueMicrotask,setTimeout,clearTimeout,setInterval, andclearInterval. - Randomness:
crypto.randomUUID()andcrypto.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.
Return shape
Section titled “Return shape”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 and avoid
Section titled “Do and avoid”- 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.
Use it from the CLI
Section titled “Use it from the CLI”Run inline TypeScript:
caplets code-mode 'return Object.keys(caplets)'Print the generated declarations:
caplets code-mode typesIf a run behaves unexpectedly, check config and runtime state:
caplets doctorWhen not to use Code Mode
Section titled “When not to use Code Mode”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.