Dependencies
Your tool can use third-party libraries. You declare them in a standard manifest at the root of your repo — requirements.txt for Python, package.json for JavaScript — and the sandbox installs them for you. There's no separate "add a library" step: the file is the source of truth.
This page covers both languages and exactly when installation happens. For where these files live in your repo, see Entry point; for editing them, see the IDE.
Python — requirements.txt
Put a requirements.txt next to your main.py. It uses the normal pip format, one package per line:
requests==2.32.3
pandas>=2.0
Pillow
The sandbox creates a dedicated virtual environment for your tool (using uv under the hood) and installs everything in requirements.txt into it. You never manage the venv yourself — just edit the file. Import the packages in main.py as usual:
import requests
def process(input, settings):
r = requests.get(input["url"])
return { "status": r.status_code }
The
artifuncsSDK (get_file_content,log, …) is pre-installed in every Python tool. Don't add it torequirements.txt— it's always available.
JavaScript — package.json
Put a package.json at the repo root and list packages under dependencies:
{
"name": "my-tool",
"type": "module",
"dependencies": {
"lodash": "^4.17.21",
"date-fns": "3.6.0"
}
}
The sandbox installs them with pnpm into a node_modules folder next to your index.js. Require/import them as normal:
import { chunk } from 'lodash'
export function process(input, settings) {
return { batches: chunk(input.items, settings.size) }
}
Logging is provided via
require('artifuncs-log')— it's injected by the sandbox, so don't add it topackage.json.
When dependencies are installed
Installation is automatic, but it's worth knowing the timing so first runs don't surprise you:
| When | What happens |
|---|---|
| First run after deploy | The sandbox does a full install of everything in your manifest. Dependency-heavy tools can take a few seconds (or longer) the first time. |
| Later runs | The installed environment is reused — install is skipped entirely, so runs are fast. |
You edit requirements.txt / package.json in the IDE | Saving the file triggers a reinstall of just the dependencies (the venv / node_modules isn't rebuilt from scratch). You'll see install output in the log panel and a success or error toast. |
The decision to install vs. skip is based purely on whether the environment already exists — there's no per-package change tracking. Editing the manifest is what forces a refresh.
Pinning versions
You can use any version specifier your package manager understands:
# requirements.txt
numpy==1.26.4 # exact — recommended for published tools
httpx>=0.27 # minimum
scipy # latest at install time
// package.json
"dependencies": {
"zod": "3.23.8", // exact
"axios": "^1.7.0" // compatible range
}
Pin exact versions before you publish. A published tool is installed fresh in each visitor's sandbox; an unpinned dependency can resolve to a newer, breaking release later and silently change how your tool behaves.
Any package?
There's no allowlist on libraries — you can install anything published to PyPI (Python) or the npm registry (JavaScript). Packages are downloaded from those registries when your tool is set up.
This is separate from network access at runtime. Once your tool is running, the sandbox blocks outbound network except for the external APIs you declare under apis in artifuncs.json. So a library installs fine, but if it tries to reach a service over the network while your tool runs, that call is blocked unless the domain is allowlisted.
When an install fails
If a package name is misspelled, a pinned version doesn't exist, or the registry can't be reached, the install fails and the uv / pnpm error is streamed to the log panel (and shown as a toast in the IDE). The tool won't run until the manifest is fixed — correct the file and save again to retry.