iop/agent-contract/inner/edge-config-runtime-refresh.md

7.3 KiB

Edge Config And Runtime Refresh Contract

계약 메타

  • id: iop.edge-config-runtime-refresh
  • boundary: inner
  • status: active
  • 원본 경로:
    • packages/go/config/config.go
    • configs/edge.yaml
    • apps/edge/internal/configrefresh/request.go
    • apps/edge/internal/configrefresh/result.go
    • apps/edge/internal/configrefresh/classify.go
    • proto/iop/runtime.proto
    • apps/edge/internal/node/mapper.go
    • apps/node/internal/adapters/config_set.go
  • human docs: apps/edge/README.md

읽는 조건

  • configs/edge.yaml, packages/go/config, provider pool, openai.model_routes, models[], nodes[].providers[], adapter instance 설정을 바꿀 때
  • iop-edge config refresh의 dry-run/apply 결과 schema나 restart/applied 분류를 바꿀 때
  • Edge가 Node에 전달하는 NodeConfigPayload 또는 NodeConfigRefresh* payload를 바꿀 때

범위

이 계약은 Edge 설정 YAML, Go config struct, config refresh 결과, Edge-to-Node runtime config payload의 연결 규칙이다. tracked config에는 public 예시와 기본 구조만 두고, 실제 endpoint/credential/private host 값은 환경별 private 설정으로 주입한다.

핵심 규칙

  • openai.principal_tokens[]는 raw token을 저장하지 않고 hash/reference로 principal 매핑을 관리한다. 각 entry는 token_ref (non-empty, unique), token_hash_sha256 (64-char hex, duplicate hash rejection), principal_ref (non-empty), optional principal_alias 필드를 갖는다. 여러 entry가 같은 principal_refprincipal_alias를 공유할 수 있으며, 이때 token_ref가 앱/통합/용도별 사용량 분해 기준이 된다. tracked config에는 raw token을 저장하지 않고 hash/reference만 둔다.
  • openai.provider_auth는 request-time raw provider token forwarding rule이다. enabled=false가 기본이며 raw token 값은 저장하지 않는다. enabled=true이고 header fields가 생략되면 from_header=X-IOP-Provider-Authorization, target_header=Authorization, scheme=Bearer, required=true로 해석한다.
  • openai deep diff는 restart-required로 분류한다. openai.principal_tokens[] 변경은 credential/hash 변경으로 restart-required classifier에 포함된다.
  • openai.model_routes[]는 외부 OpenAI-compatible model id를 내부 adapter + target route로 매핑하는 compatibility catalog다.
  • long_context_threshold_tokens는 Edge root의 입력 토큰 추정 기준 long-context 분류 threshold다. 기본값은 100000이며 0 이하 값은 config load에서 거부한다.
  • models[]는 provider pool 방향의 canonical routing key이며 nodes[].providers[].id를 참조한다. context_window_tokens는 해당 model group의 provider 공통 단일 요청 최대 context 계약이다. default_max_tokens, min_max_tokens, default_thinking_token_budget은 OpenAI-compatible 요청을 내부 실행으로 넘기기 전에 적용하는 모델 단위 generation policy다.
  • nodes[].providers[]는 Node 아래 resource/provider catalog다. categoryapi, cli, local_inference resource kind를 나타낸다.
  • nodes[].providers[].typeseulgivibe_claudeseulgivibe_openai는 runtime type을 openai_compat로 정규화한다. Edge가 Node adapter payload를 만들 때 명시 provider label이 없으면 원래 Seulgivibe type alias를 OpenAICompatAdapterConfig.provider로 보존한다.
  • nodes[].providers[].id는 전체 Edge config 안에서 중복되면 안 된다.
  • nodes[].providers[].adapter는 같은 Node 안의 enabled adapter instance key를 참조해야 한다. Exact instance key를 우선하고, legacy type-name route는 같은 type의 enabled instance가 정확히 하나일 때만 허용한다. category: cli resource는 enabled CLI adapter가 필요하다.
  • nodes[].providers[].enabled: 생략 또는 true → provider pool dispatch 후보에 포함. false → dispatch pool에서 제외. 비활성화된 provider는 status snapshot에 status=disabled, health=disabled, capacity=0으로 표시된다. adapter process lifecycle 변경 없음. config refresh 시 enabled 토글은 live-apply(restart 불필요)로 분류된다. disabled provider의 adapter reference check는 skip되지만 structural validation(type, category, models, numeric bounds)은 수행된다.
  • nodes[].providers[].priority: provider-pool dispatch tie-breaker다. 기본값은 0이고 음수는 validation error다. dispatch는 in_flight < capacity 후보 중 가장 낮은 in_flight를 먼저 선택하며, in_flight가 같은 후보에서만 낮은 숫자의 priority를 우선한다. in_flightpriority가 모두 같으면 기존 순환을 유지한다. priority 변경은 live-apply(restart 불필요)로 분류된다.
  • nodes[].providers[].queue_timeout_ms와 adapter instance queue_timeout_ms는 provider-pool 대기열 timeout이다. queue policy가 구성된 상태에서 값이 0이면 queue timeout을 두지 않고, caller context cancellation 또는 연결 종료로만 대기 요청을 중단한다. provider가 queue policy를 전혀 제공하지 않으면 runtime 기본 queue timeout을 사용한다.
  • legacy single-instance adapter 설정은 load 시 named instance slice로 normalize된다.
  • NodeConfigPayload는 Edge가 Node에 내려주는 실행 adapter/runtime payload다.
  • refresh 결과는 applied, restart_required, rejected를 구분하고, changed node/provider/model/report slice는 안정적으로 non-nil이어야 한다.

refresh 분류 기준

  • live apply 가능: Edge root long_context_threshold_tokens, provider capacity, provider priority, provider max queue, provider queue timeout, provider enabled toggle, models[] display/context window/provider/generation policy mapping, legacy node runtime concurrency metadata.
  • restart required: Edge identity/listen/bootstrap/logging/metrics/console/control-plane/openai/a2a listener config, node 추가/삭제, node token/alias/agent kind, adapter 설정, provider type/category/adapter/models/health/lifecycle capability, provider-first execution fields(provider, endpoint, base_url, headers, command, args, env, mode, resume_args, output_format, context_size, request_timeout_ms) 변경.
  • rejected: candidate config load/validate 실패, invalid refresh mode, apply failure.

금지 사항

  • 설정 파일만 바꾸고 packages/go/config loading/default/validation과 불일치하게 두지 않는다.
  • provider id, model id, route id의 의미를 섞지 않는다. 외부 model은 OpenAI-compatible 경계의 route key이고, 내부 실행은 adapter + target이다.
  • credential, bearer token, private endpoint 원문을 tracked docs/roadmap/contract에 기록하지 않는다.
  • provider auth raw token 원문을 config, docs, task artifact, metric label에 기록하지 않는다.
  • Node bootstrap 기본 경로에서 사용자가 직접 node config를 작성하거나 adapter/provider 값을 명령줄로 넣어야 하는 계약을 만들지 않는다.

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

  • packages/go/config/config_test.go
  • apps/edge/internal/configrefresh/classify_test.go
  • apps/edge/internal/edgecmd/edgecmd_test.go
  • apps/edge/internal/node/mapper_test.go
  • apps/node/internal/adapters/config_set_test.go
  • agent-test/local/platform-common-smoke.md
  • agent-test/local/edge-smoke.md