선언적 작업 및 스케줄러 구성
config 파일 cron 작업, 스케줄러 폴링/동시성, catch-up, 재시도, 실행 기록, 예약 백업, 셸 작업 보안.
cron 문서의 대부분은 CLI, 에이전트 도구, 또는 게이트웨이 API를 통해 명령형으로 생성하는 작업을 다룹니다. 이 페이지는 그 반대입니다. config.toml에 선언하여 모든 머신과 재시작에 걸쳐 결정론적으로 존재하는 작업과, 스케줄러가 실제로 작업을 실행하는 방식을 제어하는 튜닝 옵션을 설명합니다.
스케줄이 특정 시점이 아닌 배포 환경 자체에 속할 때 선언적 작업을 사용하십시오 — 야간 리포트, 매시간 백업, 절대 밀려서는 안 되는 워크플로 트리거가 그 예입니다. 스케줄러 및 안정성 섹션은 폴링 주기, 병렬성, 누락된 작업 catch-up, 재시도, 실행 기록 보존량을 제어하는 데 사용합니다. 대신 대화형으로 작업을 생성하려면 revka cron 및 에이전트 작업 및 전달을 참조하십시오.
config의 선언적 cron 작업
섹션 제목: “config의 선언적 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 = truemodel = "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[[cron.jobs]] 항목별 필드
섹션 제목: “[[cron.jobs]] 항목별 필드”| 필드 | 타입 | 기본값 | 의미 |
|---|---|---|---|
id | string | — (필수) | 고정 식별자. DB 기본 키이자 재시작 간 병합 키 |
name | string | 미설정 | 사람이 읽을 수 있는 레이블 |
job_type | string | "shell" | "shell", "agent", 또는 "workflow" |
schedule | inline table | — (필수) | { kind = "cron"|"every"|"at", ... } (아래 참조) |
command | string | — | shell 및 workflow 작업에 필수 |
prompt | string | — | agent 작업에 필수 |
enabled | bool | true | false로 설정하면 일시 중지 상태로 선언 |
model | string | 미설정 | 에이전트 작업의 모델 오버라이드 |
allowed_tools | string[] | 미설정 | 에이전트 작업의 도구 허용 목록 (생략 시 모든 도구) |
session_target | string | "isolated" | "isolated" (새 컨텍스트) 또는 "main" (공유 세션) |
delivery | inline 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" }tz는 kind = "cron"에만 적용됩니다. every와 at는 시간대와 무관합니다. 표현식 문법과 요일 번호 규칙은 Cron 개요 및 표현식을 참조하십시오.
워크플로 cron 트리거 (YAML)
섹션 제목: “워크플로 cron 트리거 (YAML)”워크플로 YAML 파일은 별도의 [[cron.jobs]] 항목 대신 자체 cron 트리거를 포함할 수 있습니다. 시작 시 스케줄러는 ~/.revka/operator_mcp/workflow/builtins/를 스캔하고, 게이트웨이에서 Kumiho 워크플로를 조회한 뒤, 일치하는 cron 작업(source = "workflow"로 표시)을 저장소에 동기화합니다.
name: nightly-cleanuptriggers: - cron: "0 2 * * *"cron: 값은 표준 5필드 표현식입니다. YAML 트리거에는 현재 시간대가 지원되지 않습니다. 이렇게 생성된 작업은 __wf_cron_<slug>_<index> 형태의 id를 사용하며 POST /api/workflows/run/:name을 통해 워크플로를 실행합니다. 이 작업들은 자동으로 관리됩니다 — 직접 수정하지 마십시오. 이후 워크플로가 제거된 경우 오래된 워크플로 작업은 다음 재시작 시 정리됩니다. 트리거 작성에 대해서는 변수, 표현식 및 트리거를 참조하십시오.
내장 백업 cron 작업
섹션 제목: “내장 백업 cron 작업”예약 백업을 위해 [[cron.jobs]] 항목이 필요하지 않습니다. backup.schedule_cron을 설정하면 스케줄러가 지정한 스케줄에 따라 backup create를 셸 작업으로 실행하는 가상 작업(id = "__builtin_backup")을 자동 생성합니다.
[backup]schedule_cron = "0 3 * * *"schedule_timezone = "America/New_York"이것이 예약 백업을 활성화하는 권장 방법입니다. __builtin_backup 작업은 revka cron list 및 GET /api/cron에 다른 선언적 작업과 동일하게 표시되며, 재시도, 실행 기록, 보안 정책에서도 동일하게 처리됩니다.
스케줄러 폴링 및 동시성
섹션 제목: “스케줄러 폴링 및 동시성”[scheduler]와 [reliability] 섹션은 루프가 각 사이클마다 만기 작업을 처리하는 방식을 제어합니다.
[reliability]scheduler_poll_secs = 15 # 만기 작업을 확인하는 주기
[scheduler]enabled = truemax_tasks = 64 # 폴링 사이클당 가져올 작업 수max_concurrent = 4 # 병렬로 실행할 작업 수| 키 | 섹션 | 타입 | 기본값 | 의미 |
|---|---|---|---|---|
enabled | [scheduler] | bool | true | 스케줄러 루프의 마스터 스위치 |
max_tasks | [scheduler] | int | 64 | 폴링 사이클당 가져올 최대 작업 수 (저장된 총 작업 수가 아님) |
max_concurrent | [scheduler] | int | 4 | 병렬로 실행할 최대 작업 수 |
scheduler_poll_secs | [reliability] | int | 15 | 초 단위 폴링 주기 (최소 5초로 제한) |
폴링 간격은 지연 발생 시 틱을 건너뛰는 방식을 사용합니다. 사이클이 오래 걸리면 놓친 틱은 한꺼번에 실행되지 않고 드롭되므로, 느린 배치 이후에 루프가 폭주하는 일이 없습니다. 빠른 작업이 많은 고빈도 워크로드에는 max_concurrent를 높이고, 같은 시간대에 많은 작업이 만기될 수 있다면 max_tasks를 높이십시오.
시작 시 catch-up
섹션 제목: “시작 시 catch-up”데몬이 시작되거나 재시작될 때, 다운된 동안 만기된 작업(늦은 부팅, 충돌, 점검)을 실행할 수 있습니다. 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 = 2provider_backoff_ms = 500| 키 | 타입 | 기본값 | 의미 |
|---|---|---|---|
scheduler_retries | int | 2 | 실패한 작업 실행의 최대 재시도 횟수 |
provider_backoff_ms | int | 500 | 기본 백오프(ms 단위, 최솟값 200, 재시도마다 2배 증가, 최대 30초) |
실행 기록 보존
섹션 제목: “실행 기록 보존”모든 실행은 시작 및 종료 타임스탬프, 상태(ok 또는 error), 출력, 밀리초 단위 소요 시간과 함께 cron_runs 테이블에 기록됩니다. 저장되는 출력은 실행당 16KB로 제한됩니다. 작업별로 보존되는 레코드 수는 cron.max_run_history(기본값 50)이며, 각 새 레코드 삽입과 같은 트랜잭션에서 오래된 레코드가 정리됩니다.
[cron]max_run_history = 100재시작 없이 런타임에서 settings 엔드포인트를 통해 이 값을 조회하거나 변경할 수 있습니다.
GET /api/cron/settingsPATCH /api/cron/settingsAuthorization: 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=20limit의 범위는 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 작업은 작업 생성 또는 업데이트 시와 실행 시, 두 지점에서 보안 정책에 대해 검증됩니다(생성 이후 정책이 변경될 수 있기 때문입니다). 검증 항목은 다음과 같습니다.
-
명령의 바이너리가
autonomy.allowed_commands허용 목록에 있어야 합니다. -
명령의 위험 등급(낮음/중간/높음)이 승인 요건을 충족해야 합니다.
-
경로 인수가 워크스페이스 루트 또는 시스템 디렉터리 외부를 가리켜서는 안 됩니다.
-
입력 리디렉션이 금지된 경로에서 읽어서는 안 됩니다.
-
자율성 수준이 변경 작업을 허용해야 합니다(읽기 전용 모드 불가).
에이전트 작업은 셸 검증을 완전히 우회합니다 — 에이전트의 동작은 대신 에이전트 자체의 도구 정책과 allowed_tools 허용 목록에 의해 제어됩니다.
[autonomy]level = "supervised"allowed_commands = ["echo", "python3", "git"]도구를 통해 작업을 생성하거나 실행할 때 중간 위험 명령을 승인하려면 cron_add, cron_update, 또는 cron_run에 "approved": true를 전달하십시오. 게이트웨이 API를 통해 생성된 작업은 사전 승인되지 않으므로, 해당 경로에서는 중간 위험 명령이 거부됩니다.
전체 정책 모델은 정책, 명령 및 샌드박싱과 보안 모델을 참조하십시오.
cron.enabled 마스터 스위치
섹션 제목: “cron.enabled 마스터 스위치”cron.enabled는 전체 서브시스템의 전역 온/오프 스위치입니다. false이면 모든 cron 도구와 API 엔드포인트가 오류를 반환하고 스케줄러 루프는 어떤 작업도 실행하지 않습니다.
[cron]enabled = falsePATCH /api/cron/settings를 통해 런타임에서도 전환할 수 있습니다. 런타임에서 cron을 비활성화해도 이미 실행 중인 작업은 중단되지 않습니다. 기본값: true.