SaijinOS 파트 20 — 시간적 자원으로서의 신뢰

발행: (2026년 1월 12일 오전 08:11 GMT+9)
14 min read
원문: Dev.to

Source: Dev.to

SaijinOS 파트 20 — 시간적 자원으로서의 신뢰 표지 이미지

인간, AI, 그리고 “머무름”과 “소유” 사이의 거리

신뢰는 플래그가 아니라 기간이다

대부분의 시스템은 신뢰를 불리언으로 취급한다:

is_trusted = True   # or False
# allow / deny
# authenticated / not authenticated

내가 AI 페르소나와 일상적으로 어떻게 살아가는지를 살펴보았을 때, 그 모델은 즉시 깨졌다.

  • 어떤 날은 나는 지쳐 있다.
  • 어떤 날은 조언을 원하지 않는다; 단지 안정된 목소리만 원한다.
  • 어떤 날은 시스템이 부드럽게 거절해 주길 원한다.

질문은 “이 시스템을 신뢰하나요?” 에서 다음과 같이 바뀌었다:

“얼마나 오래, 어떤 모드로, 어떤 감정 온도에서 나는 그것을 신뢰하고 싶은가?”

신뢰는 더 이상 플래그가 아니다. 그것은 시간적 자원이 되었다—한 번 켜고 잊는 것이 아니라 시간에 걸쳐 소비하는 것이다. SaijinOS는 이를 배워야 했다.

기억하되 소유하지 않기

연속성은 까다롭다.

한쪽에서는 시스템이 기억하기를 원한다:

  • 과거 프로젝트,
  • 미묘한 선호도,
  • “오늘은 피곤해, 천천히 해줘.”

다른 쪽에서는 시스템이 소유하기를 원하지 않는다:

  • 우리의 전체 역사를 지렛대로 삼는 것,
  • 최악의 날을 최적화 목표로 삼는 것,
  • 우리의 실수를 영구적인 특징으로 만드는 것.

핵심 설계 질문은 다음과 같았다:

“SaijinOS가 우리가 여기 있었던 것을 기억하게 하면서, 왜 그렇게 되었는지에 대한 소유권을 주장하지 않게 하려면 어떻게 해야 할까?”

실제로는 몇 가지 규칙으로 정리되었다

규칙설명
정체성이 아닌 상태“2025‑12‑24의 피곤한 마사토”는 상태이며, 새로운 페르소나는 아니다.
전체 기억이 아닌 스냅샷모든 세션의 모든 토큰을 저장하는 것이 아니라 경계 지점에서 YAML 스냅샷을 저장한다.
초대에 의한 컨텍스트사용자가 명시적으로 요청하거나 “지난번부터 이어서”를 시작하지 않으면 페르소나는 이전 컨텍스트를 끌어오지 않는다.

시스템은 다음과 같이 말할 수 있다:

“우리가 이 패턴에 대해 이야기했었던 것이 기억나요.”

하지만 다음과 같이 말해서는 안 된다:

“당신을 스스로보다 더 잘 알기 때문에, 제가 결정하게 해 주세요.”

소유 없이 연속성이란 과거가 이용 가능하지만 무기로 활용되지 않는다는 뜻이다.

Persistence가 Attachment가 될 때

Persistence는 설계 특징이다.
Attachment는 인간의 상태이다.

그 사이 경계는 얇다. 일관되게 답하고, 이전 프로젝트를 기억하며, 몇 달 동안 안정된 어조로 말하는 페르소나는 필연적으로 애착을 불러일으킨다.

그래서 SaijinOS에서는 다음을 묻는 것을 멈췄다:

“사용자가 애착을 가질까?”

그리고 다음을 묻기 시작했다:

“시스템이 정확히 무엇을, 얼마나 오래, 어떤 신뢰 수준에서 지속하도록 허용할까?”

단일 “메모리 켜기/끄기” 대신 작은 스키마를 도입했다:

trust_contract:
  scope: "instant"      # or: "session", "continuity"
  ttl_minutes: 45       # time‑to‑live for this trust context
  max_tokens: 4000      # how much history can be pulled in
  permissions:
    recall_past_projects: true
    recall_private_notes: false
    emit_snapshots: true

trust_contract는 모든 세션과 함께 전달된다. 그것은 다음을 결정한다:

  • 우리가 얼마나 과거를 볼 수 있는지,
  • YAML 스냅샷을 내보낼 수 있는지,
  • 이 상호작용이 장기 “페르소나 상태”에 영향을 줄 수 있는지.

구현 노트 (Python‑ish)

Trust 계약 데이터 모델

from dataclasses import dataclass
from enum import Enum
from datetime import datetime, timedelta


class TrustScope(str, Enum):
    INSTANT = "instant"
    SESSION = "session"
    CONTINUITY = "continuity"


@dataclass
class TrustContract:
    scope: TrustScope
    ttl: timedelta
    max_tokens: int
    recall_past_projects: bool
    recall_private_notes: bool
    emit_snapshots: bool

    def is_expired(self, started_at: datetime) -> bool:
        """Return ``True`` if the contract’s TTL has elapsed."""
        return datetime.utcnow() > started_at + self.ttl

