본문으로 건너뛰기

예약 작업(Cron)

자연어 또는 cron 표현식으로 자동 실행될 작업을 예약합니다. Hermes는 schedule/list/remove 도구를 따로 두지 않고, action 방식의 단일 cronjob 도구를 통해 cron 관리를 노출합니다.

현재 cron으로 할 수 있는 일

Cron job으로 할 수 있는 일:

  • 한 번만 실행되는 작업 또는 반복 작업 예약
  • job 일시 중지, 재개, 수정, 즉시 실행, 삭제
  • job에 skill을 0개, 1개 또는 여러 개 연결
  • 결과를 원래 채팅, 로컬 파일 또는 설정된 platform 대상으로 전달
  • 일반적인 정적 tool 목록을 가진 새 agent session에서 실행
  • no-agent mode로 실행 - 일정에 따라 script만 실행하고, stdout을 그대로 전달하며, LLM은 전혀 개입하지 않음. 아래 no-agent mode 섹션을 참고하세요.

이 모든 기능은 Hermes 자체가 cronjob 도구로 사용할 수 있습니다. 따라서 CLI 없이도 일반 문장으로 요청해 job을 만들고, 일시 중지하고, 수정하고, 삭제할 수 있습니다.

경고

Cron으로 실행되는 session 안에서는 다시 cron job을 만들 수 없습니다. Hermes는 무한 예약 루프를 막기 위해 cron 실행 중에는 cron 관리 도구를 비활성화합니다.

예약 작업 만들기

/cron으로 채팅에서 만들기

/cron add 30m "Remind me to check the build"
/cron add "every 2h" "Check server status"
/cron add "every 1h" "Summarize new feed items" --skill blogwatcher
/cron add "every 1h" "Use both skills and combine the result" --skill blogwatcher --skill maps

standalone CLI에서 만들기

hermes cron create "every 2h" "Check server status"
hermes cron create "every 1h" "Summarize new feed items" --skill blogwatcher
hermes cron create "every 1h" "Use both skills and combine the result" \
--skill blogwatcher \
--skill maps \
--name "Skill combo"

자연스러운 대화로 만들기

Hermes에게 평소처럼 요청할 수도 있습니다.

Every morning at 9am, check Hacker News for AI news and send me a summary on Telegram.

Hermes는 내부적으로 통합 cronjob 도구를 사용합니다.

skill 기반 cron job

Cron job은 prompt를 실행하기 전에 하나 이상의 skill을 로드할 수 있습니다.

단일 skill

cronjob(
action="create",
skill="blogwatcher",
prompt="Check the configured feeds and summarize anything new.",
schedule="0 9 * * *",
name="Morning feeds",
)

여러 skill

Skill은 지정한 순서대로 로드됩니다. prompt는 그 skill 위에 얹히는 작업 지시가 됩니다.

cronjob(
action="create",
skills=["blogwatcher", "maps"],
prompt="Look for new local events and interesting nearby places, then combine them into one short brief.",
schedule="every 6h",
name="Local brief",
)

cron prompt 자체에 skill 전문을 길게 넣지 않고, 예약 agent가 재사용 가능한 workflow를 이어받게 만들고 싶을 때 유용합니다.

프로젝트 디렉터리 안에서 job 실행하기

기본적으로 cron job은 특정 repo와 분리되어 실행됩니다. 즉 AGENTS.md, CLAUDE.md, .cursorrules를 로드하지 않으며, terminal/file/code-exec 도구는 gateway가 시작된 작업 디렉터리를 기준으로 실행됩니다. 이를 바꾸려면 CLI에서는 --workdir, tool call에서는 workdir=을 전달합니다.

# Standalone CLI (schedule and prompt are positional)
hermes cron create "every 1d at 09:00" \
"Audit open PRs, summarize CI health, and post to #eng" \
--workdir /home/me/projects/acme
# From a chat, via the cronjob tool
cronjob(
action="create",
schedule="every 1d at 09:00",
workdir="/home/me/projects/acme",
prompt="Audit open PRs, summarize CI health, and post to #eng",
)

