콘텐츠로 이동

SOP 참조: 구문, 트리거, 실행

SOP.toml 메타데이터, SOP.md 단계, SOP CLI, MQTT/웹훅/크론/주변장치/수동 트리거, LLM을 사용하지 않는 결정론적 모드를 포함한 실행 모드, 실행 수명 주기, 동시성/쿨다운, 감사 기록에 대한 완전한 참조 문서입니다.

**SOP(표준 운영 절차)**는 타입이 지정된 트리거, 승인 게이트, 그리고 감사 가능한 실행 레코드를 갖춘 결정론적 이벤트 기반 절차입니다. SOP는 디스크 상의 SOP.toml + SOP.md 파일로 정의되며 Rust SopEngine이 실행합니다. Kumiho에 저장되고 operator-mcp 백엔드가 실행하는 YAML 워크플로우와는 구별됩니다. 외부 신호(MQTT 메시지, 웹훅, 크론 틱, 하드웨어 핀)가 정의되고 게이트 처리된 감사 절차를 안정적으로 실행해야 할 때 SOP를 사용하세요 — 순수한 기계적 시퀀스를 위한 LLM 없는 결정론적 모드도 포함됩니다.

이 페이지는 SOP 파일 구문, 트리거 타입, 실행 모드, 실행 수명 주기, 그리고 실행을 구동하는 CLI 및 에이전트 도구에 대한 완전한 참조입니다. SOP와 워크플로우의 개념적 비교는 워크플로우 & SOP 개요를 참고하세요. 관련 YAML 워크플로우 엔진은 첫 번째 워크플로우를 참고하세요.

SOP는 설정된 sops_dir 아래에 있는 자체 디렉터리에 위치합니다. 각 디렉터리에는 필수 SOP.toml(메타데이터 + 트리거)과 선택적 SOP.md(번호가 매겨진 절차 단계)가 포함됩니다. 엔진은 시작 시 모든 SOP를 로드하고, 각 SOP의 트리거에 대해 들어오는 이벤트를 매칭하며, 매칭마다 **실행(run)**을 시작합니다. 실행은 에이전트 루프를 통해 진행되며 승인 게이트와 결정론적 체크포인트에서 일시 정지하고, 감사 로거가 모든 시작, 단계, 승인을 기록합니다.

~/.revka/workspace/sops/
deploy-prod/
SOP.toml # metadata + triggers (required)
SOP.md # numbered procedure steps (optional, but a run with no steps fails validation)

MQTT, 웹훅, 크론, 주변장치 등 모든 이벤트 소스는 단일 통합 디스패처(dispatch_sop_event)를 통해 처리되므로, 실행이 어떻게 시작되더라도 트리거 매칭, 실행 시작 감사, 헤드리스 안전 동작이 동일하게 적용됩니다.

