Skip to content
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. Return each cell's output as a tool message.

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.

Facts on this page were checked on 25 October 2026.

Related.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card