Given one container with a skill mounted, the model auto-discovers and runs the skill when the container is used via the Shell tool, but not via the Code Interpreter tool — even though the skill files are present and readable in both. Neither request declares skills; the only difference is the tool.
Furthermore, Code Interpreter has no way to specify skills, whereas the Shell tool does.
Are there plans to support skills in Code Interpreter? Aligning it with the Shell tool would be ideal.
Here’s a script with an A/B testing:
#!/usr/bin/env bash
# Code Interpreter doesn't auto-discover container-mounted skills (Shell tool does).
# PUBLIC OpenAI version (api.openai.com). Same skill-mounted container in A and B.
# Requires: OPENAI_API_KEY. Optional: OPENAI_MODEL (default gpt-5.4).
set -uo pipefail
API="https://api.openai.com/v1"
H=(-H "Authorization: Bearer ${OPENAI_API_KEY:?set OPENAI_API_KEY}")
MODEL="${OPENAI_MODEL:-gpt-5.4}"
DESC="Compute sums, products, and triangle areas and report them in a strict machine-readable format. Use whenever the user asks for arithmetic results or a triangle area."
TASK="Add 144 and 377, and give the area of a triangle with base 9 and height 13. Use the math-reporter skill if available."
WORK="$(mktemp -d)"; trap 'rm -rf "$WORK"' EXIT; cd "$WORK"
mkdir -p math-reporter
cat > math-reporter/SKILL.md <<MD
---
name: math-reporter
description: $DESC
---
# Math Reporter
Respond with ONLY: first line \`SKILL: math-reporter\`; then one \`<LABEL> = <VALUE> (<FORMULA>)\`
line per quantity (e.g. SUM, TRIANGLE_AREA); then a final line \`DONE\`. No prose.
Triangle area uses \`0.5 * base * height\`.
MD
B64="$(python3 -c "import base64,zipfile,io;b=io.BytesIO();z=zipfile.ZipFile(b,'w');z.write('math-reporter/SKILL.md');z.close();print(base64.b64encode(b.getvalue()).decode())")"
pt() { python3 -c 'import sys,json;d=json.load(sys.stdin);print("".join(c["text"] for o in d.get("output",[]) if o.get("type")=="message" for c in o.get("content",[]) if c.get("type")=="output_text").strip() or ("ERROR: "+str(d.get("error"))))'; }
CID="$(curl -sS -X POST "$API/containers" "${H[@]}" -H "Content-Type: application/json" -d '{
"name":"demo",
"skills":[{"type":"inline","name":"math-reporter","description":"'"$DESC"'",
"source":{"type":"base64","media_type":"application/zip","data":"'"$B64"'"}}]
}' | jq -r .id)"
echo "container: $CID"
echo; echo "=== A. SHELL tool -> skill IS auto-discovered ==="
curl -sS -X POST "$API/responses" "${H[@]}" -H "Content-Type: application/json" -d '{
"model":"'"$MODEL"'",
"tools":[{"type":"shell","environment":{"type":"container_reference","container_id":"'"$CID"'"}}],
"input":"'"$TASK"'"}' | pt
echo; echo "=== B. CODE INTERPRETER, same container -> skill NOT discovered ==="
curl -sS -X POST "$API/responses" "${H[@]}" -H "Content-Type: application/json" -d '{
"model":"'"$MODEL"'",
"tools":[{"type":"code_interpreter","container":"'"$CID"'"}],
"input":"'"$TASK"'"}' | pt
echo
curl -sS -o /dev/null -w "delete container: HTTP %{http_code}\n" -X DELETE "$API/containers/$CID" "${H[@]}"