Event sources unified dispatcher
MQTT message (topic match) │
POST /sop/* or /webhook (path match) │
Scheduler (window check) ─────┼──▶ dispatch_sop_event ──▶ SopEngine ──▶ SOP Run ──▶ Action
Peripheral signal (board/signal) │ │
sop_execute tool (manual) │ ┌────────────────────────┴───────────┐
ExecuteStep WaitApproval
│ │
▼ ▼
Agent loop Operator
│ sop_approve
SOP Run (resumes)

SOP는 ~/.revka/config.toml에서 활성화하기 전까지 비활성 상태입니다:

[sop]
enabled = true
sops_dir = "sops" # relative to the workspace; defaults to <workspace>/sops
default_execution_mode = "supervised"
타입기본값설명
enabledboolfalseSOP 엔진의 마스터 스위치.
sops_dirstring<workspace>/sopsSOP 서브디렉터리를 검색하는 디렉터리.
default_execution_modestringsupervised자체 execution_mode를 설정하지 않은 SOP에 적용되는 모드.
max_concurrent_totalint10모든 SOP에 걸친 동시 실행의 전역 상한.
approval_timeout_secsint3600승인 게이트에서 타임아웃 처리 전까지 대기하는 시간(초) (0 = 무기한 대기).

SOP.toml은 매니페스트입니다: 식별 정보, 우선순위, 실행 정책, 동시성/쿨다운 제한, 그리고 하나 이상의 [[triggers]]를 포함합니다.

[sop]
name = "deploy-prod"
description = "Deploy service to production"
version = "1.0.0"
priority = "high" # low | normal | high | critical
execution_mode = "supervised" # auto | supervised | step_by_step | priority_based | deterministic
cooldown_secs = 300
max_concurrent = 1
deterministic = false # true forces execution_mode = deterministic
[[triggers]]
type = "webhook"
path = "/sop/deploy"
[[triggers]]
type = "manual"
필드타입기본값설명
namestring— (필수)sop_execute 및 CLI에서 사용하는 고유 SOP 식별자.
descriptionstring— (필수)사람이 읽을 수 있는 목적 설명.
versionstring"0.1.0"절차의 시맨틱 버전.
prioritystringnormallow, normal, high, critical 중 하나. priority_based 모드와 승인 타임아웃 에스컬레이션에 사용.
execution_modestring([sop].default_execution_mode)auto, supervised, step_by_step, priority_based, deterministic 중 하나. 실행 모드를 참고하세요.
cooldown_secsint0이 SOP의 실행 간 최소 대기 시간(초) (0 = 쿨다운 없음).
max_concurrentint1이 SOP의 최대 동시 실행 수.
deterministicboolfalsetrue이면 execution_modedeterministic으로 재정의.

[[triggers]] 블록은 하나의 트리거를 선언하며, 하나의 SOP에 여러 트리거를 설정할 수 있습니다. 각 type이 허용하는 필드는 트리거 타입을 참고하세요.

SOP.md는 순서가 있는 절차를 정의합니다. 단계는 ## Steps 섹션에서 번호 목록으로 파싱됩니다. 각 항목의 앞부분 굵은 텍스트가 단계 제목이며, 나머지는 본문입니다. 하위 글머리는 메타데이터를 첨부합니다.

## Steps
1. **Check readings** — Read sensor data and confirm it is within range.
- tools: gpio_read, kumiho_memory_store
2. **Close valve** — Set GPIO pin 5 LOW.
- tools: gpio_write
- requires_confirmation: true
3. **Review** — Human review before proceeding.
- kind: checkpoint

파서 동작:

  • 번호 항목(1., 2., …)은 단계 순서를 정의합니다. 번호 갭이 있으면 검증 경고가 발생합니다.
  • 앞부분 굵은 텍스트(**제목**)가 단계 제목이 되고, 뒤의 텍스트가 단계 본문입니다.
  • - tools:는 단계의 suggested_tools에 매핑되는 쉼표로 구분된 목록입니다(에이전트에 대한 힌트이며 강제 허용 목록이 아님).
  • - requires_confirmation: true는 해당 단계에 대해 승인 게이트를 강제하며, 해당 단계에 한해 실행 모드를 재정의합니다.
  • - kind: checkpoint(기본값인 - kind: execute와 반대)는 단계를 결정론적 체크포인트로 표시합니다 — SOP가 결정론적 모드로 실행될 때 승인을 위해 일시 정지합니다.

실행 모드는 단계 간 에이전트의 자율성 수준을 제어합니다. 단계별 requires_confirmation: true는 항상 해당 단계에 대해 모드를 재정의합니다.

모드동작
auto승인 프롬프트 없이 모든 단계를 실행합니다.
supervised첫 번째 단계 전에만 승인을 요구합니다.
step_by_step모든 단계 전에 승인을 요구합니다.
priority_basedcritical / high SOP는 auto로 실행되고, normal / lowsupervised로 실행됩니다.
deterministicLLM 호출 없음. 단계가 순차적으로 실행되며, 각 단계의 출력이 다음 단계의 입력으로 전달됩니다. checkpoint 단계는 승인을 위해 일시 정지합니다.

revka sop 서브커맨드는 정의를 관리합니다 — 실행을 시작하지 않습니다. (실행은 트리거 또는 sop_execute 에이전트 도구로 시작됩니다.)

Terminal window
revka sop list # list all loaded SOPs with triggers and mode
revka sop validate # validate all SOPs (warnings on empty fields, missing triggers/steps, numbering gaps)
revka sop validate <name> # validate a single SOP
revka sop show <name> # detailed view of one SOP
명령어목적
revka sop list버전, 우선순위, 모드, 단계 수, 트리거, 쿨다운과 함께 로드된 모든 SOP를 나열합니다.
revka sop validate [name]모든 SOP 또는 이름으로 지정한 SOP 하나를 검증합니다. 빈 name/description, 누락된 트리거, 누락된 단계, 단계 번호 갭에 대해 경고합니다.
revka sop show <name>단일 SOP의 전체 상세 정보를 표시합니다.

revka sop list 출력 예시:

SOPs (3):
deploy-prod v1.0.0 [high] — Deploy service to production
Mode: supervised Steps: 4 Triggers: webhook:/sop/deploy, manual
Cooldown: 300s

~/.revka/config.toml[sop] 섹션은 엔진을 전역적으로 제어하며, SOP.toml의 SOP별 필드는 단일 절차의 동작을 세부 조정합니다.

[sop]
enabled = true
sops_dir = "sops"
default_execution_mode = "supervised"
max_concurrent_total = 10 # global limit across all SOPs
approval_timeout_secs = 3600 # 1 hour before approval-timeout handling

MQTT 트리거에 피드를 제공하는 MQTT 브로커는 [channels_config.mqtt] 아래에 별도로 설정합니다 — MQTT 트리거를 참고하세요.

SOP는 들어오는 이벤트가 [[triggers]] 중 하나와 매칭될 때 실행됩니다. 다섯 가지 type 값이 지원됩니다.

[[triggers]]
type = "mqtt"
topic = "sensors/pressure"
condition = "$.value > 85" # optional JSONPath condition
[[triggers]]
type = "webhook"
path = "/sop/deploy" # exact path match
[[triggers]]
type = "cron"
expression = "0 */5 * * *" # 5/6/7-field crontab
[[triggers]]
type = "peripheral"
board = "nucleo-f401re-0"
signal = "pin_3"
condition = "> 0" # optional numeric comparison
[[triggers]]
type = "manual" # started via the sop_execute tool
타입필드비고
manual없음sop_execute 도구로 시작됩니다(CLI run 명령어 없음).
webhookpath요청 경로(/sop/... 또는 /webhook)에 대한 완전 일치.
mqtttopic, 선택적 conditiontopic+(단일 레벨) 및 #(다중 레벨) MQTT 와일드카드를 지원합니다.
cronexpression5, 6, 또는 7개 필드; 5필드 표현식은 내부적으로 초 필드가 앞에 추가됩니다.
peripheralboard, signal, 선택적 condition신호 키 "{board}/{signal}"에 매칭됩니다.

