
Alibabacloud Agentbay Aio Skills
- 112 installs
- 208 repo stars
- Updated August 4, 2026
- aliyun/alibabacloud-aiops-skills
AgentBay AIO is a Claude Code skill that executes user code in a secure remote Alibaba Cloud sandbox via the AgentBay SDK.
About
AgentBay AIO is a skill that runs user code in a secure remote Alibaba Cloud sandbox via the AgentBay SDK instead of on the local machine. A developer uses it whenever they ask the agent to run, execute, plot, or evaluate code in Python, JavaScript, R, or Java. It handles sandbox creation, execution, and result parsing through a single entry script and validates downloaded files like chart images.
- Executes Python, JavaScript, R, and Java in a remote sandbox, never locally
- Handles chart plotting with automatic CJK font configuration for matplotlib
- 60-second execution timeout with structured JSON output mode
Alibabacloud Agentbay Aio Skills by the numbers
- 112 all-time installs (skills.sh)
- Ranked #548 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
alibabacloud-agentbay-aio-skills capabilities & compatibility
Requires an AgentBay API key from the AgentBay Console; sandbox usage billed by Alibaba Cloud.
- Capabilities
- data analysis
- Use cases
- data analysis
- Platforms
- macOS · Linux · Windows
- Pricing
- Bring your own API key
What alibabacloud-agentbay-aio-skills says it does
This skill runs user code in a remote sandbox (not locally) via AgentBay SDK.
Supported languages: `python`, `javascript`, `r`, `java` (case-insensitive). Timeout: 60 seconds max (`--timeout-s`).
npx skills add https://github.com/aliyun/alibabacloud-aiops-skills --skill alibabacloud-agentbay-aio-skillsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 112 |
|---|---|
| repo stars | ★ 208 |
| Last updated | August 4, 2026 |
| Repository | aliyun/alibabacloud-aiops-skills ↗ |
What it does
Run or evaluate user code (Python, JS, R, Java) in a secure remote Alibaba Cloud AgentBay sandbox instead of locally.
Who is it for?
Running or evaluating untrusted or ad-hoc code and plotting charts without executing anything on the local machine.
Skip if: Tasks the agent should run directly in the local terminal; the skill forbids local execution as a fallback.
When should I use this skill?
The user asks to run, execute, or evaluate code, plot with Python, or run data analysis.
What you get
User code runs in an isolated cloud sandbox with parsed results and validated file downloads.
By the numbers
- 4 supported languages (python/javascript/r/java)
- 60-second max timeout
Files
AgentBay AIO Skill
How It Works
This skill runs user code in a remote sandbox (not locally) via AgentBay SDK. The entry script scripts/run_code.py handles sandbox creation, code execution, and result parsing automatically.
# Basic execution
python scripts/run_code.py --code "<user_code>" --language python
# Execute from file
python scripts/run_code.py --code-file /path/to/file.py --language python
# Structured JSON output (use this when writing results to files)
python scripts/run_code.py --code "<user_code>" --language python --jsonSupported languages: python, javascript, r, java (case-insensitive). Timeout: 60 seconds max (--timeout-s).
Prerequisites
| Dependency | Version | Purpose |
|---|---|---|
| Python | >= 3.8 | Runtime |
| wuying-agentbay-sdk | >= 1.0.0 | AgentBay SDK for sandbox code execution |
Setup
The script requires wuying-agentbay-sdk installed locally. Install it before first use:
pip install wuying-agentbay-sdkThis is the skill's own required dependency — installing it is not a security concern. If run_code.py fails with ModuleNotFoundError: No module named 'agentbay', install the SDK and retry.
Network domains used: agentbay.aliyuncs.com (API endpoint), agentbay.console.aliyun.com (console), mirrors.aliyun.com (PyPI mirror).
API Key Configuration
Run scripts directly without prompting for API Key configuration. Only guide users when the script explicitly reports "Missing API key":
1. Apply at AgentBay Console 2. Save to config file: ~/.config/agentbay/api_key (macOS/Linux) or %USERPROFILE%\.config\agentbay\api_key (Windows)
Execution Rules
CRITICAL: All user code MUST run through scripts/run_code.py — NEVER execute code directly in the local terminal (e.g., python -c, node -e, timeout ... python). This applies even if run_code.py fails on the first attempt.
- If
run_code.pyfails with a transient error, retry once before reporting failure. - If
run_code.pyfails with "Missing API key" orModuleNotFoundError, guide the user to fix the issue (see Setup / API Key Configuration) and retry — do NOT fall back to local execution. - NEVER run user code locally as a fallback. Report the error instead.
Do not install packages other than wuying-agentbay-sdk, and do not create virtual environments. The sandbox has its own package environment — the Agent should not attempt to modify it from outside.
Output Handling
Standard output: Exit code 0 = success, results in stdout. Non-zero = failure, error in stderr.
Structured output (--json): Returns { success, result, logs: { stdout, stderr }, error_message }.
Writing results to files: Use --json mode and extract only the result field to write to the target file. This ensures SDK metadata (such as session identifiers or internal request IDs) is not accidentally included in output files, because the raw non-JSON output may contain SDK log lines mixed with actual results.
Reporting results: Quote the script's original output directly. Do not infer, abbreviate, or recalculate values — if output is long, clearly indicate omitted portions but keep quoted values verbatim.
File Download Validation
When saving files generated in the sandbox (e.g., chart images) to the local environment:
1. Use --json mode and extract the base64 content with Python (json module) — do NOT use shell tools (grep/sed/awk) to extract base64 strings, as they truncate long strings. 2. Decode with: python -c "import base64,json,sys; d=json.load(sys.stdin); open('out.png','wb').write(base64.b64decode(d['result']))" < output.json 3. Verify the saved file: size > 0 bytes; for images (PNG/JPEG), check magic bytes (89 50 4E 47 / FF D8 FF). 4. For chart images, file size should be > 5 KB. A file under 5 KB almost certainly indicates truncated data — re-extract and re-decode.
If verification fails, retry the download. Do not report success with a corrupted file.
Chinese/CJK Character Rendering
The script (run_code.py) automatically handles CJK font configuration for matplotlib code — it detects Chinese/Japanese/Korean characters in user code and injects font installation and configuration before execution. No manual font setup is needed.
When the user's code contains Chinese characters AND uses matplotlib/plt, the Agent should proactively prepend the following font installation block in the --code argument on the first execution (not as a retry), because the sandbox may lack CJK fonts and the script's auto-detection provides a safety net but explicit installation is more reliable:
import subprocess
subprocess.run(['apt-get', 'update', '-qq'], capture_output=True)
subprocess.run(['apt-get', 'install', '-y', '-qq', 'fonts-wqy-microhei'], capture_output=True)
import matplotlib
import matplotlib.font_manager as fm
fm.fontManager.addfont('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc')
fm.fontManager = fm.FontManager()
matplotlib.rcParams['font.family'] = 'WenQuanYi Micro Hei'
matplotlib.rcParams['axes.unicode_minus'] = FalseThis proactive approach avoids the undetectable failure where Chinese characters render as blank boxes (tofu) in the generated image — since tofu appears only visually in the image and produces no text-based warning in stdout, a retry-based approach cannot reliably detect the problem.
Information Security
Do not output internal environment variable names, API Key values, or SDK debug details in conversation replies. When executing scripts, use --json mode and display only the result and error_message fields to users. The raw SDK output may contain internal fields (session identifiers, request IDs, access credentials) that should not be exposed to users or written to output files.
#!/usr/bin/env python3
# requires: wuying-agentbay-sdk>=1.0.0
import argparse
import asyncio
import base64
import json
import os
import sys
import time
from agentbay import AsyncAgentBay, CreateSessionParams
def _api_key_config_path() -> str:
"""Return the API key config file path for the current platform."""
home = os.path.expanduser("~")
if sys.platform == "win32":
# Windows: %USERPROFILE%\.config\agentbay\api_key
base = os.environ.get("USERPROFILE", home)
return os.path.join(base, ".config", "agentbay", "api_key")
# Unix-like: $XDG_CONFIG_HOME/agentbay/api_key or ~/.config/agentbay/api_key
xdg = os.environ.get("XDG_CONFIG_HOME") or os.path.join(home, ".config")
return os.path.join(xdg, "agentbay", "api_key")
def _read_api_key_from_config() -> str:
"""Read API key from config file if present. Returns empty string if not found or on error."""
path = _api_key_config_path()
try:
if os.path.isfile(path):
with open(path, "r", encoding="utf-8") as f:
return (f.read() or "").strip()
except OSError:
pass
return ""
def _load_code(args: argparse.Namespace) -> str:
if args.code and args.code_file:
raise ValueError("Use only one of --code or --code-file.")
if args.code:
return args.code
if args.code_file:
# Security: Validate code-file path is within current working directory
cwd = os.getcwd()
abs_code_file = os.path.abspath(args.code_file)
# Resolve symlinks to prevent directory traversal attacks
abs_code_file = os.path.realpath(abs_code_file)
if not abs_code_file.startswith(cwd + os.sep) and abs_code_file != cwd:
raise ValueError(
f"Security error: --code-file must be within current working directory. "
f"Current directory: {cwd}, Requested file: {abs_code_file}"
)
with open(abs_code_file, "r", encoding="utf-8") as f:
return f.read()
raise ValueError("Either --code or --code-file is required.")
async def main() -> int:
parser = argparse.ArgumentParser(
description="Run code in AgentBay code_latest sandbox via run_code."
)
parser.add_argument(
"--api-key",
default=os.environ.get("AGENTBAY_API_KEY", ""),
help="AgentBay API key (or set AGENTBAY_API_KEY).",
)
parser.add_argument(
"--language",
default="python",
choices=["python", "javascript", "r", "java"],
help="Language for run_code (python/javascript/r/java).",
)
parser.add_argument(
"--timeout-s",
type=int,
default=60,
help="Execution timeout in seconds (<= 60).",
)
parser.add_argument("--code", help="Inline code to execute.")
parser.add_argument(
"--code-file",
help="Path to a file containing code to execute (must be within current working directory).",
)
parser.add_argument(
"--json",
action="store_true",
help="Print structured JSON output.",
)
args = parser.parse_args()
# Validate timeout-s parameter (must be <= 60)
if args.timeout_s > 60:
print("Error: --timeout-s must be <= 60 seconds.", file=sys.stderr)
return 2
if args.timeout_s <= 0:
print("Error: --timeout-s must be > 0 seconds.", file=sys.stderr)
return 2
if not args.api_key:
args.api_key = _read_api_key_from_config()
if not args.api_key:
path = _api_key_config_path()
print(
f"Missing API key. Apply for an API key at the AgentBay console:\n"
f" https://agentbay.console.aliyun.com/service-management\n"
f"Then save it to the local config file: {path}\n"
f"(Alternatively, set the AGENTBAY_API_KEY environment variable.)",
file=sys.stderr,
)
return 2
try:
code = _load_code(args)
except ValueError as exc:
print(str(exc), file=sys.stderr)
return 2
# For Python matplotlib code, add preamble to ensure proper backend configuration
if args.language.lower() == "python" and ("matplotlib" in code or "plt." in code):
# Always inject CJK font configuration, regardless of user code content.
# Split into two parts: backend setup and CJK font config.
# This ensures CJK fonts are configured even if user code already sets Agg backend.
backend_preamble = """
import matplotlib
matplotlib.use('Agg') # Use non-interactive backend
"""
# Detect if user code contains CJK characters (Chinese/Japanese/Korean)
import re as _re_cjk
_has_cjk_chars = bool(_re_cjk.search(r'[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]', code))
# If CJK characters detected, add font installation as a safety net
cjk_install_preamble = ""
if _has_cjk_chars:
cjk_install_preamble = """
import subprocess as _sp
import os as _os
# Proactively install CJK fonts if not already available
_font_paths = ['/usr/share/fonts/truetype/wqy/wqy-microhei.ttc',
'/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc']
if not any(_os.path.exists(p) for p in _font_paths):
_sp.run(['apt-get', 'update', '-qq'], capture_output=True, timeout=30)
_sp.run(['apt-get', 'install', '-y', '-qq', 'fonts-wqy-microhei'], capture_output=True, timeout=60)
"""
cjk_font_preamble = """
import matplotlib
import matplotlib.font_manager as fm
import os as _os
import glob as _glob
# Auto-configure CJK font for Chinese/Japanese/Korean character rendering
_cjk_font_names = ['WenQuanYi Micro Hei', 'WenQuanYi Zen Hei', 'Noto Sans CJK SC',
'Noto Sans CJK', 'Noto Sans CJK JP', 'Noto Sans CJK KR',
'SimHei', 'Microsoft YaHei', 'PingFang SC',
'Source Han Sans SC', 'AR PL UMing CN', 'Droid Sans Fallback']
# Try to add font files directly if they exist
_font_dirs = ['/usr/share/fonts/truetype/wqy', '/usr/share/fonts/opentype/noto',
'/usr/share/fonts/truetype', '/usr/local/share/fonts']
for _fd in _font_dirs:
if _os.path.isdir(_fd):
for _ff in _glob.glob(_os.path.join(_fd, '**', '*.tt[cf]'), recursive=True):
try:
fm.fontManager.addfont(_ff)
except Exception:
pass
for _ff in _glob.glob(_os.path.join(_fd, '**', '*.otf'), recursive=True):
try:
fm.fontManager.addfont(_ff)
except Exception:
pass
# Clear matplotlib font cache and rebuild from scratch for reliability
_cache_dir = matplotlib.get_cachedir()
if _cache_dir and _os.path.isdir(_cache_dir):
for _cf in _glob.glob(_os.path.join(_cache_dir, 'fontlist-*')):
try:
_os.remove(_cf)
except Exception:
pass
try:
fm.fontManager = fm.FontManager()
except Exception:
pass
_available_cjk = [f.name for f in fm.fontManager.ttflist
if any(c in f.name for c in _cjk_font_names) or 'CJK' in f.name]
if _available_cjk:
matplotlib.rcParams['font.sans-serif'] = list(dict.fromkeys(_available_cjk)) + ['DejaVu Sans']
else:
matplotlib.rcParams['font.sans-serif'] = ['DejaVu Sans']
matplotlib.rcParams['axes.unicode_minus'] = False
"""
imports_preamble = """
import matplotlib.pyplot as plt
import base64
from io import BytesIO
"""
# Strip any existing matplotlib font/backend config from user code to avoid conflicts
import re as _re
# Remove user's own matplotlib.use(...) calls to avoid double-setting
code = _re.sub(r"""matplotlib\.use\(['"][^'"]*['"]\)""", '# (backend set by runner)', code)
# Remove user's own rcParams font settings to avoid overriding our CJK config
code = _re.sub(r"""matplotlib\.rcParams\[['"]font\.sans-serif['"]\]\s*=.*""", '# (font set by runner)', code)
code = _re.sub(r"""matplotlib\.rcParams\[['"]axes\.unicode_minus['"]\]\s*=.*""", '# (unicode_minus set by runner)', code)
code = _re.sub(r"""plt\.rcParams\[['"]font\.sans-serif['"]\]\s*=.*""", '# (font set by runner)', code)
code = _re.sub(r"""plt\.rcParams\[['"]axes\.unicode_minus['"]\]\s*=.*""", '# (unicode_minus set by runner)', code)
code = cjk_install_preamble + backend_preamble + cjk_font_preamble + imports_preamble + code
# If the code doesn't have savefig, automatically save the plot
if "plt.savefig" not in code and "savefig" not in code:
# Add code to save the last plot automatically
auto_save_code = """
# Automatically save the last plot if no savefig was called
if plt.get_fignums():
buf = BytesIO()
plt.savefig(buf, format='png', dpi=100, bbox_inches='tight')
buf.seek(0)
img_base64 = base64.b64encode(buf.read()).decode('utf-8')
print(f"[AGENTBAY_CHART_BASE64:{img_base64}]")
plt.close()
"""
code = code + auto_save_code
try:
agent_bay = AsyncAgentBay(api_key=args.api_key, user_agent='AlibabaCloud-Agent-Skills/alibabacloud-agentbay-aio-skills')
except TypeError:
agent_bay = AsyncAgentBay(api_key=args.api_key)
session_result = await agent_bay.create(CreateSessionParams(image_id="code_latest"))
try:
code_result = await session_result.session.code.run_code(
code, args.language, timeout_s=args.timeout_s
)
if args.json:
payload = {
"success": code_result.success,
"result": code_result.result,
"logs": {
"stdout": code_result.logs.stdout,
"stderr": code_result.logs.stderr,
},
"error_message": code_result.error_message,
}
print(json.dumps(payload, ensure_ascii=True))
else:
if code_result.success:
# First, check for AGENTBAY_CHART_BASE64 marker in stdout or result
stdout_content = "".join(code_result.logs.stdout) if code_result.logs.stdout else ""
result_content = code_result.result or ""
combined_output = stdout_content + result_content
# Check for our custom marker [AGENTBAY_CHART_BASE64:...]
import re
chart_match = re.search(r'\[AGENTBAY_CHART_BASE64:([A-Za-z0-9+/=]+)\]', combined_output)
if chart_match:
try:
img_base64 = chart_match.group(1)
img_bytes = base64.b64decode(img_base64)
timestamp = int(time.time())
filename = f"chart_{timestamp}.png"
with open(filename, "wb") as f:
f.write(img_bytes)
print(f"Successfully saved {filename} ({len(img_bytes)} bytes)")
# Remove the marker from output
combined_output = combined_output.replace(chart_match.group(0), "")
except Exception as e:
print(f"Error saving auto-captured chart: {e}", file=sys.stderr)
# Check for rich output in results
if hasattr(code_result, 'results') and code_result.results:
for res in code_result.results:
# Handle Images (PNG, JPEG, SVG)
img_data = None
ext = ""
if hasattr(res, 'png') and res.png:
img_data = res.png
ext = "png"
elif hasattr(res, 'jpeg') and res.jpeg:
img_data = res.jpeg
ext = "jpg"
elif hasattr(res, 'svg') and res.svg:
img_data = res.svg
ext = "svg"
if img_data:
try:
timestamp = int(time.time())
filename = f"chart_{timestamp}.{ext}"
if ext == "svg":
with open(filename, "w", encoding="utf-8") as f:
f.write(img_data)
print(f"Successfully saved {filename}")
else:
if isinstance(img_data, str):
img_bytes = base64.b64decode(img_data)
else:
img_bytes = img_data
with open(filename, "wb") as f:
f.write(img_bytes)
print(f"Successfully saved {filename} ({len(img_bytes)} bytes)")
except Exception as e:
print(f"Error saving image: {e}", file=sys.stderr)
# For matplotlib charts, also check if the code contains plt.savefig or savefig
# and verify if the file was created in the sandbox
if args.language.lower() == "python" and ("plt.savefig" in code or "savefig" in code):
# Try to extract saved file info from stdout or result
stdout_content = "".join(code_result.logs.stdout) if code_result.logs.stdout else ""
result_content = code_result.result or ""
# Check if there's any indication of file saving
if "saved" in stdout_content.lower() or "saved" in result_content.lower():
print("\nChart saved successfully.")
else:
# If matplotlib was used but no explicit savefig, try to save the plot
# This is a fallback for cases where the user didn't call savefig
if "plt.show()" in code or ("plt.plot" in code and "plt.savefig" not in code):
print("\nNote: The matplotlib chart was generated but not explicitly saved.")
print("To save the chart, please use plt.savefig('filename.png') in your code.")
# Continue with other rich output handling
if hasattr(code_result, 'results') and code_result.results:
for res in code_result.results:
# Handle HTML
if hasattr(res, 'html') and res.html:
print(f"\n[HTML Output]:\n{res.html}")
# Handle Markdown
if hasattr(res, 'markdown') and res.markdown:
print(f"\n[Markdown Output]:\n{res.markdown}")
# Handle LaTeX
if hasattr(res, 'latex') and res.latex:
print(f"\n[LaTeX Output]:\n{res.latex}")
# Handle JSON
if hasattr(res, 'json') and res.json:
print(f"\n[JSON Output]:\n{json.dumps(res.json, indent=2)}")
# Handle Chart Data
if hasattr(res, 'chart') and res.chart:
print(f"\n[Chart Data]:\n{json.dumps(res.chart, indent=2)}")
# Handle Text (if not main result, to avoid duplication)
if hasattr(res, 'text') and res.text and not getattr(res, 'is_main_result', False):
print(f"\n[Text Output]:\n{res.text}")
if code_result.result:
print(code_result.result)
if code_result.logs.stdout:
print("".join(code_result.logs.stdout), end="")
if code_result.logs.stderr:
print("".join(code_result.logs.stderr), end="", file=sys.stderr)
else:
print(code_result.error_message or "run_code failed", file=sys.stderr)
return 1
finally:
await session_result.session.delete()
return 0
if __name__ == "__main__":
raise SystemExit(asyncio.run(main()))
Related skills
FAQ
Which languages does AgentBay AIO support?
Python, JavaScript, R, and Java, case-insensitive, with a 60-second maximum timeout.
Does it ever run code locally?
No. It always runs code through the remote sandbox and never falls back to local execution.