9.5 KiB
9.5 KiB
name, description, version, tags
| name | description | version | tags | |||
|---|---|---|---|---|---|---|
| cronjob | Create, manage, update, run, and troubleshoot Hermes Agent cronjobs — scheduling, scripts, prompts, delivery, and state management. | 1.0.0 |
|
Cronjob System
Core Concepts
Cronjobs can be of two types:
- Agent jobs — run via an agent with a prompt, model, and skills (use a
skillorskillsparameter) - Direct script jobs (
no_agent: true) — execute a shell/Python script directly
Script Jobs: THE CRITICAL PATH RULE
script parameter expects a FILENAME (relative to ~/.hermes/scripts/), NOT raw shell content.
This is the most common cronjob error. The system treats the script value as a path to a file under ~/.hermes/scripts/.
❌ WRONG: script: "cd ~/.hermes/memory\nCHANGES=$(git diff..." (raw multi-line content)
✅ RIGHT: script: "memory-sync.sh" (filename only)
Always create the script file first, then reference it:
# 1. Write the script
write_file path=~/.hermes/scripts/my-script.sh content='...'
# 2. Create the cronjob referencing the filename
cronjob action=create script=my-script.sh ...
Creating Cronjobs
# Agent job (runs via an AI agent with a prompt)
cronjob action=create \
name="My Job" \
prompt="You are a helper. Do X." \
schedule="0 9 * * *" \
repeat="forever" \
deliver="origin" \
model="custom/llama/model.gguf" \
skills="my-skill"
# Script job (runs a shell/Python script directly, no agent)
cronjob action=create \
name="My Script Job" \
script="my-script.sh" \
schedule="0 22 * * *" \
repeat="forever" \
deliver="origin" \
no_agent=true
Parameters
| Parameter | Description | Required |
|---|---|---|
name |
Human-readable job name | Yes |
prompt |
Instruction for agent (agent jobs) | Yes, unless no_agent |
script |
Filename in ~/.hermes/scripts/ (script jobs) |
Yes, if no_agent |
schedule |
Cron expression (e.g. "0 9 * * *") |
Yes |
repeat |
"forever", "13/500", "1/10" |
No (default: 1) |
deliver |
"origin" or telegram:<chat_id> |
No (default: origin) |
model |
Model ID for agent jobs | No |
provider |
Provider name | No |
base_url |
API base URL | No |
skills |
Space-separated skill names for agent | No |
no_agent |
true for direct script execution |
No |
Managing Cronjobs
# List all jobs
cronjob action=list
# Update a job (change any parameter)
cronjob action=update job_id=<ID> schedule="0 6 * * *"
# Pause a job (keep it but stop scheduling)
cronjob action=update job_id=<ID> schedule=never
# Resume a paused job
cronjob action=update job_id=<ID> schedule="0 6 * * *"
# Run a job immediately (one-shot)
cronjob action=run job_id=<ID>
# Delete a job
cronjob action=remove job_id=<ID>
Delivery Destinations
origin— delivers results to the current conversation threadtelegram:<chat_id>— delivers results directly to a Telegram chat (e.g., agent chat)
Prompt Design for Agent Jobs
The prompt must be fully self-contained — it runs without user context:
Du bist ein [role]. Deine Aufgabe: [specific task].
Schritt 1: [action]
Schritt 2: [action]
Schritt 3: [action]
⚠️ Wichtige Hinweise: [caveats, constraints, common errors]
Best Practices
- Start daily for testing before switching to longer intervals
- Use
repeatwisely —"forever"for permanent jobs,"N/M"for limited runs (N=attempts, M=max runs) - Include error handling in scripts — always check return codes
- Log results — output a summary so you can verify operations
- Keep prompts self-contained — no references to previous conversation context
- Use
deliver="origin"for your own notifications,telegram:<id>for agent delegation
Common Pitfalls
| Pitfall | Symptom | Solution |
|---|---|---|
Raw shell in script |
"Script not found: cd ~/.hermes/..." | Write script file first, reference filename only |
Forget no_agent=true |
Agent tries to run script as a prompt | Set no_agent: true for direct script execution |
| Missing script file | "Script not found: my-script.sh" | Ensure file exists at ~/.hermes/scripts/my-script.sh |
| Script not executable | Permission denied | chmod +x ~/.hermes/scripts/my-script.sh |
| Cronjob runs too often | Rate limits, performance issues | Use every 15m minimum, or daily schedule |
| Wrong deliver target | Results go to wrong chat | origin = this chat, telegram:<id> = target chat |
| Script path is absolute | Works in test, fails in cron | Use relative filename, not absolute path |
| JSON parsing fails in prompt | Non-JSON noise from tools | Use regex fallback (e.g., [...] pattern) |
| No LLM provider configured | RuntimeError: No LLM provider configured | Set model/provider via hermes model or hermes config set model.provider <provider>; then update job with cronjob action=update job_id=<ID> model=<model> provider=<provider> |
| Deleting while awaiting confirmation | User said "delete X", you asked "also delete Y?", then deleted Y BEFORE user answered | ALWAYS wait for explicit user confirmation before executing any destructive action (delete, remove, stop). Never fire off a destructive tool call while a confirmation question is pending. |
| Script outputs nothing in Telegram | Cronjob runs but message is empty | Script MUST print to stdout — anything printed becomes the delivered message body. Log messages to stderr; user-facing output to stdout. |
| Response truncated due to output length limit | Agent cronjob fails with RuntimeError: Response truncated due to output length limit |
Agent cronjobs have a hard output size limit. ALWAYS constrain the agent's output in the prompt: "max 20 lines", "compact summary only", "no explanations". For structured data, output a brief table or key-value list rather than full prose or markdown documents. |
| Telegram group sub-names as delivery targets | telegram:Essensplaner not found even though the group exists |
Telegram deliver targets must match the actual chat/group identifier known to the system (telegram:Schoen Inc), NOT internal nicknames or role names used within that group. Verify available targets with send_message(action='list') or cronjob action=list and inspect deliver fields of existing jobs. |
Script Job: Full Example
# 1. Write the script file
write_file path=~/.hermes/scripts/memory-sync.sh content='#!/bin/bash
cd ~/.hermes/memory
CHANGES=$(git diff --quiet HEAD 2>/dev/null; echo $?)
if [ "$CHANGES" = "0" ]; then
exit 0
fi
git add .
git commit -m "Auto-sync: $(date +%Y-%m-%d)" --allow-empty 2>/dev/null
RESULT=$(git push origin main 2>&1)
if [ $? -eq 0 ]; then
echo "✅ Memory synced successfully"
else
echo "⚠️ Git push failed: $RESULT"
fi
'
| Pitfall | Symptom | Solution |
|---|---|---|
Raw shell in script |
"Script not found: cd ~/.hermes/..." | Write script file first, reference filename only |
Forget no_agent=true |
Agent tries to run script as a prompt | Set no_agent: true for direct script execution |
| Missing script file | "Script not found: my-script.sh" | Ensure file exists at ~/.hermes/scripts/my-script.sh |
| Script not executable | Permission denied | chmod +x ~/.hermes/scripts/my-script.sh |
| Cronjob runs too often | Rate limits, performance issues | Use every 15m minimum, or daily schedule |
| Wrong deliver target | Results go to wrong chat | origin = this chat, telegram:<id> = target chat |
| Script path is absolute | Works in test, fails in cron | Use relative filename, not absolute path |
| JSON parsing fails in prompt | Non-JSON noise from tools | Use regex fallback (e.g., [...] pattern) |
| Custom provider/model mismatch | RuntimeError: No Anthropic credentials found or provider-specific auth errors |
When updating an agent job with a custom provider, ALWAYS set BOTH model AND provider explicitly. The provider string determines which API credentials are loaded. A model string alone does NOT select the provider. Example: model="moonshotai/kimi-k2.6" provider="noris" together. |
Script Job: Full Example
# 1. Write the script file
write_file path=~/.hermes/scripts/memory-sync.sh content='#!/bin/bash
cd ~/.hermes/memory
CHANGES=$(git diff --quiet HEAD 2>/dev/null; echo $?)
if [ "$CHANGES" = "0" ]; then
exit 0
fi
git add .
git commit -m "Auto-sync: $(date +%Y-%m-%d)" --allow-empty 2>/dev/null
RESULT=$(git push origin main 2>&1)
if [ $? -eq 0 ]; then
echo "✅ Memory synced successfully"
else
echo "⚠️ Git push failed: $RESULT"
fi
'
# 2. Make executable
terminal command='chmod +x ~/.hermes/scripts/memory-sync.sh'
# 3. Create the cronjob
cronjob action=create name=memory-sync-daily script=memory-sync.sh schedule="0 22 * * *" repeat=forever deliver=origin no_agent=true
# 4. Verify
cronjob action=list | grep memory-sync
Skill Update History
- 2026-05-09: Created as class-level skill. Documents the critical
scriptparameter filename-only requirement, script creation workflow, and comprehensive pitfall table. Migrated and improved knowledge from container-network-recon skill. - 2026-06-17: Added
No LLM provider configuredpitfall and referencesession_20260617_rechnungen_organizer.md. Lesson: always verify cronjob model/provider alignment with global config. - 2026-06-18: Added
Custom provider/model mismatchpitfall and referencesession_20260618_scraper_deploy.md. Lesson: model + provider MUST be set as a PAIR on agent jobs; for scrapers, useno_agent+ nohup wrapper + watchdog cronjob instead of LLM-based orchestration.