mqttperipheral 트리거의 condition실패 폐쇄 방식으로 평가됩니다: 잘못된 조건이나 누락/파싱 불가한 페이로드는 매칭이 아닌 매칭 실패를 반환합니다.

  • JSONPath 비교 (MQTT JSON 페이로드에 주로 사용): $.value > 85, $.status == "critical"
  • 직접 숫자 비교 (단순 주변장치 신호에 주로 사용): > 0, == 1
  • 연산자: ==, !=, >, <, >=, <=

MQTT는 기본 IoT/자동화 팬인(fan-in)입니다. MQTT 구독자는 채팅 채널이 아닙니다 — 에이전트 채팅 루프가 아닌 SOP 엔진으로 브로커 메시지를 직접 라우팅합니다. [channels_config.mqtt] 아래에서 브로커를 설정하세요:

[channels_config.mqtt]
broker_url = "mqtts://broker.example.com:8883" # use mqtt:// for plaintext
client_id = "revka-agent-1"
topics = ["sensors/alert", "ops/deploy/#"]
qos = 1 # 0 | 1 | 2
keep_alive_secs = 60
username = "mqtt-user" # optional
password = "mqtt-password" # optional
use_tls = true # must match the scheme (mqtts:// => true)
타입기본값설명
broker_urlstring— (필수)브로커 URL; mqtts://는 TLS를, mqtt://는 평문 연결을 선택합니다.
client_idstring— (필수)MQTT 클라이언트 식별자.
topicslist구독 목록; +# 와일드카드 지원.
qosint1서비스 품질: 0 최대 한 번, 1 최소 한 번, 2 정확히 한 번.
keep_alive_secsint60킵얼라이브 간격.
username / passwordstring선택적 브로커 인증.
use_tlsboolfalseTLS 활성화; broker_url 스킴과 일치해야 합니다.

MQTT 페이로드는 SOP 이벤트 페이로드(event.payload)로 전달되어 단계 컨텍스트에서 사용 가능하므로, SOP 단계에서 트리거 메시지를 읽을 수 있습니다. $.severity >= 2와 같은 트리거 condition으로 매칭하세요.

HTTP를 통해 SOP 실행을 시작할 수 있는 두 가지 게이트웨이 라우트:

메서드 + 경로동작
POST /sop/{*rest}SOP 전용. 웹훅 트리거에 대해 요청 경로를 매칭합니다. 매칭되는 SOP가 없으면 404를 반환합니다 — LLM 폴백이 없습니다.
POST /webhookSOP 우선 디스패치가 있는 채팅 엔드포인트. SOP 매칭을 먼저 시도하고, 매칭되는 항목이 없으면 일반 LLM 흐름으로 폴백합니다.

