Code Interpreter

Ma Mahalakshmi V Updated 16 Sep 2026
10 min read ·Lesson 39 of 224

Why a Language Model Needs a Real Interpreter

A language model, no matter how capable, does not actually execute arithmetic or logic when it generates text — it produces the next most plausible token given everything before it, which for a simple calculation usually produces the right answer, but for anything involving many steps, precise numerical computation, or manipulation of structured data (sorting a long list, computing a statistical measure, parsing and reshaping a CSV file), reasoning "in its head" as text generation becomes unreliable in a way that compounds with complexity. Code Interpreter is the platform's built-in answer to this: instead of asking the model to simulate what a computation would produce, it lets the model write actual code and have that code actually executed in a real sandboxed environment, with the genuine output fed back into the conversation.

This is a meaningfully different kind of built-in tool than web search or file search. Web search and file search both retrieve information; Code Interpreter performs computation, and the difference matters for the same reason a person doing long division on paper gets a more reliable answer than doing it purely from memory — the correctness comes from an actual mechanical process, not from confident recall.

Enabling Code Interpreter

response = client.responses.create(
    model="gpt-5.6-terra",
    input="I have a list of numbers: 45, 12, 78, 23, 91, 34, 67. What's the median, and how far is the largest number from the mean?",
    tools=[{"type": "code_interpreter", "container": {"type": "auto"}}],
)

print(response.output_text)

Note: The exact tool configuration (the container field and its accepted values) and which models support Code Interpreter can vary by SDK version. Confirm the current interface against your installed SDK version's documentation before relying on these specifics.

Given a request like this, the model doesn't attempt to compute the median and mean through text-generation "reasoning" alone — it writes a short piece of code that actually performs the calculation (using a real statistics library, most likely), that code actually runs in a sandboxed container the platform manages, and the genuine numerical output is what the model's final answer is based on. This is a strictly more reliable process for this kind of task than asking the model to compute it purely through generated text, since a real interpreter either produces the mathematically correct result or raises a real error — it cannot silently produce a plausible-sounding wrong number the way unaided text generation sometimes can.

Inspecting the Code That Actually Ran

response = client.responses.create(
    model="gpt-5.6-terra",
    input="Calculate the standard deviation of these values: 22, 35, 41, 18, 29, 33.",
    tools=[{"type": "code_interpreter", "container": {"type": "auto"}}],
)

for item in response.output:
    if item.type == "code_interpreter_call":
        print("Code executed:")
        print(item.code)
        print("Output:")
        print(item.outputs)

print(response.output_text)

Note: The exact structure of code_interpreter_call items (field names for the executed code and its output) can vary by SDK version. Confirm the current output shape against your installed SDK version's documentation.

Reviewing the actual code that ran, rather than only the model's final natural-language summary of the result, is worth doing routinely during development — it's a direct way to verify the model is solving the problem the way you expect (using the correct formula, the correct library, the correct interpretation of the input data) rather than trusting a plausible-sounding final answer without checking the process that produced it. This mirrors the general principle Unit 6 established for structured outputs: a result that looks right and a result that is verifiably right are different claims, and inspecting the underlying work is how the gap between them gets closed.

Working With Data Files

Code Interpreter's most practical use is analyzing an uploaded data file directly — computing statistics, filtering rows, generating a chart — since a file can be attached to the same request that enables the tool.

with open("quarterly_sales.csv", "rb") as f:
    uploaded_file = client.files.create(file=f, purpose="user_data")

response = client.responses.create(
    model="gpt-5.6-terra",
    input=[{"role": "user", "content": [
        {"type": "input_text", "text": "Which product category had the highest total sales in Q3? Show your work."},
        {"type": "input_file", "file_id": uploaded_file.id},
    ]}],
    tools=[{"type": "code_interpreter", "container": {"type": "auto", "file_ids": [uploaded_file.id]}}],
)

print(response.output_text)

