Runtime

Together AI function calling: run the model's code in a sandbox

Give a Together model a run_python tool backed by a stateful sandbox interpreter, and return each cell's output as a tool message.

A five-minute coding session costs about $0.0014 in a Runtime sandbox, against the $0.03 per session Together charges for its Code Interpreter, checked 25 September 2026. 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 where Together's runs Python. The examples call zai-org/GLM-5.3, which Together's serverless catalogue marked for function calling on 25 September 2026.

One interpreter per conversation

Together's Code Interpreter keeps "all packages, variables, and memory" for a session reused by its session_id. The Runtime equivalent 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 it pauses with its memory kept, and the next cell wakes it, usually in about half a second (pause and resume). Stop it with sbx.stop() when the conversation closes. A cell that runs too long returns status: "timeout" instead of hanging the chat.

Together Code Interpreter compared

Question Together Code Interpreter (TCI) Runtime sandbox interpreter
How the model reaches it Your code calls code_interpreter / codeInterpreter.execute Your code calls sbx.interpreter.run
Languages "Currently only supports Python" Python, JavaScript, TypeScript, R, Java, Bash and Go
Session life 60 minutes Runs, then pauses when idle; kept 1 to 365 days while paused
Packages Pre-installed data libraries, !pip install Default image, pip behind an allow list, or a custom image
Output stdout, stderr, errors, display data stdout, stderr, error with traceback, PNG charts, tables
Network control Not described on the TCI page Internet off, or named hosts only, enforced on the host
Price $0.03 per session Measured CPU plus memory while running

Both run the code outside your servers. TCI is one API call away if your stack is Together-only and Python-only. Runtime gives you the machine: its size, image, network rules and how long it lives.

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 TCI Runtime, 1 vCPU and 2 GiB
5 minutes, 20 CPU-seconds of work $0.03 $0.00125 memory + $0.00014 CPU = $0.0014
1,000 such sessions $30.00 $1.39
60 minutes, mostly waiting (the CPU floor) $0.03 $0.015 + $0.00125 = $0.01625
60 minutes with the CPU busy throughout $0.03 $0.015 + $0.025 = $0.04

Tokens are billed by Together in both cases. A paused sandbox between turns 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; the sandbox sees a placeholder that only the host's proxy turns into the key (secrets).

Start

New accounts get 50 free sandbox hours, no card. The first run prints a link to approve in your browser:

Terminalnpx withruntime sandbox run --trial -- 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 September 2026.

Facts on this page were checked on 25 September 2026.