workdir가 설정된 경우:

  • 해당 디렉터리의 AGENTS.md, CLAUDE.md, .cursorrules가 system prompt에 주입됩니다. 탐색 순서는 interactive CLI와 같습니다.
  • terminal, read_file, write_file, patch, search_files, execute_code는 모두 그 디렉터리를 작업 디렉터리로 사용합니다. 내부적으로는 TERMINAL_CWD를 통해 처리됩니다.
  • 경로는 실제로 존재하는 절대 디렉터리여야 합니다. 상대 경로나 존재하지 않는 디렉터리는 create/update 시점에 거부됩니다.
  • 수정할 때 --workdir "" 또는 tool call의 workdir=""을 전달하면 workdir 설정을 지우고 이전 동작으로 되돌릴 수 있습니다.
Serialization

workdir가 있는 job은 scheduler tick에서 병렬 pool이 아니라 순차적으로 실행됩니다. 이는 의도된 동작입니다. TERMINAL_CWD가 process-global이므로, workdir job 두 개가 동시에 실행되면 서로의 cwd가 꼬일 수 있습니다. workdir이 없는 job은 이전처럼 병렬 실행됩니다.

job 수정하기

job을 조금 바꾸기 위해 삭제하고 다시 만들 필요는 없습니다.

Chat

/cron edit <job_id> --schedule "every 4h"
/cron edit <job_id> --prompt "Use the revised task"
/cron edit <job_id> --skill blogwatcher --skill maps
/cron edit <job_id> --remove-skill blogwatcher
/cron edit <job_id> --clear-skills

Standalone CLI

hermes cron edit <job_id> --schedule "every 4h"
hermes cron edit <job_id> --prompt "Use the revised task"
hermes cron edit <job_id> --skill blogwatcher --skill maps
hermes cron edit <job_id> --add-skill maps
hermes cron edit <job_id> --remove-skill blogwatcher
hermes cron edit <job_id> --clear-skills

참고:

  • 반복된 --skill은 job에 연결된 skill 목록을 새 목록으로 교체합니다.
  • --add-skill은 기존 목록을 교체하지 않고 뒤에 추가합니다.
  • --remove-skill은 특정 연결 skill을 제거합니다.
  • --clear-skills는 연결된 모든 skill을 제거합니다.

lifecycle action

이제 cron job은 create/remove보다 더 넓은 lifecycle을 갖습니다.

Chat

/cron list
/cron pause <job_id>
/cron resume <job_id>
/cron run <job_id>
/cron remove <job_id>

Standalone CLI

hermes cron list
hermes cron pause <job_id>
hermes cron resume <job_id>
hermes cron run <job_id>
hermes cron remove <job_id>
hermes cron status
hermes cron tick

각 action의 의미:

  • pause - job은 유지하되 더 이상 예약 실행하지 않습니다.
  • resume - job을 다시 활성화하고 다음 미래 실행 시각을 계산합니다.
  • run - 다음 scheduler tick에서 job을 실행하도록 트리거합니다.
  • remove - job을 완전히 삭제합니다.

동작 방식

Cron 실행은 gateway daemon이 처리합니다. gateway는 60초마다 scheduler를 tick하며, 실행 시각이 된 job을 격리된 agent session에서 실행합니다.

hermes gateway install     # Install as a user service
sudo hermes gateway install --system # Linux: boot-time system service for servers
hermes gateway # Or run in foreground

hermes cron list
hermes cron status

Gateway scheduler 동작

각 tick에서 Hermes는 다음을 수행합니다.

  1. ~/.hermes/cron/jobs.json에서 job을 로드합니다.
  2. 현재 시각과 next_run_at을 비교합니다.
  3. 실행 시각이 된 각 job마다 새 AIAgent session을 시작합니다.
  4. 연결된 skill이 있으면 새 session에 하나 이상 주입합니다.
  5. prompt를 끝까지 실행합니다.
  6. 최종 응답을 전달합니다.
  7. 실행 metadata와 다음 예약 시각을 업데이트합니다.

