iop/agent-contract/inner/edge-node-runtime-wire.md

7.8 KiB

Edge-Node Runtime Wire Contract

계약 메타

  • id: iop.edge-node-runtime-wire
  • boundary: inner
  • status: active
  • 원본 경로:
    • proto/iop/runtime.proto
    • apps/edge/internal/transport/server.go
    • apps/node/internal/transport/client.go
    • apps/node/internal/transport/session.go
    • apps/node/internal/transport/parser.go
    • apps/edge/internal/node/mapper.go
    • apps/node/internal/adapters/config_set.go
  • human docs:
    • apps/edge/README.md
    • apps/node/README.md

읽는 조건

  • Edge-Node TCP/protobuf transport, register handshake, run stream, provider raw tunnel, cancel, node command, node config refresh를 바꿀 때
  • RunRequest, RunEvent, ProviderTunnelRequest, ProviderTunnelFrame, CancelRequest, NodeCommandRequest, NodeCommandResponse, NodeConfigPayload, NodeConfigRefresh* 필드를 바꿀 때
  • node adapter 설정 payload나 runtime config가 Edge에서 Node로 전달되는 방식을 바꿀 때

범위

이 계약은 Edge와 Node 사이의 내부 TCP proto-socket 경계다. Edge는 Node 연결을 수락하고, Node는 연결 직후 등록 요청을 보낸다. 실행 요청과 이벤트 스트림, 취소, 조회성 명령, 설정 refresh는 같은 내부 wire 계열에서 처리한다.

주요 흐름

  • register: Node가 RegisterRequest를 보내고 Edge가 RegisterResponse로 수락 여부와 NodeConfigPayload를 돌려준다.
  • execution: Edge가 RunRequest를 보내고 Node가 RunEvent stream으로 실행 상태를 보낸다.
  • provider raw tunnel: Edge가 기존 Edge-Node socket으로 ProviderTunnelRequest를 보내고 Node가 provider HTTP/SSE 요청을 연 뒤 ProviderTunnelFrame stream으로 provider status/header/body/end/error/usage 후보를 sequence와 함께 돌려준다. 이 경로는 OpenAI-compatible provider passthrough용이며 RunEvent 실행 stream과 분리된다.
  • provider-pool mixed dispatch: Edge service는 model group provider candidate를 선택한 뒤, 같은 selected provider/queue lease로 OpenAI-compatible provider에는 ProviderTunnelRequest, Ollama/CLI/native provider에는 normalized RunRequest를 보낸다. Edge-Node wire는 client-provided response path selector를 받지 않고, provider type만으로 후보를 제외하지 않는다.
  • cancel: Edge가 CancelRequest를 보내며 CANCEL_RUNTERMINATE_SESSION을 구분한다.
  • command: Edge가 NodeCommandRequest를 보내고 Node가 NodeCommandResponse로 usage/capabilities/session/transport/provider 상태를 응답한다.
  • refresh: Edge가 NodeConfigRefreshRequest로 새 config payload를 보내고 Node가 NodeConfigRefreshResponse로 적용/재시작 필요/실패를 응답한다.

