Let a model make several tool calls in one short program, and count every call it makes.
What code mode is
Code mode lets a model run one short program that calls several tools and returns a concise result. Each tool call is still a normal, metered tool call. The program only avoids a separate model round trip for each intermediate value. Credits are the prepaid balance every metered call debits. The middleware explains the endpoint the calls pass through.
Why you would want it
- A task needs tool A, then B with A's answer, then C with B's. Without code mode each step costs a model round trip, and each intermediate value lands in the model's context. With it, one program makes the three calls and returns only the part the model needs.
- You want to know what agents spend. Every call, inside a program or not, debits the same credits, and a failed call is refunded.
- A caller you have not allowed should see nothing. Only the callers you list see the code-mode tools.
How it works
Without batching:
model → tool A → model → tool B → model → tool C → model
With a code-mode program:
model → program calls A, B, C → selected result → model
This is an execution sketch, not code to paste into the sandbox. The model writes one JavaScript program and hands it to codemode__run. The program runs in a QuickJS sandbox under fixed caps. Inside it, call reaches any aggregated tool, and each such call is checked and metered as if the model had made it. The program ends with return, and only that value goes back to the model.
Try it
Code mode is off by default. To switch it on, set CONDENSATE_CODE_MODE to opt-in or internal (off, or leaving it unset, keeps it off), and list the callers who may use it in CONDENSATE_CODE_MODE_PRINCIPALS as a comma-separated list. Under either value, only the listed callers see the code-mode tools. Other callers see nothing. The two values behave the same today. Any other value stops the backend from booting, so a typo cannot silently switch a rollout off.
You should see three tools under the codemode upstream in tools/list for a listed caller:
| Tool | What it does |
|---|---|
codemode__search | Finds tools and namespace methods by words describing the task, best match first. limit runs from 1 to 20, default 8. |
codemode__types | Returns TypeScript signatures for the merged tool surface. docs: true adds JSDoc descriptions. |
codemode__run | Runs one JavaScript program in a QuickJS sandbox. Inside it, await call("<upstream>__<tool>", args) calls any aggregated tool. The program ends with return, and only that value comes back. |
What happens when
No caller is listed
With no callers listed, the backend warns at boot and nobody sees the tools.
A program hits a cap
Programs run under fixed caps. Each cap returns a typed error that names it, so nothing is cut off silently. Reference lists the caps.
Two programs run at once
Only one run is allowed at a time per caller.
A program calls a native namespace
Native namespaces, such as agents, canvas and review, are host objects rather than tools. They are bound only when their service URL is configured, and they count toward the namespace-call cap, not the tool-call cap.
A head reads the threads below it
A head is the lead agent, the one that hands tasks to other agents. A head that runs a program in its own thread can read the threads below it without raw HTTP. agents.children and agents.history answer one page at a time and say when more follow. agents.turnStatus and agents.memory.reflect cap their lists and count what they left out. agents.memory.recall answers at most 20 memories. Like every other agents method that takes a thread id, the four thread reads reach only the thread the program runs in, a thread below it, or a thread the program opened. The memory reads take no thread: they read the workspace the aggregator is set to.
| Method | What it answers |
|---|---|
agents.thread(id) | The thread's type, title, parent, stage and whether its agent is replying. |
agents.children(id?, { after, limit }) | One page of the live (not archived) direct children, newest first. With no id it lists the calling thread's children. It never lists a sibling or an ancestor. |
agents.turnStatus(id) | Whether the agent is replying, and which messages wait. |
agents.history(id, { after, limit }) | The log from its first event. It never skips older events in favour of a snapshot. |
agents.memory.recall(query, { limit, tags }) | Memories that match the query, from the aggregator's workspace. |
agents.memory.reflect(query) | A written answer from that workspace's memory, with its sources. |
The memory reads are on only when CONDENSATE_AGENTS_WORKSPACE names a workspace. Without it, they are refused.
You search for a tool
codemode__search ranks every aggregated tool and every method of a namespace in scope, such as agents.spawn or review.pr. A match on more of your words ranks first, so a tool that matches every word comes before one that matches only some. Among matches on the same number of words, a word in the name counts for more than a word in the description. A plural finds its singular, so "threads" finds "thread". When nothing matches, the answer says where to look next.
Credits and metering
When /mcp is on, every tools/call debits prepaid credits. A new caller receives a signup grant. A failed metered call is refunded.
CONDENSATE_FREE_SIGNUP_CREDITSsets the signup grant.CONDENSATE_DEFAULT_TOOL_COSTsets the cost per call, which is 1 by default.CONDENSATE_TOOL_COSTSoverrides the cost for named tools.- Balances live in Postgres when
CONDENSATE_DATABASE_URLis set. Otherwise they live in a JSONL file atCONDENSATE_CREDITS_PATH. With neither, they stay in memory, the backend logs a warning, and balances reset on restart.
Reference
| Cap | Default |
|---|---|
| Wall-clock time per run | 10 seconds. Some surfaces raise this for a longer run. |
| Tool calls per run | 20 |
| Namespace calls per run | 100 |
| Reply timeout per tool call | 180 seconds |
| Returned result size | 64 KiB of JSON |
agents.children page | 20 threads, at most 50 |
agents.history page | 50 events, at most 200 |
agents.turnStatus queue | 50 listed; the rest are counted |
agents.memory.recall hits | 8, at most 20 |
agents.memory.reflect sources and documents | 20 of each listed; the rest are counted |
| Search answer field | What it holds |
|---|---|
kind | tool for an aggregated tool, namespace for a namespace method. |
upstream | The upstream of a tool match. Pass it as upstream to search that upstream only. |
namespace | The namespace of a namespace match, with the method's one-line description. Pass it as upstream to search that namespace only. |
hint | Present only when nothing matched. It names codemode__types and the namespaces in scope. |
A query is at most 200 characters, and only its first 16 distinct words are scored.
| Setting | What it does |
|---|---|
CONDENSATE_CODE_MODE | off (default), opt-in or internal. Any other value stops the boot. |
CONDENSATE_CODE_MODE_PRINCIPALS | The comma-separated callers who see the code-mode tools. |
CONDENSATE_FREE_SIGNUP_CREDITS | The signup grant for a new caller. |
CONDENSATE_DEFAULT_TOOL_COST | The cost per call. Default 1. |
CONDENSATE_TOOL_COSTS | The cost of named tools. |
CONDENSATE_DATABASE_URL | Keeps balances in Postgres. |
CONDENSATE_CREDITS_PATH | Keeps balances in a JSONL file when there is no database. |
CONDENSATE_AGENTS_WORKSPACE | The workspace whose memory agents.memory reads. Unset, those reads are refused. |
Read next
- Connect an upstream, for the endpoint these tools are served from and the
leantool list that pairs with code mode. - Hook up Claude Code and Codex, whose plugin connects the code-mode tools for those two agents.