콘텐츠로 이동

선언적 작업 및 스케줄러 구성

config 파일 cron 작업, 스케줄러 폴링/동시성, catch-up, 재시도, 실행 기록, 예약 백업, 셸 작업 보안.

cron 문서의 대부분은 CLI, 에이전트 도구, 또는 게이트웨이 API를 통해 명령형으로 생성하는 작업을 다룹니다. 이 페이지는 그 반대입니다. config.toml에 선언하여 모든 머신과 재시작에 걸쳐 결정론적으로 존재하는 작업과, 스케줄러가 실제로 작업을 실행하는 방식을 제어하는 튜닝 옵션을 설명합니다.

스케줄이 특정 시점이 아닌 배포 환경 자체에 속할 때 선언적 작업을 사용하십시오 — 야간 리포트, 매시간 백업, 절대 밀려서는 안 되는 워크플로 트리거가 그 예입니다. 스케줄러 및 안정성 섹션은 폴링 주기, 병렬성, 누락된 작업 catch-up, 재시도, 실행 기록 보존량을 제어하는 데 사용합니다. 대신 대화형으로 작업을 생성하려면 revka cron에이전트 작업 및 전달을 참조하십시오.

[[cron.jobs]] 아래에 테이블 배열로 작업을 선언합니다. 각 시작 시 스케줄러는 이 선언들을 SQLite 작업 저장소에 동기화합니다. 새 작업은 삽입하고, 변경된 작업은 업데이트하며, config에서 제거된 작업은 삭제합니다. 선언적 작업은 source = "declarative"로 표시되고, 명령형 작업(CLI, 도구, API를 통해 생성된)은 다른 source를 가지며 동기화 시 절대 변경되지 않습니다.

# 평일 뉴욕 시간 08:00에 실행되어 Slack에 게시하는 에이전트 작업.
[[cron.jobs]]
id = "daily-report"
name = "Daily Report"
job_type = "agent"
schedule = { kind = "cron", expr = "0 8 * * 1-5", tz = "America/New_York" }
prompt = "Generate the morning system report"
enabled = true
model = "anthropic/claude-opus-4-5"
allowed_tools = ["file_read", "http_request"]
session_target = "isolated"
[cron.jobs.delivery]
mode = "announce"
channel = "slack"
to = "#ops-alerts"
best_effort = true
# 매시간 실행되는 셸 작업.
[[cron.jobs]]
id = "hourly-backup"
job_type = "shell"
schedule = { kind = "every", every_ms = 3600000 }
command = "backup create"
enabled = true
필드타입기본값의미
idstring— (필수)고정 식별자. DB 기본 키이자 재시작 간 병합 키
namestring미설정사람이 읽을 수 있는 레이블
job_typestring"shell""shell", "agent", 또는 "workflow"
scheduleinline table— (필수){ kind = "cron"|"every"|"at", ... } (아래 참조)
commandstringshellworkflow 작업에 필수
promptstringagent 작업에 필수
enabledbooltruefalse로 설정하면 일시 중지 상태로 선언
modelstring미설정에이전트 작업의 모델 오버라이드
allowed_toolsstring[]미설정에이전트 작업의 도구 허용 목록 (생략 시 모든 도구)
session_targetstring"isolated""isolated" (새 컨텍스트) 또는 "main" (공유 세션)
deliveryinline table미설정{ mode, channel, to, best_effort } — 채널로 출력 공지

schedule 테이블은 cron 전반에서 사용되는 동일한 형태를 사용합니다.

schedule = { kind = "cron", expr = "0 9 * * 1-5", tz = "America/Los_Angeles" }
schedule = { kind = "every", every_ms = 3600000 }
schedule = { kind = "at", at = "2025-12-31T23:59:00Z" }

tzkind = "cron"에만 적용됩니다. everyat는 시간대와 무관합니다. 표현식 문법과 요일 번호 규칙은 Cron 개요 및 표현식을 참조하십시오.

워크플로 YAML 파일은 별도의 [[cron.jobs]] 항목 대신 자체 cron 트리거를 포함할 수 있습니다. 시작 시 스케줄러는 ~/.revka/operator_mcp/workflow/builtins/를 스캔하고, 게이트웨이에서 Kumiho 워크플로를 조회한 뒤, 일치하는 cron 작업(source = "workflow"로 표시)을 저장소에 동기화합니다.