필드 의미

  • RunRequest.adapter, RunRequest.target: 내부 실행 식별자다. 외부 OpenAI-compatible model은 Edge 입력 표면에서 이 둘로 변환되어야 한다.
  • RunRequest.workspace: CLI agent route 같은 workspace-bound 실행의 작업 디렉터리다.
  • RunRequest.input: adapter가 해석할 실행 입력이다. CLI 실행에서는 prompt 계열 입력으로 변환된다.
  • RunRequest.metadata: caller-defined 실행 metadata다. workspace 자체는 별도 workspace 필드로 전달한다.
  • RunEvent.type: start, delta, complete, error, cancelled 같은 실행 이벤트 종류다.
  • ProviderTunnelRequest: 기존 Edge-Node socket 위에서 provider HTTP request를 열기 위한 요청이다. adapter, target, method, path, headers, body, stream, timeout_sec, metadata, session_id를 싣되 normalized adapter execution인 RunRequest와 분리된다. 외부 caller의 response selector를 전달하지 않으며, 경로는 Edge가 model로 선택한 provider capability에 의해 결정된다.
  • ProviderTunnelFrame: Node가 provider response를 Edge로 돌려주는 ordered frame이다. kind, sequence, status_code, headers, body, end, error, usage, metadata를 싣는다. body는 passthrough source of truth이며 RunEvent.delta나 Edge events.Bus fanout payload로 보내지 않는다. usagemetadata는 Edge의 metric/log/known-key 관측 후보이고 provider passthrough body에 합쳐지지 않는다.
  • tunnel cancellation: HTTP caller disconnect, response wait timeout, 또는 Edge write failure가 발생하면 Edge는 같은 run id에 대한 CancelRequest(CANCEL_RUN)을 보내 upstream provider request 중단을 요청한다. Node adapter는 provider request context cancellation을 관측하고 ordered error/end semantics를 유지해야 한다.
  • RunEvent.metadata["openai_tool_calls"]: OpenAI-compatible provider adapter가 native tool_calls를 반환했을 때 완료 이벤트에 싣는 JSON 배열이다. Edge OpenAI-compatible 표면은 이 값을 message.tool_calls 또는 stream delta.tool_calls로 복원한다. provider assistant content 텍스트를 이 값으로 파싱/합성하지 않는다.
  • RunEvent.metadata["openai_text_tool_fallback"]: OpenAI-compatible provider adapter가 backend native tool API 거부 후 tools/tool_choice를 제거하고 text tool-call instruction으로 재시도했을 때 "true"를 싣는다. 이 instruction은 backend가 system role 위치를 거부하지 않도록 leading system message에 병합한다. Edge는 이 표시가 있는 실행에서만 assistant content의 text tool-call을 OpenAI-compatible tool_calls로 복원할 수 있다.
  • NodeCommandRequest.type: 실행이 아닌 조회/제어성 명령이다. adapter execution 요청과 섞지 않는다.
  • NodeConfigPayload.adapters: Edge가 Node에 내려주는 adapter instance 설정이다.
  • AdapterConfig.name: node 내부 stable adapter instance identity다. 비어 있으면 legacy single-instance type 이름과 동등하다.
  • NodeRuntimeConfig.concurrency: legacy compatibility runtime metadata다. 실행 admission은 이 값을 node-wide global gate로 사용하지 않고 provider/resource capacity를 기준으로 한다. Node store 위치나 CLI 실행 작업 디렉터리는 이 runtime payload에 싣지 않는다.
  • ProviderSnapshot: legacy wire name을 유지하지만 Node 아래 resource/provider 상태 snapshot으로 해석한다. categoryapi, cli, local_inference resource kind를 나타내며, provider-pool dispatch 대상은 Edge config models[].providers가 참조한 resource뿐이다. 또한 long_context_capacity, long_in_flight, long_queued 필드는 long-context admission 제어를 위해 사용되며, provider가 확보한 long slot 용량과 현재 점유 중인 long slot 수, 대기 중인 long 요청 수를 나타낸다.

금지 사항

  • Control Plane이나 Client가 Node에 직접 연결하거나 직접 스케줄링하는 계약을 만들지 않는다.
  • 외부 API의 model 용어를 이 내부 경계의 대표 실행 식별자로 되살리지 않는다.
  • proto/gen/iop/*.pb.go 생성물을 직접 수정하지 않는다.
  • transport handler에서 console/HTTP/A2A 표면 응답을 직접 만들지 않는다. 표면별 변환은 Edge service/input 계층에 둔다.
  • Node address, token, transport internals를 Control Plane status 계약으로 노출하지 않는다.

변경 시 확인할 코드/테스트

  • proto/iop/runtime.proto
  • apps/edge/internal/transport/*_test.go
  • apps/node/internal/transport/*_test.go
  • apps/edge/internal/openai/provider_dispatch_test.go
  • apps/edge/internal/openai/provider_selection_test.go
  • apps/edge/internal/openai/provider_tunnel_test.go
  • apps/edge/internal/openai/cancellation_routes_test.go
  • apps/node/internal/adapters/openai_compat/*_test.go
  • apps/node/internal/adapters/vllm/*_test.go
  • apps/edge/internal/node/mapper_test.go
  • apps/node/internal/adapters/config_set_test.go
  • apps/node/internal/adapters/adapters_blackbox_test.go
  • proto 변경 시 make proto, Client가 소비하면 make proto-dart