This combines the Files API from Unit 7, Lesson 2 with Code Interpreter directly: the uploaded CSV is made available inside the code execution environment, letting the model write and run code that actually reads, parses, and aggregates the real file content — rather than trying to reason about a CSV's contents purely from a text description, which is unreliable for anything beyond a very small file, and which Unit 7 never attempted for exactly this reason. This pattern — attach a data file, ask a question that requires real computation over it, let Code Interpreter do the actual analysis — is the standard way to build a "let me analyze this spreadsheet for you" feature.

Generating and Retrieving Charts

Code Interpreter can also produce visual output — a chart or plot generated by real plotting code, which the response makes available as a file to download.

response = client.responses.create(
    model="gpt-5.6-terra",
    input=[{"role": "user", "content": [
        {"type": "input_text", "text": "Create a bar chart showing total sales by category from this data."},
        {"type": "input_file", "file_id": uploaded_file.id},
    ]}],
    tools=[{"type": "code_interpreter", "container": {"type": "auto", "file_ids": [uploaded_file.id]}}],
)

for item in response.output:
    if item.type == "code_interpreter_call":
        for output_item in item.outputs:
            if getattr(output_item, "type", None) == "image":
                generated_file_id = output_item.file_id
                file_content = client.files.content(generated_file_id)
                with open("sales_by_category.png", "wb") as f:
                    f.write(file_content.read())

