채널 자율성 및 승인 정책
Telegram, Discord 등의 채널에서 도구 호출이 "비대화형 채널 승인 정책에 의해 거부됨" 오류를 받는 이유, 도구 승인 게이트와 경로 샌드박스 게이트의 차이점, 그리고 채널에서 에이전트가 워크플로를 생성하고 실행할 수 있도록 허용하는 방법입니다.
채널(Telegram, Discord, Slack 등)에서 Revka를 구동할 때, 도구 호출은 터미널에서보다 더 엄격한 정책 하에 실행됩니다. 에이전트가 다음과 같은 메시지를 보고하는 경우:
❌ Denied by non-interactive channel approval policy.
…채널 승인 게이트에 걸린 것입니다. 이 페이지에서는 그 게이트가 무엇인지, 사람들이 가장 자주 혼동하는 두 가지 독립적인 정책 레이어, 하나의 비직관적인 함정(tool_search), 그리고 채널에서 에이전트가 워크플로를 생성하고 실행할 수 있도록 하는 정확한 구성을 설명합니다.
채널이 다른 이유: 대화형 vs 비대화형
섹션 제목: “채널이 다른 이유: 대화형 vs 비대화형”Revka의 자율성 모델은 감독(supervised) 모드에서 사람이 위험한 도구 호출이 실행되기 전에 승인할 수 있다고 가정합니다.
| 인터페이스 | 모드 | 승인이 필요한 도구에서 발생하는 일 |
|---|---|---|
| CLI | 대화형 | [Y]es / [N]o / [A]lways 프롬프트가 표시됨 |
| 채널 (Telegram, Discord, …) | 비대화형 | 프롬프트를 확인할 운영자가 없으므로 호출이 자동 거부됨 |
따라서 채널에서 “승인 필요”는 사실상 “거부”를 의미합니다. 이는 안전 기본값으로, 무인 봇이 검토를 거쳐야 했을 부작용이 있는 동작을 자동으로 수행하는 것을 방지합니다.
두 가지 게이트 (혼동하지 마세요)
섹션 제목: “두 가지 게이트 (혼동하지 마세요)”단일 파일 쓰기는 두 가지 독립적인 검사를 통과합니다. 실패 메시지와 수정 방법이 다릅니다:
-
도구 승인 게이트 — 이 도구를 호출할 수 있는가?
[autonomy] level,auto_approve,always_ask에 의해 구동됩니다. 실패 메시지: “Denied by non-interactive channel approval policy.” -
경로 샌드박스 — 파일 도구가 읽거나 쓸 수 있는 위치는 어디인가?
[autonomy] workspace_only,allowed_roots,forbidden_paths에 의해 구동됩니다. 승인 게이트와 독립적으로 도구 내부에서 시행됩니다. 실패 메시지: “Path not allowed by security policy: …” 또는 “Resolved path escapes workspace allowlist: …” 와 같은 경로 오류. 쓰기 도구에 대한 읽기 전용 차단은 “Action blocked: autonomy is read-only” 로 표시됩니다.
중요한 결과: 완전히 허용된 경로에 쓰기를 해도 도구가 승인되지 않았다면 거부될 수 있습니다 — 그리고 승인된 도구도 샌드박스 외부의 경로는 거부될 수 있습니다. 잘못된 레이어를 수정하면 도움이 되지 않습니다.
승인 결정 방법
섹션 제목: “승인 결정 방법”채널에서 각 도구 호출에 대해 Revka는 순서대로 다음을 평가합니다:
level = "full"→ 승인이 필요 없습니다 (모든 것이 허용됨).level = "read_only"→ 부작용이 있는 도구는 다운스트림에서 차단됩니다.- **
always_ask**에"*"또는 도구 이름이 포함됨 → 항상 승인 필요 → 채널에서 자동 거부 (아래 모든 항목보다 우선 적용). shell도구 → 외부 게이트가 아닌 자체 명령 허용 목록 (allowed_commands/block_high_risk_commands)에 의해 관리됩니다.- MCP 네임스페이스 도구 (이름에
__포함, 예:revka-operator__run_workflow,kumiho-memory__kumiho_memory_engage) → 채널에서 자동 승인. - **
auto_approve**에"*"또는 도구 이름이 포함됨 → 허용됨. - 그 외 (supervised 기본값) → 승인 필요 → 채널에서 자동 거부.
핵심 요점: 단순 이름의 내장 도구
섹션 제목: “핵심 요점: 단순 이름의 내장 도구”이 규칙(5단계 vs 7단계)이 대부분의 채널 문제의 핵심입니다:
- 내장 도구는 단순 이름을 가집니다 —
file_read,file_write,shell,tool_search,browser등. 채널에서 자동 승인되지 않습니다. 기본auto_approve목록의 읽기 전용 도구들만 기본적으로 작동합니다; 그 외에는 명시적으로 추가해야 합니다. - MCP / 운영자 도구는
__로 네임스페이스가 지정됩니다 — 기본적으로 채널에서 자동 승인됩니다.
따라서 채널 워크플로를 활성화하려면 일반적으로 관련된 단순 이름의 내장 도구(tool_search, file_write)만 허용 목록에 추가하면 됩니다. 운영자 워크플로 도구 자체(revka-operator__create_workflow 등)는 이미 __ 규칙에 의해 허용됩니다.
비직관적인 부분: tool_search
섹션 제목: “비직관적인 부분: tool_search”Revka는 기본적으로 지연 도구 로딩을 사용합니다. 컨텍스트 창을 작게 유지하기 위해, 대부분의 운영자 및 MCP 도구는 처음부터 로드되지 않습니다 — 시스템 프롬프트에는 경량 스텁만 나열됩니다. 에이전트가 지연된 도구를 호출하기 전에, 먼저 내장 tool_search 도구를 호출하여 해당 도구의 전체 스키마를 가져와야 합니다.
tool_search는 단순 이름을 가지므로, 허용 목록에 추가하지 않으면 채널에서 자동 거부됩니다 — 그리고 모든 지연 도구의 게이트웨이이기 때문에, 에이전트가 create_workflow나 run_workflow에 도달하기 전에 차단됩니다. 표시되는 거부 메시지는 tool_search에 대한 것이지만, 실제 요청은 워크플로에 관한 것이었습니다.
tool_search는 도구 스키마만 컨텍스트에 로드하며, 부작용이 없습니다. 또한 표시되는 모든 도구는 여전히 개별적으로 게이트됩니다. 자동 승인하는 것이 안전합니다.
레시피: 채널에서 워크플로 생성 및 실행
섹션 제목: “레시피: 채널에서 워크플로 생성 및 실행”흐름에 필요한 단순 이름의 내장 도구를 [autonomy].auto_approve에 추가한 다음,
데몬을 재시작합니다 (구성은 시작 시 읽힘):
[autonomy]level = "supervised"
auto_approve = [ # 읽기 전용 기본값 (유지) "file_read", "web_search_tool", "web_fetch", "calculator", "glob_search", "content_search", "image_info", "weather",
# 채널 기반 워크플로에 필요: "tool_search", # 지연된 운영자/MCP 도구 활성화 "file_write", # 워크플로 YAML을 ~/.revka/workflows에 쓰기
# 선택 사항 — 이미 "__" 규칙에 의해 자동 승인되지만, 여기에 # 나열하면 이전 버전도 지원됨: "create_workflow", "run_workflow", "get_workflow_status",]
# 내장 기본값은 ~/.revka/workflows만 있습니다. 워크플로가# workspace 디렉터리 외부에 쓰기가 필요한 경우 아티팩트/워크스페이스# 루트를 명시적으로 추가하세요.allowed_roots = ["~/.revka/workflows", "~/.revka/artifacts", "~/.revka/workspace"]
always_ask = [] # "*" 또는 워크플로 도구가 포함되어서는 안 됨그러면 종단 간 채널 흐름이 완료됩니다:
tool_search → file_write (YAML을 ~/.revka/workflows/에) → run_workflow
→ get_workflow_status.
워크플로가 쓰는 위치와 경로가 이미 허용된 이유
섹션 제목: “워크플로가 쓰는 위치와 경로가 이미 허용된 이유”~/.revka/workspace는 workspace_dir이므로, 경로 샌드박스가 자동으로 그곳에 쓰기를 허용합니다. ~/.revka/workflows는 내장 기본 allowed_roots의 유일한 항목입니다 — workspace_dir 외부에 있지만, allowed_roots에 있기 때문에 파일 도구가 거기에 쓸 수 있습니다. ~/.revka/artifacts는 기본 루트가 아닙니다: 워크플로가 직접 거기에 쓰기가 필요하다면 allowed_roots에 직접 추가하세요. 워크플로 쓰기가 (경로 메시지가 아닌) 승인 메시지로 실패한다면, 경로가 문제가 아닙니다; file_write 도구가 단순히 허용 목록에 추가되지 않은 것입니다.
경로 샌드박스는 level에 관계없이 파일 도구에 적용됩니다 — level = "full"이라도, 쓰기는 여전히 workspace_dir + allowed_roots로 제한되고 forbidden_paths 하에 차단됩니다. 자율성은 도구가 실행될지 여부를 제어하고; 샌드박스는 파일이 어디로 갈 수 있는지를 제어합니다.
실행 위치: 워크플로 실행은 채널 게이트를 받지 않음
섹션 제목: “실행 위치: 워크플로 실행은 채널 게이트를 받지 않음”run_workflow는 워크플로 엔진에서 백그라운드 작업으로 실행을 시작하고 즉시 반환합니다. 워크플로의 내부 단계(에이전트 생성, 셸, 파일 단계 등)는 채팅 턴 중 에이전트의 직접 도구 호출을 관리하는 채널 승인 게이트가 아닌 워크플로 엔진에 의해 관리됩니다.
이 예외는 의도적입니다: human_approval 단계를 정의하는 워크플로는 채널에서 승인 요청 메시지에 응답하여 승인하도록 일시 중지합니다. 이것은 자율성 정책이 아닌 워크플로의 기능입니다.
보안 자세: 표적형 vs 전체형
섹션 제목: “보안 자세: 표적형 vs 전체형”| 접근 방식 | 구성 | 트레이드오프 |
|---|---|---|
| 표적형 (권장) | level = "supervised" + 특정 도구만 허용 목록에 추가 | 최소 권한; 실제로 필요한 경우에만 도구를 추가합니다. 경로 샌드박스가 여전히 모든 파일 쓰기를 제한합니다. |
| 전체형 | level = "full" | 모든 채널 도구 호출에 승인 게이트 없음. 가장 간단하지만 가장 넓은 영향 범위. 단일 소유자, 신뢰할 수 있는 봇에게 합리적입니다. 파일 쓰기는 여전히 allowed_roots에 의해 샌드박스됩니다. |
제한 사항: 채널별 자율성 없음
섹션 제목: “제한 사항: 채널별 자율성 없음”자율성 설정은 모든 비대화형 채널에 균일하게 적용됩니다. 현재 채널별 재정의가 없습니다 — 구성으로 Telegram에서는 도구를 자동 승인하면서 Discord에서는 계속 프롬프트를 표시하도록 할 수 없습니다. 채널별 세분성을 위해서는 코드 변경이 필요합니다.
문제 해결
섹션 제목: “문제 해결”- “Denied by non-interactive channel approval policy” → 단순 이름의 도구가
허용 목록에 없습니다. 어떤 도구인지 확인하려면,
[channels_config] show_tool_calls = true를 설정하고❌ <tool>: …줄을 찾은 다음,<tool>을auto_approve에 추가하세요. - “Path not allowed by security policy …” / “Resolved path escapes workspace
allowlist …” / “Action blocked: autonomy is read-only” → 승인 게이트가 아닌
경로 샌드박스 또는 읽기 전용 게이트입니다.
allowed_roots,workspace_only, 그리고level이read_only가 아닌지 확인하세요. - 편집이 무시되는 것 같음 → 데몬을 재시작하세요;
config.toml은 시작 시 읽힙니다. always_ask가"*"로 설정됨 → 이것은auto_approve와__규칙을 재정의하므로, 모든 것이 채널에서 거부됩니다. 제거하세요.
참조: [autonomy] 키
섹션 제목: “참조: [autonomy] 키”| 키 | 기본값 | 효과 |
|---|---|---|
level | "supervised" | read_only | supervised | full. 채널에서 full은 절대 프롬프트를 표시하지 않고; supervised는 달리 허용되지 않은 모든 것을 자동 거부합니다. |
auto_approve | 읽기 전용 도구 (file_read, web_search_tool, web_fetch, calculator, glob_search, content_search, image_info, weather) | 승인을 건너뛰는 도구. 사용자 항목은 기본값과 병합됩니다. "*"를 허용합니다. |
always_ask | [] | 항상 승인이 필요한 도구; auto_approve와 __ 규칙을 재정의합니다. 채널에서는 항상 거부됩니다. "*"를 허용합니다. |
workspace_only | true | 파일 경로를 workspace_dir + allowed_roots로 제한합니다. |
allowed_roots | ["~/.revka/workflows"] | 파일 도구가 워크스페이스 외부에서 읽고 쓸 수 있는 추가 루트. |
forbidden_paths | 시스템 및 민감한 디렉터리 | 워크스페이스/허용된 루트 외부의 경로에 대한 거부 목록. allowed_roots 항목 하의 경로는 우선 적용되어 허용됩니다. |
allowed_commands | 선별된 실행 파일 목록 | shell 도구의 허용 목록. |
block_high_risk_commands | true | rm -rf, chmod 777, curl | sh와 같은 패턴을 강제 차단합니다. |
require_approval_for_medium_risk | true | 중간 위험 셸 명령에 대한 승인 게이트. |
non_cli_excluded_tools | [] | 비CLI 채널에서 완전히 제거되는 도구 (보이지 않으며, 단순히 거부되지 않음). |
max_actions_per_hour | 20 | 정책별 시간당 작업 예산. |
max_cost_per_day_cents | 500 | 정책별 일일 지출 가드레일. |