iop/agent-ops/rules/project/domain/node/rules.md
toki fc33b18e79 docs(agent-ops): 도메인 룰을 현재 구조에 맞춘다
코드 구조와 도메인 소유권 문서의 불일치를 제거해 후속 작업이 올바른 규칙과 경계를 로드하도록 한다.
2026-07-30 20:55:52 +09:00

11 KiB

domain last_rule_review_commit last_rule_updated_at
node 4695bcbc60 2026-07-30

node

목적 / 책임

Edge에 연결되어 실제 adapter execution을 수행하는 IOP 노드 에이전트 영역이다. Edge에서 들어온 실행·취소·조회성 명령을 공통 Agent Runtime 요청으로 변환하고, 공통 registry/provider를 Node transport와 연결하며, 실행 이벤트와 현재 단계의 로컬 실행 이력을 관리한다.

포함 경로

  • apps/node/cmd/node/ — node CLI 진입점과 서브커맨드
  • apps/node/internal/bootstrap/ — fx 의존성 주입과 adapter registry 구성
  • apps/node/internal/node/ — transport handler 구현과 실행 오케스트레이션
  • apps/node/internal/router/ — RunRequest를 ExecutionSpec으로 해석하는 라우팅
  • apps/node/internal/transport/ — edge와의 TCP/protobuf 세션 및 메시지 처리
  • apps/node/internal/adapters/ — Node-owned mock/ollama/vllm/OpenAI-compatible adapter와 Edge config translation
  • apps/node/internal/store/ — SQLite 실행 이력 저장
  • apps/node/README.md — node 실행 흐름과 adapter/session 경계 설명

제외 경로

  • apps/edge/ — Node를 관리하는 실행 그룹 컨트롤러 영역
  • apps/control-plane/ — 여러 Edge 연결 관리와 운영 제어 API 제공 영역
  • apps/worker/ — 비동기 작업 처리 예정 영역
  • packages/go/agentruntime/, packages/go/agentprovider/cli/ — Node가 소비하는 공통 provider/runtime 구현
  • packages/go/의 나머지 영역 — 여러 앱이 공유하는 Go 공통 패키지
  • proto/ — 앱 간 메시지 계약