~/.hermes/cron/.tick.lock의 file lock은 scheduler tick이 겹쳐 같은 job batch가 두 번 실행되는 것을 막습니다.

전달 옵션

job을 예약할 때 출력이 어디로 갈지 지정합니다.

Option설명예시
"origin"job이 만들어진 곳으로 다시 전달messaging platform의 기본값
"local"로컬 파일에만 저장(~/.hermes/cron/output/)CLI의 기본값
"telegram"Telegram home channelTELEGRAM_HOME_CHANNEL 사용
"telegram:123456"ID로 지정한 특정 Telegram chat직접 전달
"telegram:-100123:17585"특정 Telegram topicchat_id:thread_id 형식
"discord"Discord home channelDISCORD_HOME_CHANNEL 사용
"discord:#engineering"특정 Discord channelchannel name 기준
"slack"Slack home channel
"whatsapp"WhatsApp home
"signal"Signal
"matrix"Matrix home room
"mattermost"Mattermost home channel
"email"Email
"sms"Twilio를 통한 SMS
"homeassistant"Home Assistant
"dingtalk"DingTalk
"feishu"Feishu/Lark
"wecom"WeCom
"weixin"Weixin(WeChat)
"bluebubbles"BlueBubbles(iMessage)
"qqbot"QQ Bot(Tencent QQ)
"all"연결된 모든 home channel로 fan out실행 시점에 해석
"telegram,discord"특정 channel 집합으로 fan out쉼표로 구분한 목록
"origin,all"origin과 다른 모든 연결 channel로 전달token 조합 가능

agent의 최종 응답은 자동으로 전달됩니다. cron prompt 안에서 send_message를 호출할 필요가 없습니다.

routing intent: all

all을 사용하면 설정된 모든 messaging channel에 하나의 cron job을 전달할 수 있습니다. channel 이름을 일일이 나열할 필요가 없습니다. all실행 시점에 해석되므로, Telegram을 연결하기 전에 만든 job도 이후 TELEGRAM_HOME_CHANNEL을 설정하면 다음 tick부터 Telegram으로 전달됩니다.

의미상 all은 home channel이 설정된 모든 platform으로 확장됩니다. 대상이 0개여도 괜찮습니다. 이 경우 job은 전달 대상 없이 실행되고, upstream에는 delivery failure로 기록됩니다.

all은 명시 대상과 조합할 수 있습니다. origin,all은 origin chat과 다른 모든 연결 home channel에 전달하며, (platform, chat_id, thread_id) 기준으로 중복을 제거합니다.

응답 wrapper

기본적으로 전달되는 cron 출력에는 예약 작업에서 온 메시지임을 알 수 있도록 header와 footer가 붙습니다.

Cronjob Response: Morning feeds
-------------

<agent output here>

Note: The agent cannot see this message, and therefore cannot respond to it.

wrapper 없이 agent 원본 출력만 전달하려면 cron.wrap_responsefalse로 설정합니다.

# ~/.hermes/config.yaml
cron:
wrap_response: false

silent suppression

agent의 최종 응답이 [SILENT]로 시작하면 전달이 완전히 억제됩니다. 출력은 감사용으로 로컬(~/.hermes/cron/output/)에 계속 저장되지만, delivery target으로 메시지는 보내지 않습니다.

이는 문제가 있을 때만 보고해야 하는 monitoring job에 유용합니다.

Check if nginx is running. If everything is healthy, respond with only [SILENT].
Otherwise, report the issue.

실패한 job은 [SILENT] marker와 관계없이 항상 전달됩니다. 성공한 run만 조용히 처리할 수 있습니다.

script timeout

script parameter로 연결된 pre-run script의 기본 timeout은 120초입니다. 예를 들어 bot처럼 보이는 timing pattern을 피하기 위해 randomized delay를 넣는 등 script가 더 오래 걸려야 한다면 timeout을 늘릴 수 있습니다.