name: nightly-cleanup
triggers:
- cron: "0 2 * * *"

cron: 값은 표준 5필드 표현식입니다. YAML 트리거에는 현재 시간대가 지원되지 않습니다. 이렇게 생성된 작업은 __wf_cron_<slug>_<index> 형태의 id를 사용하며 POST /api/workflows/run/:name을 통해 워크플로를 실행합니다. 이 작업들은 자동으로 관리됩니다 — 직접 수정하지 마십시오. 이후 워크플로가 제거된 경우 오래된 워크플로 작업은 다음 재시작 시 정리됩니다. 트리거 작성에 대해서는 변수, 표현식 및 트리거를 참조하십시오.

예약 백업을 위해 [[cron.jobs]] 항목이 필요하지 않습니다. backup.schedule_cron을 설정하면 스케줄러가 지정한 스케줄에 따라 backup create를 셸 작업으로 실행하는 가상 작업(id = "__builtin_backup")을 자동 생성합니다.

[backup]
schedule_cron = "0 3 * * *"
schedule_timezone = "America/New_York"

이것이 예약 백업을 활성화하는 권장 방법입니다. __builtin_backup 작업은 revka cron listGET /api/cron에 다른 선언적 작업과 동일하게 표시되며, 재시도, 실행 기록, 보안 정책에서도 동일하게 처리됩니다.

[scheduler][reliability] 섹션은 루프가 각 사이클마다 만기 작업을 처리하는 방식을 제어합니다.

[reliability]
scheduler_poll_secs = 15 # 만기 작업을 확인하는 주기
[scheduler]
enabled = true
max_tasks = 64 # 폴링 사이클당 가져올 작업 수
max_concurrent = 4 # 병렬로 실행할 작업 수
섹션타입기본값의미
enabled[scheduler]booltrue스케줄러 루프의 마스터 스위치
max_tasks[scheduler]int64폴링 사이클당 가져올 최대 작업 수 (저장된 총 작업 수가 아님)
max_concurrent[scheduler]int4병렬로 실행할 최대 작업 수
scheduler_poll_secs[reliability]int15초 단위 폴링 주기 (최소 5초로 제한)

폴링 간격은 지연 발생 시 틱을 건너뛰는 방식을 사용합니다. 사이클이 오래 걸리면 놓친 틱은 한꺼번에 실행되지 않고 드롭되므로, 느린 배치 이후에 루프가 폭주하는 일이 없습니다. 빠른 작업이 많은 고빈도 워크로드에는 max_concurrent를 높이고, 같은 시간대에 많은 작업이 만기될 수 있다면 max_tasks를 높이십시오.

데몬이 시작되거나 재시작될 때, 다운된 동안 만기된 작업(늦은 부팅, 충돌, 점검)을 실행할 수 있습니다. catch-up 단계는 max_tasks 제한을 무시하고 모든 지연 작업을 조회하여 각각 한 번씩 실행한 후 일반 폴링 루프로 진입합니다.

[cron]
catch_up_on_startup = true # 기본값

catch_up_on_startup = false로 설정하면 catch-up을 건너뜁니다. 누락된 작업은 다음 자연 예약 실행 시간까지 대기합니다. catch-up 단계는 의도적으로 max_tasks를 우회합니다. 누락된 모든 작업을 각 한 번씩 실행하는 것이 목적이기 때문입니다 — 해당 제한은 정상 상태 폴링에만 적용됩니다.

실패한 실행은 자동으로 재시도됩니다. 재시도 횟수는 reliability.scheduler_retries(기본값 2, 즉 최대 총 3회 시도)입니다. 시도 사이에는 reliability.provider_backoff_ms(200ms 최솟값 적용)를 기준으로 지수 백오프와 지터가 적용되며, 두 배씩 증가하여 최대 30초까지 늘어납니다.

[reliability]
scheduler_retries = 2
provider_backoff_ms = 500
타입기본값의미
scheduler_retriesint2실패한 작업 실행의 최대 재시도 횟수
provider_backoff_msint500기본 백오프(ms 단위, 최솟값 200, 재시도마다 2배 증가, 최대 30초)

