Cron Mode: execute_code Blocked
Why It's Blocked
execute_code runs arbitrary local Python, including subprocess calls that can bypass shell-string approval checks. In cron jobs, no user is present to approve these calls, so the tool is denied for safety.
Error Signature
When blocked, you see:
BLOCKED: execute_code runs arbitrary local Python (including subprocess calls that bypass shell-string approval checks). Cron jobs run without a user present to approve it. Use normal tools instead, or set approvals.cron_mode: approve only if this cron profile is intentionally trusted.
Note on approvals.cron_mode: The error message mentions this as a configuration option that could potentially enable execute_code in cron mode. However, this requires explicit user configuration of the cron profile as "intentionally trusted." Do NOT attempt to work around the block by trying different Python code — the restriction is at the tool-policy level, not the code level. If the user wants execute_code enabled in cron, they must configure it explicitly; the agent cannot and should not bypass this.
Workaround Patterns
Common Trigger: Batching su Commands via subprocess
A frequent anti-pattern that triggers this block is attempting to use execute_code to run multiple su -c shell commands through Python's subprocess module:
# This WILL be blocked in cron mode:
def su_run(cmd):
full_cmd = f"su -c '{cmd}'"
subprocess.run(full_cmd, shell=True, capture_output=True, text=True)
# Then calling it repeatedly in a Python script:
su_run("ls /sdcard/VisualAgent/commands/")
su_run("cat /sdcard/VisualAgent/commands/cmd.json")
su_run("screencap -p /sdcard/result.png")
Why this is blocked: The subprocess call with shell=True bypasses the shell-string approval mechanism. Even though each individual command is benign, the execute_code tool cannot verify this without running the code, which is exactly what the cron safety guard prevents.
The fix: Replace the Python subprocess wrapper with direct terminal tool calls, one per operation. The terminal tool's shell-string approval mechanism can inspect each command individually and approve safe ones.
Workaround Patterns
Pattern 1: Terminal + Shell Commands (Recommended for Simple Tasks)
Use terminal with su -c for each operation:
# Check for commands
su -c 'ls -la /sdcard/VisualAgent/commands/'
# Read a command file
su -c 'cat /sdcard/VisualAgent/commands/cmd_001.json'
# Execute screenshot
su -c 'screencap -p /sdcard/VisualAgent/results/screenshot.png'
# Execute tap
su -c 'input tap 500 1000'
# Write result
su -c 'echo "{\"status\":\"success\"}" > /sdcard/VisualAgent/results/result.json'
Pattern 2: Direct MCP Tools (Recommended for UI Operations)
Use Hermes Android phone tools directly instead of shell commands:
mcp_android_phone_screenshot— captures screen via MCPmcp_android_phone_tap— taps coordinatesmcp_android_phone_swipe— swipes screenmcp_android_phone_input_text— types textmcp_android_phone_open_app— launches app
These are safer and don't require execute_code.
Pattern 3: Shell + Python One-Liners (For JSON Parsing)
When you need JSON parsing in shell, use python3 -c:
# Extract command type from JSON
su -c 'python3 -c "import json; print(json.load(open(\"/sdcard/VisualAgent/commands/cmd.json\")).get(\"type\"))"'
# Parse and execute based on type
su -c 'python3 -c "
import json, subprocess, sys
cmd = json.load(open(\"/sdcard/VisualAgent/commands/cmd.json\"))
t = cmd.get(\"type\", \"\")
if t == \"screenshot\":
subprocess.run([\"screencap\", \"-p\", \"/sdcard/VisualAgent/results/screenshot.png\"])
"'
Note: This is still a shell command, not execute_code. The Python runs in a single -c string.
However, even python3 -c via terminal may fail in cron if the command string is complex (contains quotes, newlines, or multiple statements). The terminal tool may also be blocked for long or complex shell strings in cron mode. Test with a simple one-liner first; if it fails, fall back to Pattern 4.
Pattern 4: Hybrid — MCP Tools for Execution, Terminal for File I/O (Most Reliable in Cron)
For the VisualAgent pattern, use MCP tools for UI operations and terminal for file management:
terminalto list command files:su -c 'ls /sdcard/VisualAgent/commands/'terminalto read command:su -c 'cat /sdcard/VisualAgent/commands/cmd.json'- MCP tool to execute (e.g.,
mcp_android_phone_screenshot) terminalto write result:su -c 'echo "..." > /sdcard/VisualAgent/results/result.json'
What NOT to Do
- ❌ Don't try to use
execute_codewithsubprocessin cron — it will be blocked - ❌ Don't write a Python script to a file and try to run it via
execute_code - ❌ Don't attempt to bypass the block with creative workarounds — use the approved patterns above
- ❌ Don't try to use
execute_codefor complex multi-step logic with loops/conditionals — break it into separateterminalcalls instead
When execute_code IS Available
execute_code works normally in interactive sessions (when a user is present). The block only applies to cron jobs and other non-interactive contexts where no user can approve potentially dangerous operations.
Real-World Recovery Example
If you accidentally try execute_code and get blocked:
- Recognize the error — "BLOCKED: execute_code runs arbitrary local Python..."
- Stop — don't try again or look for workarounds
- Switch to Pattern 4 (Hybrid) — use
terminalfor file I/O and MCP tools for UI execution - For JSON parsing — use
python3 -cviaterminalorjqif available
Example recovery from a blocked VisualAgent service attempt:
# Was going to do this (BLOCKED):
# execute_code with Python script that loops, parses JSON, calls subprocess
# Instead do this:
terminal: "su -c 'ls -la /sdcard/VisualAgent/commands/'"
# → see files, identify commands
terminal: "su -c 'cat /sdcard/VisualAgent/commands/cmd.json'"
# → read command content
mcp_android_phone_screenshot: {path: "/sdcard/VisualAgent/results/screenshot.png"}
# → execute screenshot via MCP
terminal: "su -c 'echo \"{\\"status\\":\\"success\\"}\" > /sdcard/VisualAgent/results/result.json'"
# → write result