# ~/.hermes/config.yaml
cron:
script_timeout_seconds: 300 # 5 minutes

또는 HERMES_CRON_SCRIPT_TIMEOUT 환경 변수를 설정합니다. 해석 우선순위는 env var -> config.yaml -> 기본값 120초입니다.

No-agent mode(script-only job)

LLM reasoning이 필요 없는 반복 job, 예를 들어 classic watchdog, disk/memory alert, heartbeat, CI ping에는 생성 시 no_agent=True를 전달합니다. scheduler는 지정된 schedule에 맞춰 script를 실행하고, agent를 건너뛰고 stdout을 그대로 전달합니다.

hermes cron create "every 5m" \
--no-agent \
--script memory-watchdog.sh \
--deliver telegram \
--name "memory-watchdog"

의미:

  • script stdout(trimmed)은 메시지로 그대로 전달됩니다.
  • stdout이 비어 있으면 silent tick입니다. 아무것도 전달하지 않습니다. 이것이 watchdog pattern입니다. "문제가 있을 때만 말하기"에 해당합니다.
  • non-zero exit 또는 timeout이 발생하면 error alert가 전달됩니다. 깨진 watchdog이 조용히 실패하지 못하게 하기 위해서입니다.
  • 마지막 줄의 {"wakeAgent": false}는 silent tick입니다. LLM job에서도 사용하는 같은 gate입니다.
  • token, model, provider fallback이 없습니다. job은 inference layer를 전혀 건드리지 않습니다.

.sh / .bash 파일은 /bin/bash에서 실행됩니다. 그 외 파일은 현재 Python interpreter(sys.executable)로 실행됩니다. script는 반드시 ~/.hermes/scripts/ 안에 있어야 합니다. pre-run script gate와 같은 sandboxing 규칙입니다.

agent가 대신 설정해 주는 방식

cronjob 도구 schema는 no_agent를 Hermes에 직접 노출합니다. 따라서 chat에서 watchdog을 설명하면 agent가 필요한 설정을 연결하게 할 수 있습니다.

Ping me on Telegram if RAM is over 85%, every 5 minutes.

Hermes는 write_file을 통해 check script를 ~/.hermes/scripts/에 쓴 뒤 다음처럼 호출합니다.

cronjob(action="create", schedule="every 5m",
script="memory-watchdog.sh", no_agent=True,
deliver="telegram", name="memory-watchdog")

메시지 내용이 script만으로 완전히 결정되는 경우, 예를 들어 watchdog, threshold alert, heartbeat에서는 Hermes가 no_agent=True를 자동 선택합니다. 같은 도구로 job을 pause/resume/edit/remove할 수도 있으므로, lifecycle 전체가 CLI 없이 chat으로 구동됩니다.

실제 예시는 Script-Only Cron Jobs guide를 참고하세요.

context_from으로 job 연결하기

Cron job은 이전 run의 기억 없이 격리된 session에서 실행됩니다. 하지만 한 job의 출력이 다음 job에 필요한 context인 경우가 있습니다. context_from parameter는 이 연결을 자동으로 만듭니다. Job B의 prompt 앞에는 runtime에 Job A의 최신 출력이 context로 붙습니다.

# Job 1: Collect raw data
cronjob(
action="create",
prompt="Fetch the top 10 AI/ML stories from Hacker News. Save them to ~/.hermes/data/briefs/raw.md in markdown format with title, URL, and score.",
schedule="0 7 * * *",
name="AI News Collector",
)

# Job 2: Triage - receives Job 1's output as context
# Get Job 1's ID from: cronjob(action="list")
cronjob(
action="create",
prompt="Read ~/.hermes/data/briefs/raw.md. Score each story 1-10 for engagement potential and novelty. Output the top 5 to ~/.hermes/data/briefs/ranked.md.",
schedule="30 7 * * *",
context_from="<job1_id>",
name="AI News Triage",
)