경로 매칭은 설정된 트리거 path에 대해 완전 일치합니다. path = "/sop/deploy" 트리거는 POST /sop/deploy와 매칭됩니다.

페어링이 활성화된 경우(기본값), 페어링 베어러 토큰을 제공하세요. 웹훅 시크릿이 설정된 경우 두 번째 레이어가 추가됩니다:

POST /sop/deploy
Authorization: Bearer <token>
X-Webhook-Secret: <secret>
X-Idempotency-Key: <unique-key>
Content-Type: application/json
  • Authorization: Bearer <token>POST /pair에서 발급된 페어링 토큰 (페어링 & 인증 참고).
  • X-Webhook-Secret: <secret> — 선택적; 웹훅 시크릿이 설정된 경우에만 필요합니다.
  • X-Idempotency-Key: <key> — 선택적 중복 제거 키. 기본 TTL 300초; 해당 창 내의 중복 요청은 "status": "duplicate"와 함께 200 OK를 반환합니다. 키는 엔드포인트별로 네임스페이스됩니다(/webhook vs /sop/*).

웹훅 라우트는 클라이언트당 속도 제한이 적용됩니다(webhook_rate_limit_per_minute, 기본값 60).

Terminal window
curl -X POST http://127.0.0.1:42617/sop/deploy \
-H "Authorization: Bearer <token>" \
-H "X-Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"message":"deploy-service-a"}'
{
"status": "accepted",
"matched_sops": ["deploy-pipeline"],
"source": "sop_webhook",
"path": "/sop/deploy"
}

전체 웹훅 인그레스 세부 사항은 웹훅 인그레스를 참고하세요.

스케줄러는 캐시된 크론 트리거를 (last_check, now] 구간의 윈도우 기반 검사로 평가하므로, 폴링 경계를 넘어도 실행 시점을 놓치지 않으며, 하나의 윈도우에 여러 실행 시점이 포함되더라도 주어진 표현식은 틱당 최대 한 번 디스패치됩니다. 잘못된 크론 표현식은 캐시 빌드 시 실패 폐쇄됩니다. 크론 트리거는 데몬(revka daemon)이 실행 중이어야 합니다. 표현식 구문 및 시간대는 크론 개요 & 표현식을 참고하세요.

MQTT, 웹훅, 크론, 주변장치, sop_execute 도구 등 모든 소스가 단일 디스패처 dispatch_sop_event로 수렴하여 시스템에 세 가지 일관된 보장을 제공합니다:

  • 단일 매처 경로. 소스에 관계없이 트리거 매칭이 동일하므로, 동일한 condition 및 경로/토픽 규칙이 모든 곳에 적용됩니다.
  • 실행 시작 감사. 시작된 모든 실행은 실행이 진행되기 전에 감사 로거가 기록합니다(감사 로거 참고).
  • 헤드리스 안전성. 에이전트 루프 컨텍스트가 없는 경우(예: 활성 에이전트 턴 없이 웹훅이 도착), ExecuteStep 액션은 자동으로 실행되지 않고 보류(pending) 상태로 로그됩니다. ExecuteStep 단계를 처리하려면 에이전트 루프를 실행하거나, 승인에서 일시 정지하도록 SOP를 설계하세요.

단일 인바운드 이벤트가 여러 SOP와 매칭될 수 있으며, 응답의 matched_sops에 시작된 각 SOP가 나열됩니다.

각 실행은 최대 7가지 상태를 거칩니다:

상태설명
pending생성되었지만 아직 시작되지 않음.
running활성 실행 중.
waiting_approval승인 게이트에서 일시 정지됨.
paused_checkpoint결정론적 체크포인트에서 일시 정지됨.
completed모든 단계가 성공적으로 완료됨.
failed단계 실패.
cancelled사용자 또는 시스템에 의해 취소됨.

실행은 pending에서 시작하여 running으로 이동하고, 운영자가 sop_approve로 해결할 때까지 waiting_approval(모드/단계 게이트) 또는 paused_checkpoint(결정론적 체크포인트)에서 일시 정지됩니다. sop_status 도구로 라이브 상태를 조회하세요.

SOP 동시성, 쿨다운, 승인 타임아웃

섹션 제목: “SOP 동시성, 쿨다운, 승인 타임아웃”

세 가지 독립적인 제한이 SOP의 과도한 실행을 방지합니다:

# Global, in config.toml
[sop]
max_concurrent_total = 10 # across all SOPs
approval_timeout_secs = 3600 # wait at an approval gate before timeout handling (0 = forever)
# Per-SOP, in SOP.toml
cooldown_secs = 300 # minimum seconds between runs of this SOP (0 = none)
max_concurrent = 1 # max simultaneous runs of this SOP
범위필드기본값설명
전역max_concurrent_total10모든 SOP에 걸친 최대 동시 실행 수.
전역approval_timeout_secs3600타임아웃 처리 전까지 승인 게이트에서 대기하는 시간(초) (0 = 타임아웃 없음).
SOP별cooldown_secs0하나의 SOP 실행 간 최소 대기 시간(초).
SOP별max_concurrent1하나의 SOP의 최대 동시 실행 수.

승인 타임아웃 동작은 우선순위를 인식합니다. 게이트가 approval_timeout_secs를 초과하면:

  • critical / high 우선순위 SOP는 자동 승인되어 계속 진행됩니다(자동 승인은 감사 추적에 기록됩니다).
  • normal / low 우선순위 SOP는 수동 결정을 위해 무기한 대기합니다.

결정론적 모드는 LLM 호출 없이 SOP를 순수한 파이프라인으로 실행합니다: 단계가 순차적으로 실행되고 각 단계의 출력이 다음 단계의 입력으로 전달됩니다. 모든 단계가 완전히 명세되어 있고 속도, 반복성, 토큰 비용 제로를 원하는 기계적 시퀀스(하드웨어 액추에이션, 고정 데이터 변환)에 이상적입니다.

SOP.toml에서 deterministic = true 또는 execution_mode = "deterministic"으로 활성화한 다음, SOP.md에서 사람 검토 지점을 체크포인트로 표시하세요:

[sop]
name = "valve-shutdown"
description = "Mechanical valve shutdown sequence"
version = "1.0.0"
priority = "critical"
deterministic = true # forces deterministic mode
[[triggers]]
type = "peripheral"
board = "nucleo-f401re-0"
signal = "pin_3"
condition = "> 0"
## Steps
1. **Read pressure** — Sample the pressure sensor.
- tools: gpio_read
2. **Confirm shutdown** — Operator review before actuation.
- kind: checkpoint
3. **Close valve** — Drive the valve closed.
- tools: gpio_write

checkpoint 단계에서 실행이 일시 정지(paused_checkpoint)되고 상태가 JSON 파일({sop_dir}/{run_id}.state.json 또는 시스템 임시 디렉터리)에 저장됩니다. 검토 후 sop_approve 도구로 재개하세요. 각 실행은 llm_calls_saved를 보고하며, 엔진은 모든 결정론적 실행에 걸친 누적 합계를 유지합니다.

모든 실행 시작은 SopAuditLogger에 의해 Memory 백엔드의 sop 카테고리에 기록되어, 어떤 SOP가 언제 어떤 이벤트 소스에서 실행되었는지에 대한 감사 추적을 제공합니다. 일반적인 키 패턴:

키 패턴기록 내용
sop_run_{run_id}실행 스냅샷 (시작 및 완료 업데이트).
sop_step_{run_id}_{step_number}단계별 결과.
sop_approval_{run_id}_{step_number}운영자 승인 기록.
sop_timeout_approve_{run_id}_{step_number}타임아웃 자동 승인 기록 (우선순위 에스컬레이션).

CLI로 정의를 검사하고(revka sop list / show), sop_status 도구로 라이브 실행 상태를 확인하세요. [observability] backend = "prometheus"인 경우, GET /metrics에서 revka_* 런타임 메트릭 패밀리가 노출됩니다. SOP별 집계는 include_metrics: true와 함께 sop_status를 통해 사용 가능합니다. 더 넓은 감사 및 메트릭 표면은 감사 로그관찰 가능성 & 트레이싱을 참고하세요.

에이전트 세션 내에서 네 가지 MCP 도구가 SOP 실행을 시작하고 구동합니다:

도구목적
sop_execute <name>이름으로 SOP를 수동으로 트리거합니다(manual 트리거를 충족).
sop_status <run_id>현재 실행 상태 및 단계 결과를 가져옵니다. 신뢰 단계/게이트 평가기 상태는 include_gate_status: true로, SOP 메트릭 집계는 include_metrics: true로 전달하세요.
sop_approve <run_id>승인 게이트 또는 결정론적 체크포인트에서 일시 정지된 실행을 승인합니다.
sop_advance <run_id> <result>단계 결과를 보고하고 실행을 다음 단계로 진행합니다.

이 도구들은 에이전트의 나머지 스케줄링 및 오케스트레이션 도구들과 함께 스케줄링 & SOP 도구에 문서화되어 있습니다.