12 code_interpreter: Bounded Local Computation
Part III · Skills and the compositional research toolchain
Implementation baseline: pinned local Pyodide worker · reviewed reference snapshot 45a903c
A calculation can be reproducible without being authoritative. The Northstar mean of 8.25 hours is deterministic given the workbook values 9 and 7.5; the interpreter does not prove that those measurements describe a real device or that Python-in-WebAssembly is an operating-system sandbox.
12.1 One portable computation contract
code_interpreter is a server-owned tool exposed to both coordinator adapters through the same schema. It is not an OpenAI- or Anthropic-hosted code tool. The reviewed configuration controls call count, deadline, code size, and three independent output ceilings:
- name: code_interpreter
maxCalls: 10
timeoutMs: 30000
maxCodeCharacters: 20000
maxOutputCharacters: 64000Its input contains a user-visible summary, Python code, and optionally up to four unique invocation-local sourceIds. The caller cannot supply packages, network settings, a working directory, host paths, credentials, a persistent volume, or provider-specific execution options.
Chapter 8 owns whether the proposed call is currently authorized. This chapter owns what happens after admission: scheduling, worker creation, mounting, execution, cancellation, output fitting, and progress privacy.
12.2 Fresh worker construction
Every admitted call constructs a new Pyodide WebAssembly worker and a new Python state. Completion, timeout, cancellation, malformed worker output, or execution error terminates that worker. No Python variables, imported modules, mounted files, or mutations carry into a later call.
Fresh construction narrows several failure modes:
- one call cannot intentionally prepare hidden Python state for the next;
- a mutation of mounted input cannot alter the invocation source registry;
- cleanup does not depend on generated code politely deleting files; and
- timeout can terminate the worker rather than waiting for cooperative Python.
Fresh does not mean costless. Runtime startup and WebAssembly memory are paid per call, which is one reason the server imposes a shared scheduler and small call budget.
12.3 Invocation-local mounts, not arbitrary files
The coordinator can pass only exact source IDs from two trusted invocation inventories:
- request attachments admitted by Chapter 4; and
- successful
read_sourcerepresentations admitted by Chapter 11.
Unknown, invented, expired, duplicate, or cross-invocation IDs reject before Python starts. For each accepted ID, the server copies canonical text into the worker under a fixed /inputs/<sourceId>.txt path. Python receives an input_files mapping from ID to canonical-text path.
For admitted request attachments, input_assets can additionally expose the fixed worker-local path to the original admitted bytes and the canonical text path. The model still chooses an ID, not a host path. The copied files and worker filesystem disappear when the call ends.
This read→ID→mount sequence avoids embedding hundreds of thousands of source characters inside generated Python. It also preserves provenance: code declares which invocation-owned representations it used. A mount does not certify those representations as true.
12.4 The Python execution boundary
The worker is intended for bounded calculations, deterministic transforms, parsing, sorting, filtering, counting, aggregation, deduplication, ranking, and checks over explicit input. The tool-owned coordinator guidance requires execution when the requested result creates or transforms structured and machine-readable data rather than inviting the model to simulate arithmetic in prose.
The declared profile provides no:
- network access;
- third-party package installation;
- arbitrary host path or attachment access;
- browser, shell, or operating-system process access;
- persistent Python state; or
- generated-file upload and durable artifact handoff.
The ordinary JavaScript bridge and package installer imports are blocked, and Python receives a null-prototype JavaScript-global object. Schema, code, output, quota, and ownership checks execute outside Python.
These are meaningful controls around a local educational runtime. They are not a claim of complete Pyodide escape resistance or hostile multi-tenant isolation.
12.5 Scheduling and concurrency
Calls enter one process-wide queue shared across HTTP invocations. Only the configured active capacity may hold live WebAssembly workers; the current reviewed profile serializes calls to limit memory pressure.
Scheduling has two consequences:
- a single invocation cannot create unbounded parallel workers; and
- one invocation can delay another, so queue time must remain inside the call/run deadline and operational policy.
Every admitted call spends its invocation quota even if it later waits, fails, or times out. A queued call cancelled before its turn cannot enter the worker later. Fairness, tenant weighting, and distributed scheduling are not implemented by this local queue.
The queue protects process pressure structurally; it does not enforce a WebAssembly heap limit or guarantee that one worker cannot degrade the process before termination.
12.6 Deadlines and cancellation
A whole-tool deadline bounds validation, queueing as implemented by the runtime, worker startup, and execution. Non-cooperative Python is stopped by terminating the worker. Cancellation propagates through the scheduler; an already-cancelled queued task never becomes runnable.
The runtime distinguishes:
- invalid input before execution;
- unavailable source IDs;
- Python exceptions;
- deadline expiry;
- caller cancellation; and
- malformed or oversized worker results.
A Python exception is returned as a bounded typed tool result so the coordinator can correct code when appropriate. Pi shows only the safe statement that Python executed and returned an exception; details remain in the bounded model-visible result. Timeout and cancellation remain runtime outcomes rather than fabricated Python output.
Termination is a local control. It does not prove exact CPU accounting, instant memory reclamation, or absence of process impact before the worker stopped.
12.7 Output fitting
Successful output contains bounded stdout, stderr, optional final-expression representation, elapsed time, and exact omitted-character counts. Each of the three text channels has its own configured ceiling, followed by the aggregate tool-result byte bound.
Fitting is explicit rather than silent. If Python prints a million-character table, the caller sees that characters were omitted; it cannot claim the displayed suffix or prefix is complete. Progress never carries these channels.
Character ceilings and UTF-8 serialized-byte ceilings are different. Unicode output can pass a character check and still consume more bytes. Both boundaries remain necessary.
The tool does not infer correctness from exit success. A program can run without exception and compute the wrong formula. For material calculations, the code, input identity, units, result, and independent check belong in the evidence record.
12.8 Progress without code disclosure
The tool module owns its progress presenter. Negotiated Pi cards can show requested, queued/started, execution phase, elapsed time, bounded output sizes, omission counts, and terminal category.
Cards do not include:
- Python source;
- stdout, stderr, or expression result;
- mounted text or source IDs;
- filenames or host paths; or
- exception details.
Progress is display-only and excluded from model context. It helps a user distinguish waiting from completion without creating a second data-exfiltration channel.
12.9 Numeric normalization and missingness
Computation pipelines need a rule for values before arithmetic. A finite numeric string such as "9", "7.5", or "1e-1" can be normalized deliberately when the surrounding schema permits numeric text. Empty strings, booleans, malformed numbers, infinities, and NaN reject.
Missing data remains missing. null, an absent cell, or a parser-level missing marker must not become zero merely because Python’s aggregation is easier over numbers. A mean over [9, 7.5, null] has at least three possible policies:
- reject because the expected measurement is absent;
- compute over observed values and disclose
n = 2; or - return a missing aggregate.
The task contract must choose. Silently replacing null with 0 yields 5.5 and invents a measurement. The Northstar calculation has exactly two finite measured runtimes, so its accepted denominator is two.
This chapter’s rule aligns with the presentation boundary: chart null renders as a gap or N/A, not zero. Data meaning must survive both computation and display.
12.10 Worked Northstar calculation
The synthetic workbook supplies measured runtime values for Prototype A and Prototype B:
measured_runtime_hours = [9.0, 7.5]
assert all(isinstance(value, (int, float)) for value in measured_runtime_hours)
mean_runtime_hours = sum(measured_runtime_hours) / len(measured_runtime_hours)
mean_runtime_hoursThe deterministic result is 8.25. Its evidence label is calculation from workbook measurements, not product specification, image observation, or public guidance.
The complete research path is:
XLSX attachment
→ shared bounded ingestion
→ invocation-local canonical representation
→ source ID selected for code_interpreter
→ isolated worker copy
→ Python calculation
→ bounded result: 8.25 hours
The published recording shows the local interpreter card and the final evidence-labelled result. It does not expose generated code/output in progress, and it does not prove that every future model will write the same program. Deterministic tests separately execute known Python against synthetic inputs.
A robust task-specific check also records expected count, units, valid ranges, and missing-value policy. The interpreter supplies a computation mechanism; Chapter 13 decides whether the research claim has sufficient premises.
12.11 Current sandbox limitations
The current worker is runtime/process isolation, not operating-system isolation. Important limitations include:
- no independently enforced per-worker heap ceiling;
- termination depends on the host runtime and event-loop scheduling;
- CPU and memory pressure can affect the server before cancellation;
- Pyodide and the JavaScript host share one application process boundary;
- blocked imports and null-prototype globals are defense in depth, not a formal non-escape proof;
- the loopback server has no production multi-tenant entitlement layer; and
- no durable generated-artifact pipeline exists for this tool.
Default tests deny ordinary fetch at the Bun layer and exercise local Pyodide. That is test control, not an OS firewall.
Chapter 17 owns production isolation requirements: separate processes or containers, OS resource controls, egress policy, filesystem confinement, tenant scheduling, image/dependency patching, exploit testing, and incident response. Deferring those requirements does not make them optional; it prevents this chapter from pretending the current worker already satisfies them.
12.12 Evidence and testing
Credential-free tests cover fresh state, exact output truncation and omission counts, blocked JavaScript-bridge import, source-ID mounting, unknown-ID rejection, an actual read_source→mount→Python sequence, queue cancellation, non-cooperative timeout and worker termination, tool-owned instructions, registration, and progress privacy.
These tests establish the implemented local boundary. They do not establish adversarial sandbox strength, arbitrary package compatibility, semantic correctness of model-written programs, identical results across Pyodide revisions, or provider-hosted code-tool equivalence.
12.13 Failure modes
Model arithmetic presented as execution. Require the tool for structured computation and retain its result identity.
Path smuggling. Let generated code name /Users/... or a URL. Mount only server-selected invocation sources at fixed paths.
State leakage. Reuse one Python environment across callers. Construct and destroy a worker per admitted call.
Cancellation resurrection. A queued cancelled task starts later. Remove or reject it before worker construction.
Output-as-progress. Code or results leak through UI cards. Keep progress metadata-only.
Missing-as-zero. Null data silently changes an aggregate. Define and test missingness policy before arithmetic.
12.14 Pattern summary
Problem: Generated computation needs useful inputs and bounded execution without granting arbitrary host access.
Pattern: Create a fresh scheduled worker, mount only invocation-owned snapshots by opaque ID, terminate on deadline/cancellation, and fit every output channel explicitly.
Result: Both coordinator adapters can use one local computation tool whose inputs, state, and results are reviewable.
Cost: Startup overhead, process-wide contention, limited libraries, and incomplete hostile-code isolation remain.
12.15 Exercises
- Compute a mean from
[9, null, 7.5]under three explicit missing-value policies. Label each result. - Design a two-worker scheduler with cancellation and a memory-pressure gate. State which properties still require OS enforcement.
- Add a task-specific check that rejects mixed units before calculating a Northstar mean.
- Explain why identical Python source and mounted bytes do not by themselves establish identical results across runtime revisions.
12.16 Chapter contract
- Scope: fresh-worker construction, source mounts, Python boundary, scheduling, deadlines, cancellation, output fitting, progress, numeric normalization, and missingness.
- Canonical claims: local deterministic execution proves a result under stated inputs and runtime bounds, not input truth or production sandbox strength.
- Migration inputs: current Pyodide implementation, shared source registry, Northstar runtime calculation, and deterministic worker tests.
- Evidence gates: real local worker tests under network denial plus task-specific input/result checks.
- Demonstration slots: Northstar shows the 8.25-hour calculation path, not universal program correctness.
- Source-claim ledger: computation evidence records input representation IDs/digests where retained, code/runtime revision, units, missingness policy, and output limits.
- Exclusions: generic tool authorization belongs to Chapter 8; research support belongs to Chapter 13; production isolation belongs to Chapter 17.