Skip to main content

Codemode

Codemode lets the model combine tool calls in a JavaScript program, inspect their programmatic results and emit a concise answer. It uses the current Session's callable tools and access scope. It does not provide Node.js, direct filesystem access, network globals or timers; those operations require an eligible host tool.

Enable and choose a mode​

Open Dashboard → Tools → Built-in → codemode to set Profile defaults or apply a Codemode-only change to an idle Session with no pending input. Profile Save does not reselect an existing Session. See Dashboard settings.

For a new or idle resumed Session, tool selection can include Codemode:

anyy --tools '+codemode,+tool_search'
anyy --resume SESSION_ID --tools '+codemode,+tool_search'

The + rules modify the Profile's default selection, not the resumed Session's current active list. They do not write config.yaml. MCP discovery may also auto-activate Codemode unless an explicit rule excludes it.

codemode.mode: on keeps direct tools alongside Codemode. only hides script-callable direct declarations from model requests while keeping those tools callable through Codemode. Mode does not activate Codemode, grant more tools or change the Role. codemode.inline_budget controls how much nested-tool documentation is included in its declaration (default about 3000 estimated tokens); tools omitted from that inline list can still be discovered. See Toolsets.

Write a script​

The public argument shape is an object with a required code string:

{"code":"const result = await tools.bash({command: \"pwd\"}); text(result);"}

When the selected native model declares compat.supportsOpenAIGrammarTools and the provider supports that request path, Anyy can send raw JavaScript grammar input. Other models use the JSON shape above. Both paths save the same canonical arguments.

The script is an async function body, so top-level await and return work. Supply source without Markdown fences. For example, with read available:

const page = await tools.read({path: "README.md", offset: 1, limit: 60});
text(page);

All started calls should be awaited. Calls still pending when the script finishes are cancelled. A fresh VM and globals are created for every call; use store for values that must survive another Codemode call.

An optional first line sets output and execution limits:

// @options: {"max_output_tokens": 2000, "timeout_ms": 30000}
const results = await Promise.all([
tools.bash({command: "git status --short"}),
tools.read({path: "README.md", limit: 40})
]);
for (const result of results) text(result);

These are two independent reads; sequence operations when one depends on another. timeout_ms must be a positive integer at most 2147483647 and includes VM loading/startup. There is no additional script timeout when omitted, but parent cancellation and host-tool limits still apply. max_output_tokens is a nonnegative integer, default 10000, used as an approximate text budget.

Discover and call tools​

Use the exact identifiers returned by discovery rather than guessing MCP names:

APIBehavior
ALL_TOOLSCurrent callable names and descriptions
await searchTools(query, {limit, namespace})Search that snapshot; default limit 8, optional namespace
await describeTool(name)Return its declaration, or undefined; accepts canonical name or script identifier
await describeNamespace(name)Return namespace description/instructions and tool identifiers, or undefined
await tools.name({...})Invoke an existing callable tool through the normal host path

Names are normalized into JavaScript identifiers. Punctuation becomes _; the live declaration is authoritative when names collide. Namespace metadata groups tools for discovery; it does not grant access. Hidden tools and model-only declarations are not script-callable.

searchTools only searches existing callable metadata. It neither fetches another server catalog nor activates declarations for a later model request. The separate tool_search model tool performs that activation.

A nested call usually rejects on failure. A tool with a declared structured return can instead resolve an error object: inspect bash.exit_code, a product result's status, or MCP's isError rather than assuming every resolved Promise succeeded. Structured results are for the script to inspect; emit the useful parts with text instead of dumping an entire remote response.

Output and branch-local values​

GlobalUse
text(value)Add text; objects are JSON encoded
image(dataURLOrBlock)Add a base64 PNG/JPEG/GIF/WebP image and save a temporary image file; remote URLs are rejected
console.log(...)Add diagnostics in the console output block
return valueAdd the returned value to output
exit()End the script successfully
store(key, value) / load(key)Save/read a JSON-serializable value under a string key; undefined deletes it

Successful store changes are committed to the selected conversation branch. Loading a different branch selects its own committed values; reopening the database preserves them. An error, cancellation or timeout discards the current script's staged changes. Already completed tool effects are not undone.

Each stored JSON value may contain at most 262144 characters; keys and serialized values together may contain at most 1048576. Store compact state, not full files or credentials. The VM has a 256 MiB memory limit. Hard output limits are 16777216 JavaScript characters or 100000 output/console calls; exceeding either fails the script.

A failed script can return partial output with its error. The text budget shortens output using head/tail excerpts and names the temporary full-output path; use read with offset/limit while that file exists. A temporary output path is not a durable attachment promise. For stored logical result refs and context budgets, see tool results.

Classifier and image model APIs​

Anyy also exposes the following asynchronous model APIs inside Codemode. The tool description points to the bundled readable reference at <ProfileHome>/system/docs/pi-v1.2.0/codemode.md; read it for the complete schemas before using them.

APIArguments
models.getModelsOfType(type, provider?)List configured models
models.getAvailableOfType(type, provider?)Filter by enabled provider and locally resolvable credentials; this is not a remote health probe
models.getModelOfType(type, provider, id)Look up one model using three separate strings; unknown model returns undefined
models.classify(model, context)Use a configured classifier model
models.generateImages(model, context)Use a configured image model

Types are chat, image and classifier. Listing chat models does not expose a chat-generation function. Execution requires a model object containing the catalog's provider and id, not a combined provider/id string or a custom endpoint.

For classification, context.state is an object; optional images contain base64 image blocks. questions is a nonempty object. Each question has instructions, type and criteria: choice maps labels to meanings, score lists levels from lowest to highest, and bool supplies string meanings for true and false.

const available = await models.getAvailableOfType("classifier");
if (!available.length) { text("No configured classifier is available"); exit(); }
const result = await models.classify(available[0], {
state: {subject: "Move tomorrow's meeting to Friday"},
questions: {
scheduling: {
type: "bool", instructions: "Does this request change a meeting?",
criteria: {true: "A meeting change is requested", false: "No meeting change"}
}
}
});
if (result.stopReason !== "stop") throw new Error(result.errorMessage || result.stopReason);
text(result);

For generation, pass {input: [{type: "text", text: "..."}]}; base64 image blocks can supply references. For example:

const available = await models.getAvailableOfType("image");
if (!available.length) { text("No configured image model is available"); exit(); }
const result = await models.generateImages(available[0], {
input: [{type: "text", text: "A simple blue bird icon on white"}]
});
if (result.stopReason !== "stop") throw new Error(result.errorMessage || result.stopReason);
for (const part of result.output) {
if (part.type === "image") image(part);
else if (part.type === "text") text(part.text);
}

At most four classifier/image operations run concurrently within one script. Provider failures return results with stopReason: "error" or "aborted" and an errorMessage; invalid arguments can reject before a provider call starts. Model usage is accumulated into the Codemode result. Availability, billing and accepted image inputs still depend on the configured provider.