code_execute

Run JavaScript, Python, or Bash in a sandboxed Docker container. No network access.

"No network" is the SANDBOX only — you (the agent) can fetch the web

The network isolation applies inside the sandbox container, not to you. Your own environment has full outbound network: WebSearch, WebFetch, and curl/wget in Bash all work. So the pattern for anything that needs an external asset or data is fetch first, then feed the sandbox — never conclude "I can't get that, no network."

File I/O Contract - "sandbox = your project"

Running it (gipity sandbox run)

Code is the final positional arg. --language js|python|bash (required), --timeout <sec> (default 30, max 600), --input <path> (repeatable; narrows the /work/ mirror). The CLI pushes your local working tree up before running, so inputs staged any way - a Bash cp/ffmpeg/redirect, not just files written through an editor - are mirrored in; no manual gipity sync first. The one exception is the scratch namespaces (tmp/, .gipityscratch/, *_tmp/): they are never synced, so they are never mirrored in either - stage inputs at a real project path (see the File I/O Contract above). Files written under cwd (/work/) auto-sync back to the project at the same path. Add --json for machine output.

--discard-output <glob> (repeatable) drops matching run outputs entirely - not saved, not returned; you cannot look at a discarded file. For byproducts you want to LOOK at but never keep, don't discard - write them under tmp/ (comes back to local disk only, never enters the project). Globs support * (one segment), **, and dir/ prefixes; the CLI lists what was dropped.

To inspect a produced PDF, Read the synced file directly - the Read tool renders PDF pages when the host has poppler. If it fails ("pdftoppm is not installed"), rasterize in the sandbox instead (it always has poppler):

gipity sandbox run bash "pdftoppm -png -r 80 docs/report.pdf tmp/preview"   # pages land in local tmp/, never persisted

The language is always explicit. There is no default: pin it with --language python (or py/bash/js), an interpreter token as the first arg (gipity sandbox run bash "<cmd>", gipity sandbox run python <file-or-code>), or --file script.py (inferred from the extension). A bare gipity sandbox run "<code>" fails immediately, locally, and prints these three forms - it never guesses an interpreter for you.

gipity sandbox run --language python "print(2 ** 10)"
gipity sandbox run --language python --timeout 120 "$(cat build_report.py)"   # multi-line code, no shell-quoting pain
gipity sandbox run --language bash --input clip.mp4 "ffmpeg -y -i clip.mp4 clip.webm"
gipity sandbox run bash "echo hi; ffmpeg -version"   # interpreter shorthand pins the language
gipity sandbox run --file build_report.py            # language inferred from .py

Deterministic text questions - use text_analyze / gipity text, not the sandbox

For letter/word counts, substring occurrences and positions, nth word/char, anagram checks, or letter frequency, don't spin up the sandbox (and never answer from an LLM's head): the text_analyze tool (agent surface) and gipity text analyze "<text>" (CLI) run the same exact-arithmetic engine and answer instantly. CLI: pipe via stdin or use --file <path> for longer text. Targeted flags short-circuit the full profile: --count <substr>, --find <substr> (1-indexed positions), --word <n> / --char <n> (negative counts from the end), --anagram <other>; modifiers --whole-word, --case-sensitive, --json.

gipity text analyze "strawberry" --count r        # "r" (case-insensitive): 3 non-overlapping ...
gipity text analyze --file notes.md               # full profile: counts, words, frequency, palindrome

Pre-installed Runtimes

CLI Tools (prefer one-liners over scripts)

Discovering tools

The toolset is fixed and there is no network, so pip install / npm install / apt-get will fail - never reach for them. Use only what's preinstalled, and if unsure whether a tool or package is available, probe before using it (a fast check is cheaper than a failed run):

Worked Examples

1. FFmpeg - transcode MP4 → WebM

input_files: ["videos/clip.mp4"]
language: bash
code: ffmpeg -y -i videos/clip.mp4 -c:v libvpx-vp9 -b:v 1M -c:a libopus videos/clip.webm

Returns: project gains videos/clip.webm. The .mp4 is unchanged, so it is not re-written.

2. FFmpeg - extract 10 frames from a video

input_files: ["videos/clip.mp4"]
language: bash
code: |
  mkdir -p frames
  ffmpeg -y -i videos/clip.mp4 -vf "fps=10/$(ffprobe -v error -show_entries format=duration -of csv=p=0 videos/clip.mp4)" frames/frame_%03d.jpg

Returns: frames/frame_001.jpgframes/frame_010.jpg.

3. ImageMagick - resize + convert format

input_files: ["images/photo.jpg"]
language: bash
code: |
  mkdir -p thumbnails
  convert images/photo.jpg -resize 400x400 -quality 85 thumbnails/photo.webp

Returns: thumbnails/photo.webp.

4. Python pandas - filter/aggregate a CSV

input_files: ["data/sales.csv"]
language: python
code: |
  import pandas as pd
  df = pd.read_csv('data/sales.csv')
  q4 = df[df['quarter'] == 'Q4'].groupby('region')['amount'].sum().reset_index()
  q4.to_csv('data/sales_q4.csv', index=False)
  print(q4.to_string(index=False))

Returns: data/sales_q4.csv plus a printed preview on stdout.

5. Python matplotlib - chart a JSON metric series → PNG

input_files: ["data/metrics.json"]
language: python
code: |
  import json, os
  import matplotlib
  matplotlib.use('Agg')
  import matplotlib.pyplot as plt
  d = json.load(open('data/metrics.json'))
  os.makedirs('charts', exist_ok=True)
  plt.plot(d['labels'], d['values'])
  plt.xticks(rotation=45); plt.tight_layout()
  plt.savefig('charts/metrics.png', dpi=120)

Returns: charts/metrics.png (inline in the reply).

6. Bash + poppler - PDF → plain text

input_files: ["docs/manual.pdf"]
language: bash
code: |
  mkdir -p docs
  pdftotext -layout docs/manual.pdf docs/manual.txt
  wc -l docs/manual.txt

Returns: docs/manual.txt plus the line count on stdout.

7. qrencode - QR code for a deployed URL → PNG in the app

When the user asks for a QR code to a deployed app/URL (e.g. "stick a QR code on the front desk"), actually generate the image - don't hand back the URL and tell them to make one themselves.

language: bash
code: |
  mkdir -p src/images
  qrencode -o src/images/qr.png -s 10 -m 2 "https://app.gipity.ai/acme/front-desk/"

Returns: src/images/qr.png, saved into the app's src/ so it deploys with the site and is ready to print. Embed it on the page (<img src="images/qr.png">) if they want it shown in-app, and tell the user the file path. (-s sets pixel size per module, -m the quiet-zone margin.)

Audio/Music Generation - use dedicated tools

Do NOT use code_execute with sox/ffmpeg to generate music or sound effects. Use:

These produce higher-quality results and handle file saving automatically.