모든 실행은 시작 및 종료 타임스탬프, 상태(ok 또는 error), 출력, 밀리초 단위 소요 시간과 함께 cron_runs 테이블에 기록됩니다. 저장되는 출력은 실행당 16KB로 제한됩니다. 작업별로 보존되는 레코드 수는 cron.max_run_history(기본값 50)이며, 각 새 레코드 삽입과 같은 트랜잭션에서 오래된 레코드가 정리됩니다.

[cron]
max_run_history = 100

재시작 없이 런타임에서 settings 엔드포인트를 통해 이 값을 조회하거나 변경할 수 있습니다.

GET /api/cron/settings
PATCH /api/cron/settings
Authorization: Bearer <pairing-token>
Content-Type: application/json
{ "enabled": true, "catch_up_on_startup": false, "max_run_history": 100 }

변경 사항은 디스크의 config에 기록되고 인메모리 config에 즉시 적용됩니다. 단일 작업의 기록을 조회하려면 다음을 사용하십시오.

GET /api/cron/:id/runs?limit=20

limit의 범위는 1–100(기본값 20)이며, 존재하지 않는 작업 id는 404를 반환합니다. 전체 응답 형태는 Cron, 세션 및 첨부 API를 참조하고, 출력을 500자로 잘라 표시하는 cron_runs 도구에 대해서는 에이전트 작업 및 전달을 참조하십시오.

at 스케줄이 있는 작업은 한 번만 실행됩니다. 이후 동작은 결과와 delete_after_run 값에 따라 달라집니다.

  • 성공 + delete_after_run = true — 작업이 DB에서 제거됩니다. revka cron add-at으로 생성된 셸 작업은 항상 이 값을 설정하며, 에이전트 일회성 작업도 기본값은 true이지만 재정의할 수 있습니다.
  • 실패 — 작업은 삭제되지 않고 비활성화되어 디버깅을 위한 실패 출력이 보존됩니다. 확인 후 revka cron remove <id>로 수동 삭제하십시오.
  • delete_after_run 없는 at 스케줄 — 실행 후 비활성화되어 과거 실행 시간으로 재실행되지 않습니다.

실행 후 일회성 작업을 보존하려면 delete_after_run = false를 명시적으로 설정하면 작업이 비활성화 상태로 유지됩니다.

셸 cron 작업은 작업 생성 또는 업데이트 시와 실행 시, 지점에서 보안 정책에 대해 검증됩니다(생성 이후 정책이 변경될 수 있기 때문입니다). 검증 항목은 다음과 같습니다.

  1. 명령의 바이너리가 autonomy.allowed_commands 허용 목록에 있어야 합니다.

  2. 명령의 위험 등급(낮음/중간/높음)이 승인 요건을 충족해야 합니다.

  3. 경로 인수가 워크스페이스 루트 또는 시스템 디렉터리 외부를 가리켜서는 안 됩니다.

  4. 입력 리디렉션이 금지된 경로에서 읽어서는 안 됩니다.

  5. 자율성 수준이 변경 작업을 허용해야 합니다(읽기 전용 모드 불가).

에이전트 작업은 셸 검증을 완전히 우회합니다 — 에이전트의 동작은 대신 에이전트 자체의 도구 정책과 allowed_tools 허용 목록에 의해 제어됩니다.

[autonomy]
level = "supervised"
allowed_commands = ["echo", "python3", "git"]

도구를 통해 작업을 생성하거나 실행할 때 중간 위험 명령을 승인하려면 cron_add, cron_update, 또는 cron_run"approved": true를 전달하십시오. 게이트웨이 API를 통해 생성된 작업은 사전 승인되지 않으므로, 해당 경로에서는 중간 위험 명령이 거부됩니다.

전체 정책 모델은 정책, 명령 및 샌드박싱보안 모델을 참조하십시오.

cron.enabled는 전체 서브시스템의 전역 온/오프 스위치입니다. false이면 모든 cron 도구와 API 엔드포인트가 오류를 반환하고 스케줄러 루프는 어떤 작업도 실행하지 않습니다.

[cron]
enabled = false

PATCH /api/cron/settings를 통해 런타임에서도 전환할 수 있습니다. 런타임에서 cron을 비활성화해도 이미 실행 중인 작업은 중단되지 않습니다. 기본값: true.