가이드How-to

바인딩 설정

메신저 채널을 자체 모델과 정책을 가진 세션 레인으로 라우팅하는 방법입니다.

이 문서의 목차
  1. 1. config.toml에 바인딩을 선언합니다
  2. 2. 세션 레인으로 라우팅됩니다
  3. 3. 리로드합니다
  4. 확인

바인딩은 들어오는 메신저 메시지를 GEODE 처리로 보내는 정적 규칙입니다. 라우팅에 LLM을 쓰지 않습니다. 채널과 채널 ID가 정확히 일치하는 메시지만 실행으로 흘러가고, 바인딩 없는 채널의 메시지는 무시됩니다. 바인딩이 곧 "어느 채널이 GEODE를 깨울 수 있는가"의 화이트리스트입니다.

1. config.toml에 바인딩을 선언합니다

바인딩은 프로젝트의 .geode/config.toml [gateway] 섹션에서 선언합니다. 이 섹션은 신뢰한 폴더에서만 읽고, 전역 ~/.geode/config.toml의 [gateway]는 같은 형식이며 신뢰가 필요 없습니다. ChannelManager.load_bindings_from_config(core/messaging/binding.py)이 이 형식을 읽습니다. 각 규칙은 channel과 channel_id가 필수입니다. channel_id가 비어 있으면 그 규칙은 건너뜁니다. 빈 ID는 모든 채널에 응답하는 위험한 catch-all이 되기 때문입니다.

# .geode/config.toml
[gateway]
pollers = ["slack"]
time_budget_s = 120        # gateway-level default per message

[[gateway.bindings.rules]]
channel = "slack"
channel_id = "C0ABCDEF1"
auto_respond = true
require_mention = true
allowed_tools = ["memory_search", "web_fetch"]
time_budget_s = 90

각 규칙은 자체 정책 손잡이를 가집니다. require_mention은 GEODE가 멘션됐을 때만 응답하게 하고, allowed_tools는 그 채널에서 허용할 도구를 제한하며(빈 리스트는 전체 허용), time_budget_s는 메시지당 wall-clock 예산을 지정합니다. 시간 예산은 0 이상의 유한한 수, 횟수 제한은 0 이상의 정수여야 합니다. 숫자 필드에 불리언은 사용할 수 없습니다.auto_respond=false는 처리를 계속하고 세션은 저장하되 채널로 최종 텍스트를 보내지 않습니다. 헤드리스 denylist는 바인딩 allowlist보다 항상 우선합니다. 규칙에 없으면 gateway 레벨 기본값으로 떨어집니다. 이 필드들은 ChannelBinding(core/messaging/models.py)의 dataclass 필드와 일대일로 대응합니다.

2. 세션 레인으로 라우팅됩니다

메시지가 바인딩에 매칭되면 ChannelManager.aroute_message가 build_gateway_session_key(channel, channel_id, sender_id, thread_id)로 thread 단위 세션 키를 만듭니다. 같은 스레드의 메시지는 같은 키로 묶여 컨텍스트가 격리됩니다. 실행은 SessionLane → gateway Lane → global Lane 순서로 레인 큐를 거치므로, 같은 세션의 메시지는 직렬화되고 동시성은 워크로드별 상한으로 제어됩니다. allowed_tools는 사용자 콘텐츠에 문자열로 삽입되지 않습니다. 구조화된 메타데이터로 세션 조립에 전달되어 AgenticLoop의 모델 가시 도구와 ToolExecutor의 실제 실행을 함께 제한합니다. provider adapter가 뒤늦게 추가하는 hosted tool도 같은 allowlist를 확인하므로 Anthropic, OpenAI, GLM 경로가 같은 계약을 따릅니다. 중단된 ask를 다른 binding에서 재개하면 두 allowlist의 교집합과 더 짧은 시간 예산만 사용합니다.

3. 리로드합니다

바인딩은 두 시점에 로드됩니다. serve 부팅 시 한 번 (core/wiring/adapters.py에서 load_bindings_from_config(toml_config) 호출), 그리고 config.toml이 바뀔 때마다입니다. ConfigWatcher가 파일 변경을 감지해 load_bindings_from_config를 다시 부르므로 serve를 재시작하지 않아도 새 바인딩이 적용됩니다. 파일 삭제나 교체도 감지하며, 전역·프로젝트 설정을 합친 후보를 검증한 뒤 바인딩을 한 번에 교체합니다. 읽기·파싱·검증에 실패하면 기존 바인딩을 유지하고 debounce 이후 재시도합니다. 삭제된 파일의 규칙은 제거되고, 합쳐진 규칙이 빈 배열이면 모든 바인딩을 해제합니다. 함수에 규칙이 없는 설정을 직접 전달하면 기존 바인딩을 유지하고,rules = []를 명시하면 해제합니다. 채널 ID가 없는 규칙은 건너뛰지만, 비어 있지 않은 후보의 모든 규칙이 이 사유로 제외되면 실패로 처리합니다. serve 종료 시 감시자도 종료합니다. 실행 중인 콜백 때문에 종료가 지연되면 오류를 보고하고 이전 감시자가 끝날 때까지 중복 시작을 차단합니다. poller 구성과 serve 실행 기본값 변경은 재시작 후 적용됩니다.

확인

바인딩이 실제로 로드됐는지 활성 gateway에서 확인합니다.

uv run python -c "
from core.messaging.binding import ChannelManager
from core.wiring.adapters import _load_gateway_config

cfg, sources = _load_gateway_config()  # global + trusted project, as serve reads it
print('sources', sources)
m = ChannelManager()
n = m.load_bindings_from_config(cfg)
print('loaded', n, 'bindings')
for b in m.list_bindings():
    print(b)
"

로드된 바인딩 수와 각 규칙의 channel / channel_id / auto_respond / allowed_tools / time_budget_s가 출력되면 라우팅이 그 채널을 인식할 수 있습니다. 실제 메시지 라우팅과 poller 운영은 serve gateway 페이지를 참고하세요.

참조: Serve gateway, Messaging.

GEODE 저장소의 문서 사이트에서 옮겨 온 문서입니다. 원문 커밋 de077a4 · GitHub에서 원문 보기