Table of Contents
An Agent Skill can contain more than instructions. When a workflow needs repeatable parsing, validation, conversion, or automation, place tested executables in a scripts/ directory and describe exactly when and how the agent should run them from SKILL.md. The goal is a predictable interface, not a collection of unexplained shell commands.
Choose between a one-off command and a packaged script
Use a one-off package command when a maintained tool already performs a small, well-defined job. For example:
uvx ruff@0.8.0 check .
npx eslint@9.0.0 .

Pin the tool version when reproducibility matters, state runtime prerequisites, and explain which files the command reads or changes. Package managers may download and execute third-party code, so use trusted sources and account for network-restricted environments.
Move the logic into scripts/ when the command becomes difficult to quote correctly, has multiple steps, needs tests, or will be reused. A practical layout is:
example-skill/
??? SKILL.md
??? scripts/
? ??? validate.sh
? ??? process.py
??? references/
??? format.md
Document every script in SKILL.md
List the purpose, inputs, outputs, prerequisites, side effects, and a minimal example for each executable. Do not make the agent infer an interface by opening a long source file.
## Available scripts
- scripts/validate.sh
Validates one configuration file. Writes diagnostics to stderr.
- scripts/process.py
Reads an input file and writes JSON to stdout.
## Workflow
1. Validate the input:
bash scripts/validate.sh "$INPUT_FILE"
2. Process valid input:
python3 scripts/process.py --input "$INPUT_FILE" --format json
The open Agent Skills scripting guidance uses paths relative to the skill folder. Confirm how the target agent runtime sets its working directory; if the platform exposes an explicit skill-directory variable, prefer it when a script must work regardless of the caller's current directory.
Create self-contained Python scripts with PEP 723
PEP 723 metadata lets a Python script declare its interpreter requirement and dependencies inside the file. A compatible runner such as uv can create an isolated environment and resolve those dependencies when the script runs.

# /// script
# requires-python = ">=3.11"
# dependencies = [
# "beautifulsoup4>=4.12,<5",
# ]
# ///
from bs4 import BeautifulSoup
html = '<p class="info">This is a test.</p>'
text = BeautifulSoup(html, "html.parser").select_one("p.info").get_text()
print(text)
Run it with:
uv run scripts/extract.py
Use bounded version ranges or a script lock file when repeatability is important. Inline metadata makes dependencies visible, but it does not remove the need to review packages, licenses, install behavior, and network access.
Design a script for agent execution
Never depend on an interactive prompt
Agents commonly run commands in noninteractive shells. A prompt for a password, confirmation, menu choice, or TTY input can hang the workflow. Accept required values through named flags, environment variables, files, or standard input, and fail immediately when a required value is missing.
$ python3 scripts/deploy.py
error: --env is required; choose development, staging, or production
usage: deploy.py --env ENV --tag TAG [--dry-run]
Make --help complete and concise
The help text should explain the command, arguments, defaults, output format, side effects, and at least one example:
usage: process.py [OPTIONS] INPUT_FILE
Validate input and emit a summary.
options:
--format {json,csv,tsv} output format; default: json
--output FILE write data to FILE
--limit N maximum records to emit
--verbose write progress details to stderr
--help show this message
example:
python3 scripts/process.py data.csv --format json --output report.json
Return output that another tool can parse
Send the primary result to standard output in a documented format such as JSON, CSV, or TSV. Send progress messages and diagnostics to standard error so they do not corrupt the result stream.
{"name":"my-service","status":"running","created":"2025-01-15"}
For large results, default to a summary or require an output file. Support controls such as --limit, --offset, or pagination so an agent does not lose important data when its tool output is truncated.
Use meaningful errors and exit codes
State what failed, show the rejected value, and tell the caller what is accepted. Reserve exit code 0 for success and document nonzero codes when callers need to distinguish invalid input, missing files, validation failures, and unavailable dependencies.
Build in safe retry behavior
- Idempotency: rerunning the same command should not create duplicate records or compound an edit unexpectedly.
- Dry runs: stateful or destructive scripts should provide a preview that reports intended changes without applying them.
- Explicit targets: require precise file, project, account, or environment arguments instead of guessing.
- Safe defaults: do not overwrite, delete, deploy, or publish unless the documented workflow clearly requests it.
- Atomic writes: write to a temporary file and replace the destination only after validation when possible.
- Timeouts: bound network requests and long-running subprocesses, and report which step timed out.
- Secret handling: read credentials from the platform's approved secret mechanism; never print them or embed them in SKILL.md.
Test the interface, not just the happy path
Test valid input, missing arguments, malformed files, unavailable dependencies, empty results, reruns, partial failures, and output-size limits. Include representative fixtures that contain spaces and unusual characters in filenames. Run static checks where appropriate and verify that --help works without installing optional services.
Skills and their scripts should be reviewed like source code. TipsMake's overview of OpenCode plugins and reusable skills explains why installation source, permissions, network destinations, and credential access deserve the same scrutiny as other executable dependencies. For workflows that call external services, the guide to web APIs for AI developers provides additional integration context.
Pre-release checklist
- Every packaged script is listed in SKILL.md with a copyable example.
- Runtime and dependency versions are explicit.
- No command waits for interactive input.
- Output and diagnostics use separate, documented channels.
- Errors are actionable and exit codes are consistent.
- Retries, dry runs, and destructive operations behave safely.
- Large results are bounded or written to a file.
- Tests cover invalid input and partial failure, not only success.
Reader Comments 0
Sign in with email or Google to join the discussion.