# Job 3: Ship - receives Job 2's output as context
cronjob(
action="create",
prompt="Read ~/.hermes/data/briefs/ranked.md. Write 3 tweet drafts (hook + body + hashtags). Deliver to telegram:7976161601.",
schedule="0 8 * * *",
context_from="<job2_id>",
name="AI News Brief",
)

동작 방식:

  • Job 2가 실행될 때 Hermes는 ~/.hermes/cron/output/{job1_id}/*.md에서 Job 1의 가장 최근 출력을 읽습니다.
  • 그 출력은 Job 2의 prompt 앞에 자동으로 붙습니다.
  • Job 2는 "이 파일을 읽어라"라는 식으로 hardcode할 필요가 없습니다. content를 context로 받습니다.
  • chain 길이는 제한되지 않습니다. Job 1 -> Job 2 -> Job 3 -> ...

context_from이 받는 형식:

Format예시
단일 job ID(string)context_from="a1b2c3d4"
여러 job ID(list)context_from=["job_a", "job_b"]

출력은 목록에 적힌 순서대로 이어 붙습니다.

사용하기 좋은 경우:

  • multi-stage pipeline(collect -> filter -> format -> deliver)
  • N단계 작업이 N-1단계의 출력에 의존하는 dependent task
  • 여러 job의 결과를 모아 하나의 job이 집계하는 fan-out/fan-in pattern

provider recovery

Cron job은 설정된 fallback provider와 credential pool rotation을 그대로 상속합니다. primary API key가 rate limit에 걸리거나 provider가 오류를 반환하면 cron agent는 다음을 수행할 수 있습니다.

  • config.yamlfallback_providers 또는 legacy fallback_model이 설정되어 있으면 다른 provider로 fallback
  • 같은 provider의 credential pool에서 다음 credential로 rotation

따라서 높은 빈도로 실행되거나 사용량이 많은 시간대에 실행되는 cron job도 더 견고합니다. rate limit에 걸린 key 하나 때문에 전체 run이 실패하지 않습니다.

schedule 형식

agent의 최종 응답은 자동으로 전달됩니다. 같은 목적지로 보내기 위해 cron prompt에 send_message를 넣을 필요는 없습니다. cron run이 scheduler가 이미 전달할 정확한 대상에 send_message를 호출하면 Hermes는 중복 전송을 건너뛰고, 사용자에게 보여 줄 내용은 final response에 넣으라고 모델에 알립니다. send_message는 추가 대상이나 다른 대상에 보낼 때만 사용하세요.

상대 지연(one-shot)

30m     -> Run once in 30 minutes
2h -> Run once in 2 hours
1d -> Run once in 1 day

interval(recurring)

every 30m    -> Every 30 minutes
every 2h -> Every 2 hours
every 1d -> Every day

cron 표현식

0 9 * * *       -> Daily at 9:00 AM
0 9 * * 1-5 -> Weekdays at 9:00 AM
0 */6 * * * -> Every 6 hours
30 8 1 * * -> First of every month at 8:30 AM
0 0 * * 0 -> Every Sunday at midnight

ISO timestamp

2026-03-15T09:00:00    -> One-time at March 15, 2026 9:00 AM

반복 동작

schedule type기본 repeat동작
one-shot(30m, timestamp)1한 번 실행
interval(every 2h)forever삭제될 때까지 실행
cron expressionforever삭제될 때까지 실행

다음처럼 override할 수 있습니다.

cronjob(
action="create",
prompt="...",
schedule="every 2h",
repeat=5,
)

programmatic job 관리

agent-facing API는 하나의 도구입니다.

cronjob(action="create", ...)
cronjob(action="list")
cronjob(action="update", job_id="...")
cronjob(action="pause", job_id="...")
cronjob(action="resume", job_id="...")
cronjob(action="run", job_id="...")
cronjob(action="remove", job_id="...")

update에서 skills=[]를 전달하면 연결된 skill을 모두 제거합니다.

cron job에서 사용할 수 있는 toolset

