Skip to main content

훅이 존재하는 이유

시스템 프롬프트의 지시사항은 제안입니다. 충분히 고집스럽거나 혼란스러운 LLM은 이를 무시할 수 있습니다. 대부분의 에이전트 동작에서는 정확히 그것이 원하는 것입니다 — 지시사항은 모델이 적응할 수 있는 여지를 제공합니다. 하지만 일부 요구사항은 제안이 아닙니다. “모든 민감한 도구 호출은 반드시 기록되어야 한다.” “쓰기 작업은 조직이 읽기 전용 모드일 때 차단된다.” “¥50k 이상의 결제는 실행 전에 사람의 승인이 필요하다.” 이것들은 불변식입니다 — 모델이 어떤 턴에서 결정하든 관계없이 반드시 유지되어야 하는 시스템의 사실입니다. 훅은 에이전트의 실행 생명주기에서 잘 정의된 지점에서 LLM 루프 외부에서 실행되는 코드입니다. LLM은 훅을 볼 수 없습니다. LLM은 훅에 이의를 제기할 수 없습니다. LLM은 훅을 단계를 건너뛰도록 설득할 수 없습니다. PreToolUse 훅이 allow=False를 반환하면, 추론 추적이 아무리 강력하더라도 도구 호출은 발생하지 않습니다. 이것이 중요한 아키텍처 구분입니다: 훅은 FIM One이 “에이전트는 ~해야 한다”를 “에이전트는 ~할 수 없다”로 바꾸는 방법입니다.

훅이 연결되는 위치

현재 세 가지 훅 포인트가 정의되어 있습니다. 각각은 에이전트가 한 번의 루프 반복 중에 통과하는 경계를 표시합니다: 같은 포인트의 여러 훅은 우선순위 순서대로 실행됩니다. 이전 PreToolUse 훅의 재작성된 인자는 이후 훅으로 전달되므로 미들웨어가 구성됩니다.

훅 vs. 명령어 선택 기준

요구사항을 프롬프트 명령어로 해결할지 훅으로 해결할지 결정하는 것은 “런타임 어설션 vs. 코드 주석” 계산과 동일합니다: 경험칙: 잘못된 동작이 인시던트라면 훅을 사용하세요. 잘못된 동작이 사소한 불편함이라면 명령어로 충분합니다.

훅 계약

훅은 PreToolUseHook, PostToolUseHook, 또는 SessionStartHook의 서브클래스이며 하나의 필수 메서드를 가집니다:
전달된 HookContext는 tool_name, tool_args, agent_id, user_id, 그리고 엔진이 요청별 사실(조직 id, 대화 id, 커넥터 작업의 requires_confirmation 플래그 등)로 채우는 유연한 metadata 딕셔너리를 포함합니다. 반환된 HookResult는 결과를 제어합니다:
  • allow: bool = True — 도구 호출 진행 여부 (PostToolUse / SessionStart에서는 무시됨)
  • error: str | None — 인간이 읽을 수 있는 이유로, 차단될 때 LLM에 관찰로 표시됨
  • modified_args: dict | None — 설정된 경우, 실행 전에 도구 인자를 대체함
  • modified_result: Any | None — 설정된 경우 (PostToolUse), LLM으로 반환되기 전에 관찰을 대체함
  • side_effects: list[str] — 훅이 수행한 작업의 감사 추적으로, 에이전트의 추적에 병합됨

사례 연구: FeishuGateHook

이 시스템 위에 출시된 첫 번째 훅은 FeishuGateHook입니다. 이는 PreToolUse 훅으로, requires_confirmation=True로 표시된 모든 도구를 조직의 Feishu 그룹에 게시된 인간 승인 카드로 변환합니다. 이 훅은 전체 생명주기를 실행합니다: 이 설계가 제공하는 것:
  • 도구 호출이 진정으로 일시 중지됩니다. 에이전트의 SSE 스트림은 “I will call oa__purchase_pay”와 관찰 사이에서 일시 중지됩니다. 사용자는 에이전트가 대기 중인 것을 보며, 이는 내부에서 일어나는 일과 일치합니다.
  • 승인이 프로세스 재시작을 견딥니다. 대기 중인 행은 데이터베이스에 있으며, 메모리에는 없습니다. 카드가 미결 상태일 때 백엔드가 재시작되면, 다음 폴링이 중단된 지점부터 계속됩니다.
  • 결정이 감사됩니다. ConfirmationRequest는 payload, responded_at, responded_by_open_id 및 최종 상태를 유지합니다. 누가 무엇을 언제 승인했는지에 대한 감사 가능한 기록입니다.
  • 의사 결정 루프에 LLM이 없습니다. 모델이 도구 호출을 생성합니다. 인간이 판정을 생성합니다. 훅은 결정론적 다리입니다.