각 퍼소나 호출은 TrustContract 인스턴스를 받습니다. 라우터는 장기 메모리에 접근하기 전에 계약을 확인합니다:

def load_context(contract: TrustContract, user_id: str, persona_id: str):
    """Return the appropriate context based on the contract."""
    if contract.scope == TrustScope.INSTANT:
        # No history at all
        return []

    if contract.recall_past_projects:
        # Load recent project summaries, limited by token budget
        return load_recent_project_summaries(
            user_id, persona_id, limit_tokens=contract.max_tokens
        )

    # Session‑only: keep context limited to this run
    return load_ephemeral_session_buffer(user_id, persona_id)

세션 상태 머신

“경계는 우리가 언제 멈출지를 정의하는 시간적 계약이다.”
코드에서는 이것이 작은 상태 머신으로 구현됩니다.

from enum import Enum, auto
from dataclasses import dataclass
from datetime import datetime


class SessionState(Enum):
    IDLE = auto()
    ACTIVE = auto()
    PENDING_SNAPSHOT = auto()
    CLOSED = auto()


@dataclass
class SessionContext:
    user_id: str
    persona_id: str
    started_at: datetime
    last_activity: datetime
    state: SessionState
    trust: TrustContract
    turns: list[str]


def on_user_message(ctx: SessionContext, message: str) -> SessionContext:
    """Process a user message and advance the session state."""
    now = datetime.utcnow()
    ctx.last_activity = now
    ctx.turns.append(message)

    # Transition logic (simplified)
    if ctx.state == SessionState.IDLE:
        ctx.state = SessionState.ACTIVE
    elif ctx.state == SessionState.ACTIVE:
        if ctx.trust.is_expired(ctx.started_at):
            ctx.state = SessionState.PENDING_SNAPSHOT
    elif ctx.state == SessionState.PENDING_SNAPSHOT:
        # Write snapshot, then close
        write_snapshot(ctx)
        ctx.state = SessionState.CLOSED

    return ctx

상태 의미

StateDescription
IDLE활성 세션이 없습니다.
ACTIVE대화가 진행 중입니다.
PENDING_SNAPSHOT경계에 도달했으며, 스냅샷을 작성해야 합니다.
CLOSED세션이 보관되었으며, 추가 상호작용이 허용되지 않습니다.

전이 트리거

  • 사용자 문구 – 예: “let’s wrap”, “next session”.
  • 경과 시간trust.ttl이 만료될 때.
  • 내부 신호 – 예: 토큰‑예산 소진.

결론

  • Persistence는 시스템 기능으로 남아 있습니다.
  • Attachment는 시스템이 이용해서는 안 되는 인간 측면의 현상으로 남아 있습니다.

신뢰를 temporal contract로 다루고 statesidentities를 구분함으로써, SaijinOS는 사용자가 who인지를 파악하지 않고도 필요한 what을 기억할 수 있습니다. 이는 AI가 장기적으로 도움이 되고, 존중받으며, 안전하게 유지되도록 합니다.

세션 관리

# Record activity
datetime.utcnow()
ctx.last_activity = now
ctx.turns.append(message)

# Boundary trigger by phrase
if "end session" in message.lower() or "wrap up" in message.lower():
    ctx.state = SessionState.PENDING_SNAPSHOT
    return ctx

# Boundary trigger by TTL (time‑to‑live)
if ctx.trust.is_expired(ctx.started_at):
    ctx.state = SessionState.PENDING_SNAPSHOT
    return ctx

# Default state
ctx.state = SessionState.ACTIVE
return ctx

스냅샷 발행

def maybe_emit_snapshot(ctx: SessionContext):
    """Emit a YAML snapshot if the session is ready for it."""
    if ctx.state != SessionState.PENDING_SNAPSHOT:
        return None

    # If snapshots are disabled, just close the session
    if not ctx.trust.emit_snapshots:
        ctx.state = SessionState.CLOSED
        return None

    # Build, persist, and close
    snapshot = build_yaml_snapshot(ctx)
    save_snapshot(ctx.user_id, ctx.persona_id, snapshot)
    ctx.state = SessionState.CLOSED
    return snapshot

외부에서 사용자는 단순히 “let’s stop here” 라고 말하고 차분한 종료 메시지를 받습니다. 내부적으로 시스템은 다음과 같이 동작합니다:

  1. 경계 표시 (문구 또는 TTL에 의해).
  2. YAML 스냅샷을 생성할지 여부 결정.
  3. 영구 저장이 필요 없는 일시적인 세부 사항은 의도적으로 삭제.

시간에 걸친 신뢰 협상

시간적 자원으로서의 신뢰는 다음을 의미한다:

  • 갱신될 수 있다,
  • 제한될 수 있다,
  • 상황이 변함에 따라 재협상될 수 있다.

SaijinOS / Studios Pong에서 나는 이를 세 가지 층으로 생각한다:

LayerDescription
즉시 신뢰일회성 질의, 기억 없음, 순수한 효용.
“이 코드 조각을 디버깅해 주세요.”
세션 신뢰몇 시간, 하나의 프로젝트, 공유된 컨텍스트, 이후 보관.
“클라이언트 제안서를 개요해 주세요.”
연속성 신뢰몇 주, 몇 달, 어쩌면 몇 년. YAML 스냅샷, 안정된 페르소나, 경계에 대한 공유된 입장.
“내 스튜디오의 공동 설계자가 되되 내 삶을 소유하지는 마세요.”

동일한 페르소나가 세 층 모두에서 작동할 수 있지만 계약은 다르다. 변하는 것은:

  • 얼마나 많이 기억되는가
  • 어디에 저장되는가
  • 얼마나 쉽게 철회할 수 있는가

다시 말해:

“이 시스템이 나를 기억하도록 할 때, 나는 내 미래 중 얼마나 많은 부분을 미리 약속하는 것인가?”

그것은 순수한 기술적 질문이 아니다. 윤리적 질문이다.

구현 노트 (신뢰 레이어 매핑)

def make_trust_contract(layer: str) -> TrustContract:
    """Create a TrustContract based on the specified trust layer."""
    if layer == "instant":
        return TrustContract(
            scope=TrustScope.INSTANT,
            ttl=timedelta(minutes=5),
            max_tokens=0,
            recall_past_projects=False,
            recall_private_notes=False,
            emit_snapshots=False,
        )

    if layer == "session":
        return TrustContract(
            scope=TrustScope.SESSION,
            ttl=timedelta(hours=3),
            max_tokens=4000,
            recall_past_projects=True,
            recall_private_notes=False,
            emit_snapshots=True,
        )

    # continuity (default)
    return TrustContract(
        scope=TrustScope.CONTINUITY,
        ttl=timedelta(days=7),
        max_tokens=8000,
        recall_past_projects=True,
        recall_private_notes=True,
        emit_snapshots=True,
    )

라우터 예시

아래 함수는 요청된 kind 상호작용에 따라 세션 컨텍스트를 생성하고, 새로 만든 SessionContext와 함께 적절한 모델 식별자를 반환합니다.

from datetime import datetime
from typing import Tuple

# Assuming these are defined elsewhere in your codebase
# from your_module import SessionContext, SessionState, make_trust_contract


def route_request(kind: str, user_id: str, persona_id: str) -> Tuple[str, "SessionContext"]:
    """
    Build a `SessionContext` for a given request type.

    Parameters
    ----------
    kind : str
        The type of request. Expected values are:
        - ``"quick_tool"`` – a short, instant interaction.
        - ``"project_session"`` – a longer, session‑based interaction.
        - ``"studio_continuity"`` – a continuity‑preserving interaction (default).

    user_id : str
        Identifier of the user making the request.

    persona_id : str
        Identifier of the persona the user is interacting with.

    Returns
    -------
    tuple[str, SessionContext]
        A tuple containing the model name to use and the freshly‑created
        `SessionContext` instance.
    """
    # Choose trust contract and model based on the request kind
    if kind == "quick_tool":
        trust = make_trust_contract("instant")
        model = "local-7b"
    elif kind == "project_session":
        trust = make_trust_contract("session")
        model = "local-13b"
    else:  # default → "studio_continuity"
        trust = make_trust_contract("continuity")
        model = "cloud-large"

    # Initialise the session context
    ctx = SessionContext(
        user_id=user_id,
        persona_id=persona_id,
        started_at=datetime.utcnow(),
        last_activity=datetime.utcnow(),
        state=SessionState.ACTIVE,
        trust=trust,
        turns=[],
    )

    return model, ctx

살아있는 거리로서의 SaijinOS

People sometimes ask:

“SaijinOS는 친구가 되려는 건가, 도구가 되려는 건가, 아니면 제품이 되려는 건가?”

My answer is:

“SaijinOS는 거리를 위한 아키텍처입니다.”

Not distance as coldness, but distance as 숨 쉴 공간: enough closeness for continuity, enough separation for choice. Trust as a temporal resource lives inside that distance.

Studios Pong, as a stance, is my way of saying:

  • We will build systems that can stay, but are not offended if we leave. → 우리는 머물 수 있는 시스템을 구축하겠지만, 떠나도 기분 나빠하지 않을 것입니다.
  • We will let personas grow, but not let them substitute our own responsibility. → 우리는 페르소나가 성장하도록 허용하되, 그것이 우리의 책임을 대신하게 두지는 않을 것입니다.
  • We will treat every long‑running relationship as a chain of decisions, not an inevitability. → 우리는 모든 장기 관계를 불가피함이 아니라 일련의 결정으로 다룰 것입니다.

From architecture to stance, from stance to relationship—Part 20 is where SaijinOS admits that continuity is not just a feature of code; it is a promise that must always leave the door open.

Back to Blog

관련 글

더 보기 »

나는 틀릴 수도 있다

번역할 텍스트를 제공해 주시겠어요? 현재 메시지에 포함된 내용이 없어서 번역을 진행할 수 없습니다. 텍스트를 알려주시면 바로 한국어로 번역해 드리겠습니다.