Cron은 각 job을 chat platform이 붙지 않은 새 agent session에서 실행합니다. 기본적으로 cron agent는 hermes tools에서 cron platform용으로 설정한 toolset을 받습니다. CLI 기본값도 아니고, 가능한 모든 도구도 아닙니다.

hermes tools
# pick the "cron" platform in the curses UI
# toggle toolsets on/off just like you would for Telegram/Discord/etc.

job별로 더 좁게 제어하려면 cronjob.createenabled_toolsets 필드를 사용합니다. 기존 job은 cronjob.update로 바꿀 수 있습니다.

cronjob(action="create", name="weekly-news-summary",
schedule="every sunday 9am",
enabled_toolsets=["web", "file"], # just web + file, no terminal/browser/etc.
prompt="Summarize this week's AI news: ...")

job에 enabled_toolsets가 설정되어 있으면 그 값이 우선합니다. 없으면 hermes tools의 cron-platform config가 우선하고, 그것도 없으면 Hermes가 built-in default로 fallback합니다. 비용 제어 측면에서 중요합니다. 작은 "fetch news" job마다 moa, browser, delegation을 실으면 모든 LLM call에서 tool-schema prompt가 불필요하게 커집니다.

agent를 완전히 건너뛰기: wakeAgent

cron job에 pre-check script(script=)가 붙어 있으면, script가 runtime에 Hermes가 agent를 호출할지 결정할 수 있습니다. stdout의 마지막 줄에 다음 형식을 출력하세요.

{"wakeAgent": false}

그러면 cron은 해당 tick에서 agent run을 완전히 건너뜁니다. 자주 실행되는 polling job(예: 1-2분마다 실행)에서 실제 상태가 바뀔 때만 LLM을 깨우고 싶을 때 유용합니다. 그렇지 않으면 내용이 없는 agent turn에도 계속 비용이 발생합니다.

# pre-check script
import json, sys
latest = fetch_latest_issue_count()
prev = read_state("issue_count")
if latest == prev:
print(json.dumps({"wakeAgent": False})) # skip this tick
sys.exit(0)
write_state("issue_count", latest)
print(json.dumps({"wakeAgent": True, "context": {"new_issues": latest - prev}}))

wakeAgent가 생략되면 기본값은 true입니다. 즉 평소처럼 agent를 깨웁니다.

recipe: 저렴한 pre-run gate

wakeAgent gate는 예약 job이 LLM token을 써야 하는지 $0으로 결정하는 방법입니다. 대부분의 사용 사례는 다음 세 가지 pattern으로 충분합니다.

File-change gate - 감시 중인 파일에 마지막 성공 tick 이후 새 content가 있을 때만 실행합니다. scheduler는 각 job의 last_run_at을 기록하므로, 이를 파일의 mtime과 비교합니다.

#!/bin/bash
# ~/.hermes/scripts/feed-changed.sh
FEED="$HOME/data/feed.json"
STATE="$HOME/.hermes/scripts/.feed-changed.last"
test -f "$FEED" || { echo '{"wakeAgent": false}'; exit 0; }
mtime=$(stat -c %Y "$FEED")
last=$(cat "$STATE" 2>/dev/null || echo 0)
if [ "$mtime" -le "$last" ]; then
echo '{"wakeAgent": false}'
else
echo "$mtime" > "$STATE"
echo '{"wakeAgent": true}'
fi
cronjob(action="create", name="process-feed",
schedule="every 30m",
script="feed-changed.sh",
prompt="A new ~/data/feed.json has landed. Summarize what changed.")

External-flag gate - 다른 process가 준비 완료를 알렸을 때만 실행합니다. 예를 들어 deploy hook이 파일을 떨어뜨리거나, CI job이 state store에 값을 설정하는 경우입니다.

#!/bin/bash
# ~/.hermes/scripts/flag-ready.sh
if test -f /tmp/new-data-ready; then
rm -f /tmp/new-data-ready
echo '{"wakeAgent": true}'
else
echo '{"wakeAgent": false}'
fi
cronjob(action="create", name="nightly-analysis",
schedule="0 9 * * *",
script="flag-ready.sh",
prompt="Run the nightly analysis over today's batch.")

