스트리밍 메시지
스트리밍 메시지 (Streaming Messages)
open–content–close 규율, 청크형 형태, 그리고 그것들을 묶는 규칙 — 1.0 버전을 설명드릴게요.
출처: 문서
본문
세 가지 이벤트 패밀리가 긴 값을 조각 단위로 스트리밍해요: 텍스트 메시지, 도구 호출, 추론 메시지. 세 가지 모두 두 철자를 가진 하나의 패턴을 따릅니다 — 명시적 open–content–close 삼중항과, 그렇지 않으면 버퍼링해야 할 프로듀서를 위한 간결한 청크형(chunked) 형태요. 이 페이지는 패턴을 한 번 정의하고; 패밀리 페이지(text messages, tool calls, reasoning)는 각 패밀리에 특정한 것만 추가합니다.
Open, content, close
스트리밍되는 항목은 *_START 이벤트로 열리고, 0개 이상의 콘텐츠 이벤트로 확장되며, *_END 이벤트로 닫히고, 모두 항목의 식별자(메시지의 messageId, 도구 호출의 toolCallId)로 매칭됩니다.
- 프로듀서는 이미 열린 식별자로 항목을 열어선 안 돼요(MUST NOT).
- 프로듀서는 열리지 않은 식별자에 대해 콘텐츠나 종료 이벤트를 보내선 안 돼요(MUST NOT).
- 프로듀서가 여는 모든 항목은 실행이 끝나기 전에 닫혀야 해요.
여는 이벤트는 항목을 기술하는 필드를 담아요; 콘텐츠 이벤트는 식별자와 delta만 담아요. 델타는 도착 순서대로 결합되어 항목의 값을 형성해요.
sequenceDiagram
participant Producer
participant Consumer
Producer->>Consumer: TEXT_MESSAGE_START (messageId: "msg-1")
Producer->>Consumer: TEXT_MESSAGE_CONTENT (delta: "Hello, ")
Producer->>Consumer: TEXT_MESSAGE_CONTENT (delta: "world.")
Producer->>Consumer: TEXT_MESSAGE_END (messageId: "msg-1")
인터리빙 (Interleaving)
메시지, 도구 호출, 추론 메시지, 단계는 독립적이에요. 프로듀서는 자유롭게 섞을 수 있어요(MAY) — 메시지가 여전히 스트리밍되는 동안 도구 호출이 열릴 수 있어요 — 단 각 항목이 자신의 open/close 규율을 지키는 한이요.
독립형 이벤트(STATE_SNAPSHOT, STATE_DELTA, MESSAGES_SNAPSHOT, ACTIVITY_SNAPSHOT, ACTIVITY_DELTA, CUSTOM, RAW, REASONING_ENCRYPTED_VALUE)는 스스로 항목을 열고 닫지 않으며, 열린 실행 안 어디에든 나타날 수 있어요. 청크형 형태에서 이들 중 일부는 열린 청크 스트림을 끝내기도 해요 — 도착하는 것 자체가 소비자에게 축약이 더 이상 계속될 수 없음을 알리는 것이죠 — 청크 스트림 닫기가 나열하는 대로요.
청크형 형태 (The chunked form)
TEXT_MESSAGE_CHUNK, TOOL_CALL_CHUNK, REASONING_MESSAGE_CHUNK는 삼중항의 간결한 철자예요. 소비자는 검증 전과 애플리케이션 코드 전에 이들을 start/content/end 형태로 확장해야 하므로(MUST), 삼중항의 모든 규칙이 확장된 이벤트에 적용돼요. 확장이 강제와 미들웨어의 어디에 위치하는지는 processing model에 명시되며; 모든 경로에서 성립하는 불변식은 청크가 그것이 실제로 가진 이벤트로 판단된다는 것입니다 — 어떤 단계든 잘못된 청크를 먼저 만나면 복구하는 것이 아니라 거부해요.
sequenceDiagram
participant Producer
participant Expansion
participant Consumer
Producer->>Expansion: TOOL_CALL_CHUNK (toolCallId, toolCallName, delta)
Expansion->>Consumer: TOOL_CALL_START
Expansion->>Consumer: TOOL_CALL_ARGS
Producer->>Expansion: TOOL_CALL_CHUNK (delta)
Expansion->>Consumer: TOOL_CALL_ARGS
Producer->>Expansion: RUN_FINISHED
Expansion->>Consumer: TOOL_CALL_END
Expansion->>Consumer: RUN_FINISHED
두 철자는 하나의 항목 안에서 섞이지 않아요. 청크가 연 항목은 청크 형태로 계속·닫히며 — 그 *_END는 합성되고, 결코 보내지지 않으며 — *_START가 연 항목은 명시적으로 계속·닫혀요. 청크 스트림이 조립하는 식별자를 담은 명시적 이벤트는 그 연속이 아니에요: 그것은 축약을 끝내며(청크 스트림 닫기가 기술하는대로), 그 뒤는 삼중항 규칙으로 판단됩니다 — 그래서 한 항목 안에서 형태를 섞는 것은 프로듀서가 발행해선 안 되는 잘못된 시퀀스가 돼요.
첫 번째 청크 (The first chunk)
항목의 첫 번째 청크는 여는 데 필요한 것을 담아요; 이후 청크는 그 필드들을 생략하고 이미 열린 것을 계속할 수 있어요(MAY).
- 메시지의 첫
TEXT_MESSAGE_CHUNK는messageId를 반드시 담아야 해요(MUST).role을 담을 수 있어요(MAY); 부재한 role은TEXT_MESSAGE_START에서와 정확히assistant를 뜻해요. - 메시지의 첫
REASONING_MESSAGE_CHUNK는messageId를 반드시 담아야 해요(MUST). - 호출의 첫
TOOL_CALL_CHUNK는toolCallId와toolCallName둘 다 담아야 해요(MUST).
소비자는 필수 필드가 빠진 첫 청크를 식별자를 지어내기보다 프로토콜 위반으로 취급해야 해요.
연속 청크 (Continuation chunks)
- 식별자를 담은 이후 청크는 그것이 연속하는 것과 같은 식별자를 담아야 해요. 다른 식별자를 지목하는 청크는 새 항목을 열며, 이전 것은 먼저 닫혀요.
- 연속 청크는 여는 쪽이 확립한 필드를 반복할 수 있어요(MAY) — 텍스트 메시지의
role이나name, 도구 호출의toolCallName이나parentMessageId— 단 같은 값으로만요. 소비자는 충돌하는 반복을 프로토콜 위반으로 취급해야 해요. 여는 쪽이 생략으로 확립한 값과 충돌하는 것도 포함해요: role 없이 열린 메시지는assistant메시지이며, 다른 role을 주장하는 이후 청크는 그것과 모순돼요.
충돌 반복 규칙은 서브에이전트 귀속 규칙이
subagentRunId에 대해 자신의 오프너와 다른 연속에 내리는 것과 같은 판단입니다: 프로듀서가 한 항목에 대해 양립할 수 없는 두 가지를 말했고, 그 사이에서 고를 올바른 방법이 없어요.
청크 스트림 닫기 (Closing a chunk stream)
청크형 형태에는 명시적 종료 이벤트가 없으므로, 소비자는 스트림이 더 이상 계속될 수 없을 때 *_END를 합성합니다:
- 청크가 같은 레인에서 다른 항목을 열 때;
- 메시지, 도구 호출, 단계, 상태, 커스텀, 추론 이벤트가 항목의 레인에 도착할 때 — 조립에서 비켜서 아무것도 닫지 않는 네 가지 예외가 있습니다:
RAW,ACTIVITY_SNAPSHOT,ACTIVITY_DELTA,REASONING_ENCRYPTED_VALUE(그리고 새 레인을 열지 이 레인을 건드리지 않는SUBAGENT_STARTED); - 실행 레벨 이벤트가 도착할 때 —
RUN_STARTED,RUN_FINISHED,RUN_ERROR,MESSAGES_SNAPSHOT— 이는 모든 레인을 닫으며, 또는 항목이 귀속된 서브에이전트가 종료할 때 — 그 서브에이전트의 레인을 닫아요.
축약 연속이 어느 레인(부모 에이전트 또는 서브에이전트)에 속하는지는 귀속 규칙이 결정하고, 식별자도 태그도 담지 않은 연속에 대해서는 해석으로 결정합니다: 해당 종류의 부모 에이전트 열린 스트림이 존재하면 그것을 계속하고, 그렇지 않으면 그 종류의 유일한 열린 스트림을 계속해요. 여러 레인이 그 종류의 열린 스트림을 보유하고 있는데 그 중 어느 것도 부모의 것이 아니면, 그 연속은 고유한 지시 대상이 없으므로 모호함으로 거부되어야 해요(MUST) — 병렬 서브에이전트를 실행하는 프로듀서는 자신의 연속에 귀속을 붙여야 합니다. 청크 스트림은 그 소유자를 넘어 살아남아선 안 돼요: 서브에이전트가 연 항목은 그 서브에이전트의 종료 이벤트보다 늦게 닫히지 않아요.
청크 메타데이터 (Chunk metadata)
청크의 metadata는 그 청크에서 합성된 이벤트에 적용되며, 메타데이터 규칙 아래에서 항목으로 병합돼요. 메타데이터만 담은 연속 청크 — 사용량과 완료 사유를 보고하는 마지막 청크 — 는 합법입니다: 콘텐츠를 추가하지 않지만, 그 메타데이터는 여전히 그것이 계속하는 항목에 도달해요.
더 알아보기 (Learn more)
- 이벤트 패턴 — 패턴 개요
- Text Messages — 텍스트 메시지 스트리밍
- Reasoning — 추론 메시지 스트리밍
- 이벤트 모델 — 이벤트 봉투·식별자