Note: The exact mechanism for retrieving a generated chart image (the output item's structure and the method for downloading file content) can vary by SDK version. Confirm the current interface against your installed SDK version's documentation.

The chart here is a genuine image produced by real plotting code actually executed against the real uploaded data — not a description of what a chart might look like, which a model attempting to describe a chart in words could never substitute for. Downloading the resulting image with client.files.content() and saving it to disk follows the same pattern Unit 7, Lesson 3 used for saving a generated image, since in both cases the underlying operation is "the platform produced a real image file, and your code needs to retrieve and persist it."

Multi-Step Analysis: The Model Can Iterate

A genuinely useful property of Code Interpreter is that the model can run code, see the actual output (including an error, if the code failed), and write follow-up code in response — an iterative debugging loop happening automatically within the tool, without requiring your own code to orchestrate the multi-round back-and-forth Unit 8, Lesson 3 built for custom function calls.

response = client.responses.create(
    model="gpt-5.6-terra",
    input=[{"role": "user", "content": [
        {"type": "input_text", "text": "Find any rows in this dataset with missing values and tell me which columns are affected."},
        {"type": "input_file", "file_id": uploaded_file.id},
    ]}],
    tools=[{"type": "code_interpreter", "container": {"type": "auto", "file_ids": [uploaded_file.id]}}],
)

code_interpreter_calls = [item for item in response.output if item.type == "code_interpreter_call"]
print(f"Number of code execution steps: {len(code_interpreter_calls)}")

For a question requiring exploration (checking for missing data, trying one filtering approach and then refining it), code_interpreter_calls may contain more than one step — the model writing an initial piece of exploratory code, seeing its real output, and writing a follow-up based on what it actually found, all handled internally by the platform within a single client.responses.create() call. This is a meaningful difference from the explicit, application-code-driven loop Unit 8 required for custom functions: Code Interpreter's internal iteration doesn't require your own code to detect a "the model wants to try again" signal and manually re-invoke anything, though inspecting code_interpreter_calls afterward, as shown here, is still worth doing to understand how many steps the model actually needed.

Cost, Latency, and When to Reach for Code Interpreter

Like every built-in tool covered in this unit, Code Interpreter adds cost and latency beyond a plain text request — a real sandboxed environment has to be provisioned and code has to actually execute, which takes measurably longer than text generation alone. It is well suited to requests genuinely requiring computation or data manipulation (statistics, calculations across many data points, file parsing and aggregation, chart generation) and unnecessary for requests a model can answer reliably through ordinary reasoning (a simple arithmetic fact, a conceptual question, a request that doesn't touch any actual data). A useful heuristic: if verifying the model's answer by hand would require you to actually run a calculation or inspect real data rather than just checking whether the reasoning sounds right, that's a strong signal Code Interpreter is the appropriate tool for the request.

The Sandbox Is Isolated, and That's Deliberate

The environment Code Interpreter executes code in is a sandboxed container with no access to your own systems, network, or credentials — it can run the code the model writes and work with files explicitly provided to it, but it cannot reach an internal database, call an internal API, or access anything outside the specific files attached to the request. This is a deliberate safety boundary, not a limitation to work around: unlike a custom function (Unit 8) where you control exactly what a function can access, Code Interpreter's code is effectively written by the model itself, and running arbitrary model-written code against your real internal systems would be a significant, unnecessary risk. If a task genuinely requires touching your own systems (querying an internal database, calling an internal service), that calls for a custom function with a narrow, well-defined interface (Unit 8) rather than Code Interpreter, precisely because a custom function's implementation is code you wrote and control, while Code Interpreter's implementation is code the model wrote at request time.

Testing Code-Interpreter-Dependent Logic With Fakes

Following this unit's established pattern, code that processes a Code Interpreter response — counting execution steps, extracting generated file IDs — can be tested with fake response objects rather than a real sandboxed execution.

class FakeCodeOutput:
    def __init__(self, output_type, file_id=None):
        self.type = output_type
        self.file_id = file_id

class FakeCodeInterpreterCall:
    def __init__(self, code, outputs):
        self.type = "code_interpreter_call"
        self.code = code
        self.outputs = outputs

class FakeResponse:
    def __init__(self, output):
        self.output = output

def extract_generated_image_ids(response) -> list[str]:
    image_ids = []
    for item in response.output:
        if item.type != "code_interpreter_call":
            continue
        for output_item in item.outputs:
            if output_item.type == "image":
                image_ids.append(output_item.file_id)
    return image_ids

def test_extract_generated_image_ids():
    fake_response = FakeResponse(output=[
        FakeCodeInterpreterCall(code="plt.bar(...)", outputs=[FakeCodeOutput("image", file_id="file-123")]),
    ])
    result = extract_generated_image_ids(fake_response)
    assert result == ["file-123"]
    print("PASS: extract_generated_image_ids correctly pulls generated file IDs from a fake response")

test_extract_generated_image_ids()

This lets the file-retrieval logic itself be verified deterministically and without cost, reserving real Code Interpreter calls (which involve actually provisioning a sandbox and executing real code) for a smaller set of end-to-end tests confirming the model produces reasonable results against representative real data — the same tiered testing approach this course has applied to every other paid, non-deterministic API surface.

Common Mistakes

Asking the model to reason through a nontrivial calculation or data analysis in plain text without enabling Code Interpreter, relying on unaided text generation for a task that benefits directly from actual, verifiable code execution.

Trusting a final natural-language summary without reviewing the underlying executed code, missing an opportunity to catch a case where the code solved a subtly different problem than the one actually asked.

Enabling Code Interpreter for every request regardless of whether real computation is involved, adding unnecessary cost and latency to questions that don't need it.

Forgetting that a generated chart or output file must be explicitly retrieved and saved, rather than assuming it appears automatically somewhere outside the response object.

Best Practices

Reach for Code Interpreter specifically when a request requires genuine computation, data manipulation, or chart generation, rather than for requests a model can already answer reliably through ordinary reasoning.

Inspect the actual executed code during development, not just the final summary, to confirm the model solved the intended problem the intended way.

Combine Code Interpreter with the Files API when the task involves analyzing an uploaded data file, letting real code operate on the real file content rather than asking the model to reason about a file's contents from a text description alone.

Explicitly retrieve and save any generated output files (charts, processed data), following the same download-and-persist pattern established for other generated file types earlier in this course.

0 Comments

Reviewed before they appear

No comments yet.

OpenAI SDK
Introduction to the OpenAI SDK Setting Up Python Creating an API Key Your First Call — client.responses.create() and response.output_text Understanding Billing, Credits, and What a Request Costs Why Responses Replaced Chat Completions Anatomy of a Request: model, input, and instructions Anatomy of a Response: The Typed output Array, Not Just Text Roles: User, Assistant, and Developer/System Choosing a Model, and Reading the Models Page Instead of Memorizing Names Instructions vs. Input Writing Prompts That Get Consistent Results Few-Shot Examples Reasoning Models and the reasoning Parameter Debugging a Prompt That Misbehaves Why Streaming Matters for User Experience stream=True and Iterating Over Events Handling the Event Types You Actually Care About Background Mode for Long-Running Jobs Project — Add Live Streaming to Your Chatbot The Problem With Parsing Free Text JSON Schema and Strict Mode Pydantic Models With the SDK's Parse Helpers Handling Refusals and Validation Failures Project — A Resume-to-JSON Extractor Working With input_image input_file, PDFs, and the Files API Image Generation Speech-to-Text and Text-to-Speech Project: A PDF Question-Answering Script What Function Calling Is Defining a Tool Schema The Full Loop Multiple Tools Errors, Timeouts, and Untrusted Arguments Project: A Weather Assistant Web Search File Search and Vector Stores Code Interpreter Remote MCP Servers and Connectors Project: A Research Assistant What an Embedding Is, Without the Maths Generating and Storing Embeddings Similarity Search From Scratch Hosted Vector Stores vs. Rolling Your Own A Small RAG App Over a Folder of Notes Agents vs. a Single API Call — When You Need One pip install openai Giving Agents Tools Handoffs and Multi-Agent Triage Guardrails and Approvals Tracing and Observing What Your Agent Did A Multi-Agent Support Desk Error Codes and What Each One Means Retries, Timeouts, and Backoff Rate Limits and Spend Limits Prompt Caching and Cost Optimisation The Batch API for Bulk Work Async Clients and Concurrency Moderation and Safety Best Practices Designing the App Backend With FastAPI Streaming to a Simple Frontend Deploying and a Cost/Safety Checklist Why Web Search Is Useful for Current Information Using the Web Search Tool with the Responses API Configuring Search Behavior for Application Use Cases Understanding Citations and Source Attribution Where to Go Next Building a Research Assistant with Web Search Combining Web Search with Structured Outputs Handling Conflicting or Low-Quality Web Sources Reducing Unsupported Claims with Grounded Generation Testing Freshness-Sensitive AI Answers Production Considerations for Web-Grounded Applications Understanding File Search and Retrieval-Augmented Generation Creating and Organizing Vector Stores Uploading Documents for Retrieval Connecting Vector Stores to Responses API Requests Designing Document Metadata and Filtering Strategies Building a PDF Question-Answering Application Improving Retrieval Quality With Better Document Preparation Handling Missing Evidence and Retrieval Failures Combining File Search With Web Search Building a Production Knowledge-Base Assistant What the Code Interpreter Tool Is Designed For Running Python-Based Analysis Through the OpenAI SDK Uploading Datasets for Analysis Analyzing CSV and Spreadsheet Data Generating Charts and Data Summaries Handling Generated Files and Downloadable Artifacts Building a Data-Analysis Assistant Combining Code Execution with Structured Outputs Validating Generated Calculations and Results Security and Sandbox Considerations for Code Execution Understanding Multimodal Input with the OpenAI SDK Sending Images to a Model Image Analysis from URLs and Uploaded Files Extracting Text and Information from Screenshots Building an Image-Question-Answering Application Combining Image Input with Structured Output Analyzing Multiple Images in One Request Handling Image Quality and Input Limitations Designing Multimodal Prompts for Reliable Results Building a Practical Vision-Powered Python Application Understanding Speech-to-Text and Text-to-Speech Workflows Transcribing Audio with the OpenAI SDK Working with Uploaded Audio Files Handling Timestamps and Transcription Metadata Building a Meeting Transcription Workflow Generating Spoken Responses from Text Handling Long Audio and Processing Failures Combining Audio with Text and Tool Calling Building an End-to-End Python Voice Application What Embeddings Are and When to Use Them Generating Embeddings With the OpenAI API Preparing Text for Embedding Comparing Vectors With Cosine Similarity Building a Simple Semantic Search Engine in Python Storing Embeddings in a Database Metadata Filtering for Semantic Search Chunking Strategies for Better Retrieval Evaluating Semantic Search Quality Building a Document Similarity Application When Batch Processing Makes Sense Designing Large-Volume AI Processing Pipelines Using Asynchronous Python with the OpenAI SDK Running Concurrent Requests Safely Controlling Concurrency and Avoiding Rate Limits Tracking Batch Job Progress Handling Partial Failures in Bulk Workloads Retrying Failed Items Without Duplicating Successful Work Designing Resumable AI Processing Jobs Building a Production Batch-Processing Pipeline Batch Processing Makes Sense Large-Scale AI Processing Pipelines Async Python with OpenAI SDK Safe Concurrent Requests Concurrency & Rate Limits Batch Progress Tracking Partial Failure Handling Safe Retry Handling Resumable AI Jobs Production Batch Pipeline System–User Data Separation Reusable App Instructions Prompt Templates & Variables Extraction & Classification Prompts Summarization & Transformation Prompts Explicit Output Requirements Prompt Version Management Prompt Testing & Evaluation Reusable Python Prompt Library API Key Security Secure API Key Storage Secure Secret Management Prompt Injection Prevention Trusted vs. Untrusted Content Tool Argument Validation Sensitive Data Handling Secure Logging AI Action Authorization Production AI Security Checklist Why AI Applications Need Evaluation Beyond Unit Tests Unit Testing OpenAI SDK Integration Code Mocking API Responses in Python Tests Testing Structured Outputs Against Schemas Testing Tool-Calling Workflows Building a Small Evaluation Dataset Measuring Accuracy, Consistency, and Failure Rates Regression Testing Prompts and Model Changes Human Evaluation Versus Automated Evaluation Creating a Repeatable Evaluation Pipeline AI Request Monitoring Token Cost Management Usage Metrics Design Reducing Model Calls Prompt & Context Optimization Model Selection & Optimization AI Caching Strategies Interactive Latency Optimization Usage Dashboards & Budget Alerts Performance & Cost Checklist Every API Call Starts Fresh Fixing API Statelessness Server-Side Conversation Memory Limits of Response Chaining What We're Building Conversation Memory Challenges Preparing an OpenAI SDK Application for Deployment Environment-Specific Configuration for Development and Production Deploying a Python AI Service with Docker Container Health Checks and Startup Configuration Managing Secrets in Cloud Deployments Background Workers for Long-Running AI Tasks Queues and Asynchronous Job Architectures Scaling AI Workloads Horizontally Monitoring Production Incidents and Failures Production Deployment Checklist for OpenAI SDK Applications Reusable OpenAI Service Classes AI Client Dependency Injection Typed AI Responses Python Configuration Management AI Request Decorators Centralized AI Error Handling Clean SDK Abstractions Reusable OpenAI Utilities Internal AI Python Libraries SDK Integration Maintenance Production AI Chatbot Document Q&A System Web Research Assistant Customer Support Agent AI Data Analysis Assistant Image Analysis App Meeting Transcription & Summary Semantic Document Search Multi-Tool AI Agent Production OpenAI SDK App Why "It Looked Fine When I Tested It" Isn't Enough Timing Note Status Note Pre-Decision Status Note Current Availability Note
Ask about this post
AI Ask about this post

Ask questions about Code Interpreter and get answers drawn from it.

Signed-in readers only.