주요 구성 요소

  • agentruntime.Provider / agentruntime.Router — 공통 provider 실행과 Node routing 계약
  • agentruntime.CommandHandler / agentruntime.SessionTerminator — command와 logical session 종료 optional 계약
  • agentruntime.ProviderProber / agentruntime.ProviderTunnelAdapter — provider availability probe와 raw tunnel optional 계약
  • node.runRequestFromProto() / node.runEventToProto() — Edge-Node protobuf와 공통 runtime request/event translation
  • node.Nodetransport.Handler 구현체이자 실행 파이프라인 조정자
  • node.runManager — run ID 기준 runHandle(cancel, done) 등록/해제/취소 관리; node.Node 내부에서만 사용
  • node.Node.OnConfigRefresh() — Edge가 보낸 NodeConfigRefreshRequest를 적용하고 adapter registry를 live swap
  • node.Node.OnProviderTunnelRequest() — provider tunnel 요청을 지원 adapter에 전달하고 tunnel frame을 edge session으로 반환
  • node.sessionSink — adapter RuntimeEvent를 proto RunEvent로 변환해 edge session으로 보내는 sink
  • transport.Session — edge와 연결된 node 세션 및 메시지 처리
  • bootstrap.runtimeSupervisor — 초기 연결과 reconnect를 직렬화하고 단일 active Edge session, bounded retry, fatal shutdown을 소유하는 Node lifecycle supervisor
  • quota-probe — 공통 CLI status checker 결과를 content-addressed QuotaSnapshot JSON으로 내보내는 내부 진단 command
  • agentruntime.Registry / agentruntime.LifecycleProvider — provider 등록/조회와 start/stop lifecycle 관리
  • adapters.ConfigSet / adapters.DiffConfigSets() — Edge config payload에서 adapter registry/runtime snapshot을 만들고 refresh diff를 산출
  • adapters.BuildFromPayload() — edge에서 받은 NodeConfigPayloadRegistry를 초기화하는 factory
  • adapters/ollama.Ollama — Ollama /api/chat streaming, /api/tags capabilities, /api/* command passthrough를 처리하는 adapter
  • adapters/openai_compat.Adapter — OpenAI-compatible /v1/models, chat completions, provider label/header/options passthrough, provider tunnel을 처리하는 adapter
  • adapters/vllm.Vllm — vLLM/SGLang류 OpenAI-compatible endpoint를 직접 호출하고 provider tunnel을 처리하는 adapter
  • store.Store — 실행 상태와 결과 저장

유지할 패턴

  • transport/proto 타입은 apps/node/internal/node/runtime_bridge.go에서 agentruntime 타입으로 변환한다.
  • 내부 실행 식별자는 adapter + target을 사용한다. 외부 OpenAI-compatible API나 legacy placeholder를 제외하고 model을 내부 실행 대표 용어로 되돌리지 않는다.
  • Edge-Node runtime wire와 Edge가 내려주는 config payload 계약 상세는 agent-contract/inner/edge-node-runtime-wire.mdagent-contract/inner/edge-config-runtime-refresh.md를 기준으로 확인한다.
  • Node-owned 어댑터 추가 시 agentruntime.Provider를 구현하고 adapters.BuildFromPayload()에서 공통 registry에 등록한다. 여러 host가 함께 사용할 provider는 platform-common 경계로 둔다.
  • 여러 adapter instance는 agentruntime.Registry.RegisterKeyed(instanceKey, typeName, provider)로 등록하고, router lookup은 instance key를 우선한다. legacy type-name lookup은 단일 instance일 때만 안전하다.
  • field Node의 기본 시작 경로는 Edge bootstrap script가 만든 최소 config와 Edge가 RegisterResponse로 내려주는 adapter/runtime payload다. 사용자가 기본 경로에서 node config를 직접 작성하거나 adapter/provider 세부값을 명령줄에 넣는 흐름을 만들지 않는다.
  • Node runtime 작업 디렉터리나 store/workspace 경로는 대상 OS에서 쓰기 가능한 기본값이어야 한다. Edge가 특정 node에 workspace_root를 내려줄 때 macOS/dev host 절대 경로(/Users/...) 같은 값을 Linux/Windows node에 재사용하지 않으며, OS별 경로가 필요하면 Edge 설정에 미리 굽는다.
  • 실행 취소는 run ID 기준으로 runManager에 등록하고 실행 종료 시 반드시 deregister로 해제한다.
  • CancelAction_CANCEL_RUN은 현재 run 취소, CancelAction_TERMINATE_SESSION은 logical session 종료로 구분한다.
  • ProviderTunnelRequest는 run ID/tunnel ID 기준으로 runManager에 등록하고, ProviderTunnelFrame은 RunEvent stream과 별도 proto message로 edge에 반환한다. tunnel 지원은 agentruntime.ProviderTunnelAdapter를 구현한 adapter에만 허용한다.
  • NodeCommandRequest는 실행 요청과 분리해 USAGE_STATUS, CAPABILITIES, SESSION_LIST, TRANSPORT_STATUS 같은 조회/제어성 명령으로 처리한다.
  • OLLAMA_API command는 Ollama adapter 내부의 제한된 /api/* passthrough로 처리하고, Edge/OpenAI surface가 node HTTP client를 우회해 직접 Ollama에 붙는 구조로 확장하지 않는다.
  • agentruntime.Registry의 start/stop은 bootstrap lifecycle에서만 호출하고 개별 provider에서 직접 호출하지 않는다.
  • Edge 연결 lifecycle은 runtimeSupervisor 하나가 초기 dial, active session 종료 대기, reconnect와 shutdown을 직렬화해 동시에 둘 이상의 dial/session이 생기지 않도록 유지한다.
  • quota-probe는 provider 원문이나 credential을 내보내지 않고 공통 status package가 정규화·검증할 수 있는 quota evidence만 출력한다.
  • response_idle_timeout_ms, startup_idle_timeout_ms, completion_marker, resume_args, mode 같은 CLI profile 설정은 edge config/proto payload를 통해 주입하고 node 코드에 target별 상수를 늘리지 않는다.
  • config refresh는 adapters.BuildConfigSet()로 next registry를 만들고 start 성공 후 router registry를 live swap한다. 기존 in-flight run은 old adapter snapshot으로 마무리하고, old registry stop은 active run drain 뒤에 처리한다.
  • Node-wide runtime concurrency는 admission source로 되살리지 않는다. per-adapter Capabilities().MaxConcurrency가 adapter gate capacity의 기준이다.
  • Ollama adapter는 내부 target을 model 이름으로 사용하고, context_sizeoptions.num_ctx의 강제 소유값으로 주입한다. 요청 input에 명시된 options.num_ctx가 있어도 Edge-owned context_size가 항상 우선한다. context_size가 0이면 request 값을 그대로 사용한다.
  • vLLM/openai_compat adapter는 OpenAI-compatible provider endpoint를 호출하되, Edge가 선택한 served model target과 provider header/auth/passthrough 정책을 보존한다.
  • RuntimeEvent는 start/delta/reasoning_delta/complete/error/cancelled 타입을 유지하고, adapter별 streaming 표현을 node 외부로 새 이벤트 체계로 노출하지 않는다.
  • node 내부 변경은 가능한 대상 패키지 테스트를 먼저 추가하거나 갱신한다.
  • apps/node/cmd/node/**, apps/node/internal/bootstrap/**, apps/node/internal/transport/**, apps/node/internal/node/**, apps/node/internal/router/**, apps/node/internal/adapters/**, apps/node/internal/store/**의 실행 요청/응답/stream/cancel/status/session/config-refresh/provider-tunnel 경로를 바꾼 뒤에는 testing domain rule의 작업 후 검증 기준을 따른다.

다른 도메인과의 경계

  • edge: edge는 node 연결 등록, adapter/runtime 설정 전달, 라우팅 진입, stream relay를 담당한다. node는 edge가 보낸 실행/취소/명령 요청을 처리하고 이벤트와 명령 응답을 돌려준다.
  • platform-common: node는 packages/go/agentruntime, packages/go/agentprovider/cli, config/events/observability와 proto 생성물을 소비한다. 공통 provider/runtime 구현과 설정/event helper는 platform-common이 소유하고 Node는 wire translation과 실행 조정을 소유한다.
  • control-plane: control-plane은 Node가 아니라 Edge를 통해 시스템을 제어한다. node는 control-plane 직접 연결/직접 스케줄링을 전제로 하지 않는다.

금지 사항

  • node 도메인 내부에서 gRPC, WebSocket 기본 transport, actor/FSM/plugin framework를 새 기본 구조로 도입하지 않는다.
  • proto/gen/iop/*.pb.go 생성 파일을 직접 수정하지 않는다.
  • 새 어댑터 구현을 node.Node에 직접 분기문으로 박아 넣지 않는다.
  • provider tunnel 지원을 RunEvent delta에 섞거나 OpenAI-compatible raw response를 node stdout parser처럼 취급하지 않는다.
  • config refresh 중 old registry를 in-flight run이 끝나기 전에 stop해 기존 실행을 끊지 않는다.
  • edge-local console, OpenAI-compatible HTTP, A2A 같은 입력 표면 책임을 node로 끌어오지 않는다.
  • placeholder 상태인 control-plane/worker 책임을 node에 임시로 흡수하지 않는다.
  • CLI provider별 session/conversation 상태를 Node에 다시 구현하지 않는다. provider 세부 상태는 packages/go/agentprovider/cli 내부에 두고 공통 agentruntime interface에는 host-neutral 의미만 노출한다.
  • field bootstrap 기본 안내에서 사용자가 IOP_HOME, IOP_NODE_CONFIG, IOP_NODE_METRICS_PORT 같은 환경 변수를 먼저 선언해야만 동작하는 형태를 요구하지 않는다. 필요한 값은 bootstrap 기본값 또는 Edge-provided config로 처리하고, 환경 변수는 optional override로만 둔다.