Skip to content

Hosted Code Execution

By the end of this guide you will be able to:

  • Enable a provider’s hosted code-execution tool with one unified tool entry.
  • Read code-produced files (charts, CSVs, data) uniformly from response.files.
  • Understand how each provider returns those files, so you can fetch the bytes.

Hosted code execution runs a sandboxed Python environment on the provider’s side and folds the result back into a single response — no client-side tool loop, no executor to write. Use it for computation, data wrangling, and generating artifacts (plots, CSVs) from a prompt.

Enable it — one interface, every provider

Section titled “Enable it — one interface, every provider”

Pass the code_interpreter builtin. The SDK maps it to each provider’s own hosted tool (OpenAI code_interpreter, Anthropic code_execution, Google codeExecution; xAI inherits the OpenAI Responses shape):

import { complete } from '@combycode/llm-sdk';
const { text } = await complete({
model: 'openai/gpt-5.4-nano', // or anthropic/… , google/… , xai/…
apiKey: process.env.OPENAI_API_KEY,
prompt: 'Compute 12345 * 6789 using code and tell me the result.',
tools: [{ type: 'code_interpreter' }],
});
// text → "…83,810,205…"

That’s the whole request surface — the model writes and runs code server-side and returns the answer in one turn.

When executed code produces files (a matplotlib chart, an exported CSV), they surface uniformly on response.files as FileOutput[], independent of model-generated media:

interface FileOutput {
id?: string; // provider file id — fetch bytes via the files API
name?: string; // filename, when provided
mimeType?: string; // when known
data?: string; // inline base64, when returned inline
url?: string; // fetchable URL, when returned as one
source?: string; // e.g. 'code_execution'
ref?: Record<string, unknown>; // provider meta (e.g. OpenAI containerId) used by retrieveFile
}
const { response } = await complete({
model: 'anthropic/claude-haiku-4.5',
apiKey: process.env.ANTHROPIC_API_KEY,
prompt: 'With matplotlib, plot y = x**2 for x in 1..5, save it to a PNG file, and return the file.',
tools: [{ type: 'code_interpreter' }],
maxTokens: 6000,
});
for (const f of response.files ?? []) {
// one shape across every provider — see retrieval below
console.log(f.source, f.id ?? f.url ?? `${(f.data ?? '').length} inline bytes`);
}

The same code runs against any provider — you never touch a provider-specific block shape.

response.files is unified, but the bytes live in different places per provider. You don’t fetch per-provider, though — the helpers below resolve every shape:

ProviderFields setHow to get the bytes
Anthropic{ id, source }Uniform — retrieveFile(file) / streamFile(file) (see below).
OpenAI{ url, source } (code-interpreter images) or { id, name, ref, source } (container files)Uniform — retrieveFile(file) / streamFile(file) (see below).
Google{ data, mimeType, source }Uniform — retrieveFile(file) / streamFile(file) (see below).
xAI{ data, name, mimeType, source } (inline bytes from the code-interpreter logs)Uniform — retrieveFile(file) / streamFile(file) (see below).

Read the bytes — retrieveFile / streamFile

Section titled “Read the bytes — retrieveFile / streamFile”

You don’t fetch per-provider. The result object carries two helpers bound to the same model + key the call used — pass a FileOutput straight back:

const { response, retrieveFile } = await complete({
model: 'anthropic/claude-haiku-4.5',
apiKey: process.env.ANTHROPIC_API_KEY,
prompt: 'Plot y = x**2 for x in 1..5 with matplotlib, save a PNG, and return the file.',
tools: [{ type: 'code_interpreter' }],
maxTokens: 6000,
});
for (const file of response.files ?? []) {
const { blob, name, mimeType, size } = await retrieveFile(file);
// name → 'chart.png' mimeType → 'image/png' size → 43940
// browser: URL.createObjectURL(blob) → <img> / <a download={name}>
}

retrieveFile buffers into a Blob; streamFile pipes large files to a file / GridFS / HTTP response without buffering. Both resolve all three shapes (inline data, url, provider file id) and return the real name / mimeType / size, with auth sent only to the provider’s own host. Full reference: Retrieving output files.

stream() has full file parity with complete(). As the model finalizes each output file, a { type: 'file', file } event is emitted mid-stream, and the same files are collected onto the streamed final response’s files (surfaced via the onCompletion hook / agent final response). The event carries the FileOutput descriptor (id / url / inline data + name), not the bytes — fetch those with the same retrieveFile / streamFile:

for await (const ev of llm.stream(PROMPT, { tools: [{ type: 'code_interpreter' }], maxTokens: 6000 })) {
if (ev.type === 'text') process.stdout.write(ev.text);
if (ev.type === 'file') {
// A chart/CSV just finalized — fetch its bytes + attachment metadata.
const { blob, name, mimeType, size } = await llm.retrieveFile(ev.file);
}
}

The routing is identical across providers: Anthropic emits the file id in its code-execution result block, OpenAI in the container-file annotation / image output, and Google folds its inline code-execution artifact into a file event (kept distinct from conversational media).

  • Anthropic beta routing is automatic. Anthropic’s code execution is a beta feature and its file outputs only return on the beta endpoint — the SDK detects the code_interpreter builtin and routes the request accordingly. You do nothing.
  • Produce a real file to get a file. Providers surface a downloadable file only when the code writes one (e.g. saving a chart). Code that merely prints a table to stdout yields text, not a FileOutput. Ask the model to save/return a file when you want one.
  • Agent runs carry files through too. response.files propagates through AgentLoop / createAgent, so a code-execution step inside an agent run still surfaces its files on the final response.
  • Not all providers have it. OpenAI, Anthropic, Google, and xAI support hosted code execution (xAI returns its output files inline in the code-interpreter logs — the SDK handles that for you). OpenRouter does not route hosted code execution, so code_interpreter is unavailable there (web search still works, via its :online routing).