멀티 런타임 세션
대화 히스토리를 유지한 채 스레드 도중 런타임을 교체합니다.
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 | 같은 설정으로 respawn | replay하지 않음 (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)이 블록 단위로 기록되므로 사후 분석에서 런타임별 사용량을 명확히 나눌 수 있습니다.