A five-minute coding session costs about $0.0014 in a Runtime sandbox.
Together removed its Code Interpreter API with Python SDK 3.0 and TypeScript
SDK 1.0, released 22 October 2026, so a Together model that writes code needs
a machine of yours to run it. Runtime bills the CPU the code uses and the
memory it holds, so a session that mostly waits for the model costs little,
and its interpreter runs seven languages. The examples call
zai-org/GLM-5.3, which Together's serverless catalog marked for function
calling on 25 October 2026.
One interpreter per conversation
A conversation's code needs its packages, variables and memory kept from one
cell to the next. On Runtime that is a sandbox found again by name:
Sandbox.getOrCreate returns the conversation's sandbox, woken if it paused,
and its interpreter still holds every variable.
TypeScriptimport Together from "together-ai";import type { ChatCompletionMessageParam } from "together-ai/resources/chat/completions";import { Sandbox } from "withruntime";const together = new Together(); // TOGETHER_API_KEY, on your serverasync function runCell(conversationId: string, code: string): Promise<string> { const sbx = await Sandbox.getOrCreate(`chat-${conversationId}`, { vcpu: 1, memoryMiB: 2048, idlePauseSeconds: 600, network: { internet: false }, }); const cell = await sbx.interpreter.run(code, { timeoutMs: 60_000 }); return JSON.stringify({ status: cell.status, stdout: cell.stdout, stderr: cell.stderr, error: cell.error?.value ?? null, result: cell.results.find((r) => r.main)?.data["text/plain"] ?? null, });}const tools = [ { type: "function" as const, function: { name: "run_python", description: "Run a Python cell in this conversation's notebook. Variables and imports persist " + "between calls. No internet. Returns status, stdout, stderr, error and the last value.", parameters: { type: "object", properties: { code: { type: "string" } }, required: ["code"], }, }, },];export async function chat(conversationId: string, messages: ChatCompletionMessageParam[]) { for (let turn = 0; turn < 8; turn++) { const response = await together.chat.completions.create({ model: "zai-org/GLM-5.3", messages, tools, }); const message = response.choices[0]?.message; const toolCalls = message?.tool_calls ?? []; if (toolCalls.length === 0) return message?.content ?? ""; messages.push({ role: "assistant", content: "", tool_calls: toolCalls }); for (const call of toolCalls) { const { code } = JSON.parse(call.function.arguments) as { code: string }; messages.push({ role: "tool", tool_call_id: call.id, content: await runCell(conversationId, code), }); } } return "stopped after 8 turns";}console.log( await chat("42", [ { role: "user", content: "Load a 1,000-row random DataFrame and describe it." }, ]),);Pythonimport jsonfrom together import Togetherfrom withruntime import Sandboxclient = Together() # TOGETHER_API_KEY, on your serverdef run_cell(conversation_id: str, code: str) -> str: sbx = Sandbox.get_or_create( f"chat-{conversation_id}", vcpu=1, memory_mib=2048, idle_pause_seconds=600, network={"internet": False}, ) cell = sbx.interpreter.run(code, timeout_ms=60_000) main = next((r["data"].get("text/plain") for r in cell["results"] if r["main"]), None) return json.dumps( { "status": cell["status"], "stdout": cell["stdout"], "stderr": cell["stderr"], "error": (cell["error"] or {}).get("value"), "result": main, } )tools = [ { "type": "function", "function": { "name": "run_python", "description": "Run a Python cell in this conversation's notebook. Variables and imports persist " "between calls. No internet. Returns status, stdout, stderr, error and the last value.", "parameters": {"type": "object", "properties": {"code": {"type": "string"}}, "required": ["code"]}, }, }]def chat(conversation_id: str, messages: list) -> str: for _ in range(8): message = client.chat.completions.create(model="zai-org/GLM-5.3", messages=messages, tools=tools).choices[0].message if not message.tool_calls: return message.content or "" messages.append({"role": "assistant", "content": "", "tool_calls": [c.model_dump() for c in message.tool_calls]}) for call in message.tool_calls: code = json.loads(call.function.arguments)["code"] messages.append({"role": "tool", "tool_call_id": call.id, "content": run_cell(conversation_id, code)}) return "stopped after 8 turns"print(chat("42", [{"role": "user", "content": "Load a 1,000-row random DataFrame and describe it."}]))The first call in a conversation creates its sandbox. Later calls reuse it,
from any process. After ten quiet minutes, the sandbox pauses with its memory
kept. Stop the sandbox with sbx.stop() when the conversation closes. A cell
that runs too long returns status: "timeout" instead of hanging the chat.
Together's code sandbox compared
Together's SDK v3 migration guide says client.code_interpreter and
client.codeInterpreter are gone, "along with the API they called". Together
now documents a separate code sandbox product:
| Question | Together code sandbox | Runtime sandbox interpreter |
|---|---|---|
| Access | Enabled per organization; you contact Together to request it | Every account, with 100 free hours of a 1 GB machine in the first 30 days and no card |
| What it runs | Commands in a sandbox started from a Docker-image snapshot | Stateful cells with sbx.interpreter.run, plus commands |
| Languages per cell | Whatever the snapshot installs | Python, JavaScript, TypeScript, R, Java, Bash and Go |
| Life | Runs until terminated, unless you set a ttl at creation |
Runs, then pauses when idle; kept while you have credit while paused |
| Network control | Not described on Together's code sandbox page | Internet off, or named hosts only, enforced on the host |
What sessions cost
A 1 vCPU, 2 GiB sandbox, as above, is billed at $0.025 per vCPU-hour of measured CPU, with a floor of a twentieth of a vCPU, and $0.0075 per GiB-hour of memory (pricing):
| Session | Runtime, 1 vCPU and 2 GiB |
|---|---|
| 5 minutes, 20 CPU-seconds of work | $0.00125 memory + $0.00014 CPU = $0.0014 |
| 1,000 such sessions | $1.39 |
| 60 minutes, mostly waiting (the CPU floor) | $0.015 + $0.00125 = $0.01625 |
| 60 minutes with the CPU busy throughout | $0.015 + $0.025 = $0.04 |
Together bills the tokens. Between turns, a paused sandbox stops compute billing and is charged as paused storage.
Keys
TOGETHER_API_KEY stays on your server. The loop calls Together, and the
sandbox receives only cells. If code inside the sandbox must call Together,
store the key as a Runtime secret bound to api.together.ai and
api-inference.together.ai, where Together's SDKs send chat completions by
default since Python SDK 3.0 and TypeScript SDK 1.0. The sandbox then sees a
placeholder, which only the host's proxy turns into the key
(secrets).
Start
A new account gets 100 free hours of a 1 GB machine in its first 30 days, no card. The first run prints a link to approve in your browser:
Terminalnpx withruntime sandboxes run -- python3 -c 'import pandas; print(pandas.__version__)'More: add a code interpreter to a chatbot, a data analysis agent, RL environments, what a code interpreter is.
Sources
Checked 25 October 2026.
- Together AI: function calling and agentic patterns
- Together AI: SDK v3 migration: the code interpreter and its API removed; chat completions sent to
api-inference.together.aiby default - Together AI: changelog: Python SDK 3.0 and TypeScript SDK 1.0, 22 October 2026
- Together AI: code sandbox, where the old code interpreter address now redirects
- Together AI: serverless models
- together-ai on npm (1.0.0) and together on PyPI (3.0.0)
Facts on this page were checked on 25 October 2026.