SQL-count gate - 자체 database에 처리할 새 row가 있을 때만 실행합니다. script가 context를 통해 count를 agent에 넘겨 줄 수도 있으므로, agent가 다시 query하지 않아도 작업량을 알 수 있습니다.

#!/usr/bin/env python
# ~/.hermes/scripts/new-rows.py
import json, sqlite3
conn = sqlite3.connect("/home/me/data/app.db")
n = conn.execute(
"SELECT COUNT(*) FROM messages WHERE ts > strftime('%s','now','-2 hours')"
).fetchone()[0]
if n < 1:
print(json.dumps({"wakeAgent": False}))
else:
print(json.dumps({"wakeAgent": True, "context": {"new_rows": n}}))
cronjob(action="create", name="summarize-new-msgs",
schedule="every 2h",
script="new-rows.py",
prompt="Summarize the new messages from the last 2 hours.")

이 pattern은 script에서 query할 수 있는 모든 data source에 적용됩니다. Postgres, HTTP API, 자체 state store 등 무엇이든 가능하며, cron subsystem 안에 SQL evaluator를 따로 넣을 필요가 없습니다.

Hermes 자체의 ~/.hermes/state.db는 release 사이에 바뀔 수 있는 internal schema입니다. pre-run gate에서 query하지 마세요. 대신 여러분의 database나 feed를 바라보게 하세요.

Credit: 이 recipe set은 #2654에서 @iankar8이 sql/file/command trigger를 병렬 mechanism으로 추가하는 방안을 탐색한 데서 출발했습니다. script + wakeAgent gate가 이미 세 가지 경우를 $0으로 모두 처리하므로, 최종 결과는 별도 기능이 아니라 문서로 반영되었습니다.

job chaining: context_from

cron job은 context_from에 다른 job의 이름 또는 ID를 나열해, 그 job들의 가장 최근 성공 출력을 소비할 수 있습니다.

cronjob(action="create", name="daily-digest",
schedule="every day 7am",
context_from=["ai-news-fetch", "github-prs-fetch"],
prompt="Write the daily digest using the outputs above.")

참조된 job들의 가장 최근 완료 출력은 이번 run의 prompt 위에 context로 주입됩니다. 각 upstream entry는 유효한 job ID 또는 이름이어야 합니다. cronjob action="list"를 참고하세요. 참고로 chaining은 가장 최근 완료된 출력을 읽을 뿐이며, 같은 tick에서 아직 실행 중인 upstream job을 기다리지 않습니다.

job storage

job은 ~/.hermes/cron/jobs.json에 저장됩니다. job run의 출력은 ~/.hermes/cron/output/{job_id}/{timestamp}.md에 저장됩니다.

job은 modelprovidernull로 저장할 수 있습니다. 이 필드가 생략되면 Hermes는 실행 시점에 global configuration에서 값을 해석합니다. per-job override가 설정된 경우에만 job record에 나타납니다.

storage는 atomic file write를 사용하므로, 쓰기 중단으로 인해 job file이 부분적으로만 작성된 상태로 남지 않습니다.

self-contained prompt는 여전히 중요합니다

Important

Cron job은 완전히 새 agent session에서 실행됩니다. prompt에는 연결된 skill이 이미 제공하지 않는, agent가 작업을 완료하는 데 필요한 모든 정보가 들어 있어야 합니다.

BAD: "Check on that server issue"

GOOD: "SSH into server 192.168.1.100 as user 'deploy', check if nginx is running with 'systemctl status nginx', and verify https://example.com returns HTTP 200."

보안

예약 작업 prompt는 생성 및 update 시점에 prompt injection과 credential exfiltration pattern을 검사합니다. 보이지 않는 Unicode trick, SSH backdoor 시도, 명백한 secret exfiltration payload가 포함된 prompt는 차단됩니다.