Script skills: build, approve and use Python scripts in skills
AdminA script skill is a skill that ships its own Python script next to its instructions (SKILL.md). The assistant calls the script instead of doing the work itself: it reads your file locally, computes by fixed rules and stores the result as a file — for example a SEPA credit transfer file from a CSV payment list. The model only sees the short summary the script returns, not the data. How ordinary skills without a script work is described in Upload new skills via ZIP.
Prerequisites
Section titled “Prerequisites”-
Desktop app on macOS or Windows. On Windows, script skills are tested on Windows 11 (x64); the app also offers them on ARM64 devices, but they are not tested there yet. Known limits are listed below in the section “Windows specifics”. On Linux they are not offered; the app then shows “Script skills are not yet released on this operating system.” The web edition does not have them.
-
Pro license or higher (Pro or Site). In Free the app shows an upgrade notice instead.
-
Administrator role for uploading, approving and rebuilding.
-
uv is installed (Astral’s Python package manager). CompanyWizard does not ship uv. If it is missing, the Skills page shows the install command:
-
macOS:
curl -LsSf https://astral.sh/uv/install.sh | sh -
Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
-
-
Internet access for the one-off environment build:
github.com,objects.githubusercontent.comandrelease-assets.githubusercontent.com(Python interpreter) as well aspypi.organdfiles.pythonhosted.org(packages). If a firewall filters outbound traffic, allow these hosts.
Start with the sample
Section titled “Start with the sample”The sample SEPA transfers from CSV is a complete script skill that uses only the Python standard library:
- sepa-transfers.zip (approx. 5 KB)
It contains the skill, the script and the payment list example.csv with one deliberately invalid IBAN.
- Upload — on the Skills page choose Upload Skills (.zip) and select
sepa-transfers.zip. The skill appears in the catalog, but the script is not runnable yet. - Open the skill — select
sepa-transfersin the skill tree. Above the instructions, the Scripts area shows the scriptsepa_from_csvwith the status Not approved, its Version (short form of the checksum), its Packages (here: none) and No network access. - Approve — check the description, packages and network hosts, then Approve. Optionally tick In chat without confirmation; the confirmation dialog in chat is then skipped for this script.
- Wait for the environment — after approval CompanyWizard builds the Python environment: Environment: being built, then ready. Only then is the script offered.
- Use it in chat — put
example.csvinto a folder, attach that folder in chat as the working folder, enable the skillsepa-transfersin the session’s skill selection and write: “Create a SEPA file from example.csv, execution on 2026-11-02, ordering party Example Trading Ltd with IBAN DE02120300000000202051.” - Confirm — a dialog shows the script, parameters, input files and network access. After you confirm, the script runs. The answer names two payments, the total and the warning about the invalid IBAN in line 4; the file
sepa-2026-11-02.xmlis in the working folder.
Build your own script skill
Section titled “Build your own script skill”A script skill is a top-level folder in the ZIP:
my-skill/ SKILL.md instructions for the assistant: when and how to call the script skill-scripts.yaml manifest: scripts, parameters, inputs and outputs, network requirements.txt optional: packages with checksums scripts/*.py the scriptsThe manifest skill-scripts.yaml
Section titled “The manifest skill-scripts.yaml”This is how it looks in the sample:
python: "3.12"scripts: - name: sepa_from_csv description: "Creates a SEPA bulk credit transfer (pain.001.001.09) from a CSV payment list" entry: scripts/sepa_from_csv.py parameters: properties: execution_date: type: string pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" debtor_account: type: string pattern: "^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$" debtor_name: type: string required: [execution_date, debtor_account, debtor_name] inputs: { min: 1, max: 1, extensions: [".csv"], max_mb: 5 } outputs: { extensions: [".xml"] } timeout_seconds: 60 network: deny| Field | Meaning |
|---|---|
python | Python version that uv provides, e.g. "3.12". |
name, description | Name of the script and the description the assistant sees. |
entry | Path to the .py file, relative to the skill folder, without ... |
parameters | Parameters of type string, integer, number or boolean, optionally with a pattern; required lists the mandatory ones. CompanyWizard checks them before the start. |
inputs | Number (min, max), allowed extensions and size per file (max_mb, at most 200, which is also the default). |
outputs | Extensions of the files the script creates. |
timeout_seconds | Time limit, default 60, at most 3600. |
network | deny or allowlist:host1,host2 with plain host names. |
A secrets field is rejected. The Skills page shows manifest errors right after the upload (“These skills ship scripts that cannot be approved yet:”) and in the Scripts area under “Problems with the script manifest”.
What the script receives and must deliver
Section titled “What the script receives and must deliver”- Start: like
python scripts/<file>.pyin a fresh working directory, without stdin and without further arguments —input()does not work. Your own modules in the script folder can be imported as usual. - Input: the environment variable
CW_REQUESTpoints to arequest.jsonwith{"parameters": {…}, "inputs": ["in/…"]}. The input files are copies underin/. - Output: the script writes files to the folder in
CW_OUTPUT_DIR. - Result: on stdout it prints exactly one JSON object:
{"summary": "…", "warnings": […], "metrics": {…}, "files": […]}. Onlysummaryis mandatory. This is everything the assistant sees of the run. - Limits: stdout may be at most 64 KiB, otherwise the result is rejected.
summaryis cut after 4000 characters, each warning after 500. - Errors: an exit code other than 0 counts as an error. What the script writes to stderr never reaches the assistant; it only goes to the app’s log. So report domain problems as
warnings— the assistant passes them on to the user. - Environment variables: only
PATH,HOME,LANG,LC_*,TZ,TMPDIRplusCW_REQUESTandCW_OUTPUT_DIR; on Windows alsoSystemRoot,SystemDrive,windir,PATHEXT,COMSPEC,LOCALAPPDATA,TEMPandTMP. CompanyWizard’s credentials never reach the script.
Packages: requirements.txt with checksums
Section titled “Packages: requirements.txt with checksums”Without a requirements.txt only the standard library is available. If you need packages, generate the file with checksums:
uv pip compile requirements.in --generate-hashes -o requirements.txt- Every entry needs
--hash=sha256:…. If a checksum is missing, the manifest is rejected. - No option lines such as
--index-url,-eor-r; they are rejected too. What you see in the file is exactly what gets installed. - Wheels only. If a package exists only as a source distribution, the environment build fails with a note about the source package. Pick a version that has a wheel for your operating system.
Pack and upload
Section titled “Pack and upload”Pack the skill folder so that it is the top level of the ZIP and upload it as above. The assistant itself can neither create nor change script skills — they only enter the system through a ZIP upload.
Approval and version
Section titled “Approval and version”- An approval covers exactly the checked version. CompanyWizard computes a checksum over all files of the skill (excluding
__pycache__,__MACOSX,.DS_Store) and checks it before every start. If a file changes — a new upload, an edit —, the script shows “Changed since approval - approval pending” and only runs again after a new approval. - Same packages, same environment. Scripts with an identical
requirements.txtand Python version share one environment. - Rebuild environment discards the environment and builds it afresh, for example after you installed uv or when the build failed. While a script is running in that environment, this is refused.
- Revoke withdraws the approval; the script is no longer offered from then on.
Use it in chat
Section titled “Use it in chat”- The skill has to be active in the session’s skill selection. → Enable skills and use them in chat
- Input files come from the attached working folder or as a
kb:path from a knowledge area the user may read. - Result files land in the working folder, without a working folder in the desktop app’s output folder. An existing file is never overwritten. → Where does CompanyWizard save documents?
- Before every run the confirmation dialog appears — unless the script is approved In chat without confirmation. That is only possible for scripts without network hosts. In Plan mode the app always asks.
Use it in agents
Section titled “Use it in agents”- Open the agent, tab Tools. In the Skill scripts section, tick the approved scripts. This also switches on the tool
run_skill_script; if you later untick it in the tool list, the scripts are switched off for this agent. - In the same tab, set a working folder — a script reads input files only from this folder. For the SEPA sample, the CSV goes there.
- Optionally choose an Output folder for scripts. Empty means: the working folder. If the agent has a “Working folder” storage target (Scope tab), scripts write there — the target takes precedence over the output folder and is enough on its own for saving. Without a storage target and without either folder the agent cannot be saved (“Scripts need an output folder or a working folder for this agent.”). With a “Vault” storage target, scripts are not offered. → Chain agents
- Scripts with network hosts only run in the agent if Allow scripts with network access is ticked.
- Also enable the skill in the Skills tab so the agent knows the instructions from the
SKILL.md.
Agents run without a confirmation dialog and may not use kb: inputs. If a script cannot run, the reason appears at the start of the run’s summary: ”⚠ Scripts could not be run: …”.
Security: what a script sees
Section titled “Security: what a script sees”- Original data. A script works with the original files, not with pseudonymized data — that is its purpose. If it may use the network, it can send this data to its approved hosts. The Skills page and the agent point this out (“This script receives original data (not pseudonymized) and may send it to these hosts.”). Approving the hosts is your trust decision.
- Sandbox. Every run has its own working directory; the script may write only there. Network access exists only to the approved hosts.
- Read restriction. On macOS and Windows the script reads only its working directory, its Python environment and fixed system paths. On macOS it can tell that a file exists elsewhere, how large and how old it is — but it cannot read or list it.
- Environment build on Windows. On Windows, CompanyWizard builds the Python environment outside the sandbox, because uv cannot work inside it. The build only installs the packages from
requirements.txtwith their checksums and runs no code from the skill. Its network traffic goes through the app’s proxy, which steers and logs it but does not enforce it. On macOS the build also runs in the sandbox. - No virtual machine. As with the CLI tool, this is best-effort containment, not VM isolation. → Command-line tools (CLI) in the assistant — overview & limits
- At most two scripts run at the same time; further ones wait.
Windows specifics
Section titled “Windows specifics”- No
os.devnull. A script that usessubprocess.DEVNULLoropen(os.devnull)fails on Windows withPermissionError. Redirect output to a file in the working directory instead, or capture it withsubprocess.PIPE. - Network scripts on standard accounts. Scripts with network hosts have so far been tested only under a user account with administrator rights. Under a standard account such a script may fail because it cannot reach the app’s proxy. Scripts without network access are not affected.
When something goes wrong
Section titled “When something goes wrong”| Message | What to do |
|---|---|
| ”uv is not installed. …” | Install uv with the command shown, then Rebuild environment. |
| Environment: build failed | Read the reason shown: often a package without a wheel, or a firewall blocking the hosts from the prerequisites. Fix it, then Rebuild environment. |
| ”Changed since approval - approval pending” | The skill has changed. Review the changes and Approve again. |
| ”Script skills are not yet released on this operating system.” | Script skills run on macOS and Windows, not on Linux. |
| A script that runs on macOS stops on Windows | Look for PermissionError in the app’s log: often the script uses subprocess.DEVNULL or open(os.devnull), see “Windows specifics”. |
| ”The license has expired and is read-only. …” | Approving, rebuilding and running work again after renewal; revoking works at any time. |
| The script stops, the assistant names only an exit code | The error output (stderr) is in the app’s log. Better report domain problems as warnings. |