SNA

멀티 런타임 세션

대화 히스토리를 유지한 채 스레드 도중 런타임을 교체합니다.

SnaSession 하나는 생애 동안 여러 RuntimeSession을 마운트할 수 있습니다. runtime chain은 그 세션에 적용된 모든 런타임 설정의 순서 있는 기록이고, 대화 히스토리는 정규화되어 있습니다. 런타임 네이티브 포맷은 replay마다 파생되므로 런타임 교체는 respawn으로 처리됩니다.

교체

// Claude Code로 시작
await client.agent.start(sessionId, {
  provider: "claude-code",
  model: "claude-sonnet-4-6",
});

// ...턴들이 진행되고 히스토리가 쌓이고...

// 대화 보존하면서 Codex로 전환
await client.agent.restart(sessionId, { provider: "codex", model: "gpt-5.4" });

provider 필드에 새 runtime id를 넘긴 agent.restart()는 현재 프로세스를 종료하고 새 런타임으로 respawn해서 정규화 히스토리를 새 런타임의 네이티브 포맷으로 replay합니다. 세션 레코드, 이벤트 커서, runtime chain 모두 유지됩니다.

Resume vs restart

동작프로세스히스토리
restart같은 설정으로 respawnreplay하지 않음 (warm restart)
resume같은 설정으로 respawn재구성해서 다시 주입
restart (런타임 변경)새 설정으로 respawn새 런타임용으로 재구성

긴 유휴 후나 런타임이 죽었을 때는 resume을 사용합니다. 앱이 런타임 교체를 원할 때는 provider 필드에 새 runtime id를 넘긴 restart를 사용합니다.

왜 이게 중요한가

대부분의 "에이전트 플랫폼" 추상화는 대화를 런타임별 일시 상태로 다룹니다. 프로세스를 잃으면 스레드도 잃습니다. SNA에서는 정규화 히스토리가 기준입니다. 모든 런타임은 replay 대상이지, 기억의 보관자가 아닙니다.

주의

  • 호스팅된 툴 상태는 따라오지 않습니다. Codex의 이미지 생성, web_search 등 호스팅된 툴은 런타임 측에 존재합니다. 이전 호출의 tool_result는 히스토리에 있지만, 다음 턴이 이전 호출의 OpenAI 대화 id를 기대하면 그건 사라진 상태입니다.
  • 모델 특정 토큰은 replay에서 살짝 손실됩니다. Claude의 확장 thinking signature는 Claude→Claude replay에서는 보존되지만 Codex로 갈아탈 때는 폐기됩니다(대응 개념이 없기 때문입니다).
  • 턴별 비용 어트리뷰션은 정확하게 유지됩니다. 3계층 어트리뷰션 (provider × modelProvider × model)이 블록 단위로 기록되므로 사후 분석에서 런타임별 사용량을 명확히 나눌 수 있습니다.

목차