FeishuGateHook은 구성된 Feishu Channel에 의존합니다. 훅은 채널의 send_interactive_card() 메서드를 통해 카드를 전송하고 채널이 파싱한 콜백 이벤트를 수신합니다. 이러한 분리는 의도적입니다. 훅은 “승인 상태 머신”을 소유하고, 채널은 “IM 플랫폼 메커니즘”을 소유합니다. 동일한 훅은 내일 Slack이나 WeCom을 대상으로 할 수 있으며, 로직을 변경하지 않고 채널 구현만 변경하면 됩니다.

후보 훅 (계획 없음)

네 가지 훅 패턴이 동일한 라이프사이클에 적용됩니다. 현재 로드맵에는 포함되지 않았으며, 배포 환경에서 필요해질 때까지 보류됩니다. 사용자 정의 훅 계층도 같은 조건으로 보류되어 있습니다. 에이전트별 YAML 구성(hooks: [...])에 일치하는 도구 이벤트에서 실행할 셸 명령이나 Python 호출 가능 객체를 선언하는 방식입니다. 이는 최신 에이전트 프레임워크(Claude Code, OpenDevin)에서 자리 잡은 패턴을 따릅니다. 훅 기반 시행을 사용하면 “항상 수행되어야 하는” 로직을 프롬프트에서 분리할 수 있습니다.

Hooks vs. Channels

두 추상화는 직교하는 문제를 해결합니다: Hooks는 Channels를 사용합니다 — 외부 세계와 통신해야 하는 hook(카드 전송, 알림 게시, 그룹으로 에스컬레이션)은 조직의 Channel을 호출합니다. 이를 사용하는 hook이 없는 channel도 여전히 유용합니다(예: 에이전트가 도구를 통해 사전에 알림을 보낼 수 있음). 하지만 승인 게이트 패턴은 특히 두 부분이 모두 준비되어 있어야 합니다. 다르게 말하면: Channels는 “인간과 어떻게 통신할 것인가”라는 인프라이고, Hooks는 “언제 인간과 통신해야 하는가”라는 정책입니다. 프로덕션 인간-루프 워크플로우에는 둘 다 필요합니다.

현재 상태 (v0.8.4)

출시된 항목과 앞으로 남은 항목의 스냅샷입니다.
  • ✅ HookRegistry, HookContext, HookResult 프리미티브를 ReAct와 DAG 모두에 연결
  • ✅ PreToolUseHook / PostToolUseHook / SessionStartHook 추상 기반 클래스
  • ✅ FeishuGateHook — ConfirmationRequest 테이블, 폴링 루프, 시간 초과/만료, 콜백 기반 상태 변경을 포함해 완성
  • ✅ card.action.trigger를 디코딩하고 대기 중인 행을 업데이트하는 Feishu 채널 콜백 엔드포인트
  • ✅ 에이전트 수준 훅 선언: agent.model_config_json.hooks.class_hooks가 모든 ReAct/DAG 세션에서 인스턴스화된 HookRegistry로 확인됨
  • ✅ 모든 실행 경로에서 훅이 실행됩니다: 기본 채팅 경로(Portal, API, DAG), 위임된 하위 에이전트(CallAgentTool), Workflow AGENT 노드. Eval Center는 의도적으로 훅을 우회합니다(자동 평가가 사람의 승인을 기다리느라 차단되면 안 됩니다). 위임된 에이전트는 호출자의 레지스트리를 상속하지 않습니다. 자체 model_config_json으로 별도의 레지스트리를 구성합니다. 확인 게이트는 모든 에이전트에 자동으로 연결되므로, 레지스트리를 다시 구성하면 상속보다 더 많은 항목이 포함됩니다. 즉, 위임된 에이전트는 게이트에 더해 자체적으로 선언한 항목도 가져오며, 게이트는 호출자의 require_confirmation_for_all이 아니라 위임된 에이전트의 값을 확인합니다. 두 실행 경로 모두 fail closed로 동작합니다. 훅을 구성할 수 없는 에이전트는 실행되지 않습니다.
  • ❌ AuditLogHook, ReadOnlyGuard, ResultTruncateHook, ConnectorRateLimitHook (계획 없음)
  • ❌ 사용자 정의 YAML 훅 선언 (계획 없음)
훅 시스템은 프로덕션 강화의 핵심 기반입니다. 첫 번째 사용자 기능인 FeishuGateHook 자체도 프로덕션 기능이므로, 전체 훅 카탈로그가 완성될 때까지 기다리는 대신 2026-04-24 로드쇼에 맞춰 뼈대를 먼저 출시했습니다.