• AG-UI 이벀트 μ‹œμŠ€ν…œμ€ μ—μ΄μ „νŠΈ-UI κ°„ μ‹€μ‹œκ°„ 톡신을 μœ„ν•œ typed 이벀트 슀트림 ν”„λ‘œν† μ½œ
  • 28개 ν™œμ„± 이벀트 νƒ€μž…κ³Ό 3κ°€μ§€ 섀계 νŒ¨ν„΄μœΌλ‘œ κ΅¬μ„±λœ ν‘œμ€€ν™”λœ μ—μ΄μ „νŠΈ μΈν„°νŽ˜μ΄μŠ€
  • Thread(λŒ€ν™” μ„Έμ…˜) > Run(μ‚¬μš©μž 1ν„΄) > Step(선택적 단계) > Streaming Item 의 4계측 ꡬ쑰

ν•΄λ‹Ή κ°œλ…μ΄ ν•„μš”ν•œ 이유

  • LangGraph, CrewAI λ“± λ‹€μ–‘ν•œ ν”„λ ˆμž„μ›Œν¬λ₯Ό ν•˜λ‚˜μ˜ UIμ—μ„œ μ—°κ²°ν•  ν‘œμ€€ μΈν„°νŽ˜μ΄μŠ€ λΆ€μž¬ ν•΄κ²°
  • LLM μ‘λ‹΅μ˜ μ‹€μ‹œκ°„ μŠ€νŠΈλ¦¬λ°μ„ μœ„ν•œ 이벀트 기반 비동기 톡신 ν•„μš”
  • MCP(μ—μ΄μ „νŠΈ 도ꡬ) Β· A2A(μ—μ΄μ „νŠΈ κ°„ 톡신)와 ν•¨κ»˜ μ—μ΄μ „νŠΈ ν”„λ‘œν† μ½œ μŠ€νƒμ˜ UI 계측 λ‹΄λ‹Ή

AS-IS β€” REST μš”μ²­/응닡 방식

sequenceDiagram
    autonumber
    participant User
    participant UI
    participant Agent

    User->>UI: λ©”μ‹œμ§€ μž…λ ₯
    UI->>Agent: HTTP POST /chat
    Note over Agent: 전체 응닡 생성 (waiting...)
    Agent-->>UI: μ™„μ„±λœ 응닡 λ°˜ν™˜
    UI->>User: 응닡 ν‘œμ‹œ (ν•œ λ²ˆμ—)

TO-BE β€” AG-UI 이벀트 슀트리밍

sequenceDiagram
    autonumber
    participant User
    participant UI
    participant Agent

    User->>UI: λ©”μ‹œμ§€ μž…λ ₯
    UI->>Agent: RunAgentInput (threadId + runId)
    Agent-->>UI: RUN_STARTED
    Agent-->>UI: TEXT_MESSAGE_START
    Agent-->>UI: TEXT_MESSAGE_CONTENT (delta)
    Agent-->>UI: TEXT_MESSAGE_CONTENT (delta)
    Agent-->>UI: TEXT_MESSAGE_END
    Agent-->>UI: RUN_FINISHED
    UI->>User: μ‹€μ‹œκ°„ 슀트리밍 ν‘œμ‹œ

4계측 ꡬ쑰: Thread > Run > Step > Item

flowchart TD
    subgraph THREAD["Thread (threadId β€” λŒ€ν™” μ„Έμ…˜)"]
        subgraph RUN["Run (runId β€” μ‚¬μš©μž 1ν„΄)"]
            RUN_STARTED([RUN_STARTED])
            RUN_FINISHED([RUN_FINISHED])
            RUN_ERROR([RUN_ERROR])
            subgraph STEP["Step (선택적, N개 순차)"]
                STEP_STARTED[STEP_STARTED]
                STEP_FINISHED[STEP_FINISHED]
                subgraph MSG["Text Message"]
                    TMS[TEXT_MESSAGE_START]
                    TMC[TEXT_MESSAGE_CONTENT]
                    TME[TEXT_MESSAGE_END]
                end
                subgraph TOOL["Tool Call"]
                    TCS[TOOL_CALL_START]
                    TCA[TOOL_CALL_ARGS]
                    TCE[TOOL_CALL_END]
                    TCR[TOOL_CALL_RESULT]
                end
                subgraph REASON["Reasoning"]
                    RST[REASONING_START]
                    RMC[REASONING_MESSAGE_CONTENT]
                    REN[REASONING_END]
                end
            end
        end
    end
    RUN_STARTED --> STEP_STARTED
    STEP_STARTED --> TMS
    STEP_STARTED --> TCS
    STEP_STARTED --> RST
    TMS --> TMC
    TMC -->|반볡| TMC
    TMC --> TME
    TCS --> TCA
    TCA -->|반볡| TCA
    TCA --> TCE
    TCE --> TCR
    RST --> RMC
    RMC -->|반볡| RMC
    RMC --> REN
    TME --> STEP_FINISHED
    TCR --> STEP_FINISHED
    REN --> STEP_FINISHED
    STEP_FINISHED -->|λ‹€μŒ Step| STEP_STARTED
    STEP_FINISHED --> RUN_FINISHED
    RUN_STARTED -->|치λͺ…적 μ—λŸ¬| RUN_ERROR
    RUN_FINISHED -->|λ‹€μŒ μ‚¬μš©μž ν„΄| RUN_STARTED

28개 ν™œμ„± 이벀트 (μΉ΄ν…Œκ³ λ¦¬λ³„)

Lifecycle β€” 5개

μ΄λ²€νŠΈν•΅μ‹¬ ν•„λ“œμ˜λ―Έ
RUN_STARTEDthreadId, runIdμ—μ΄μ „νŠΈ μ‹€ν–‰ μ‹œμž‘
RUN_FINISHEDthreadId, runIdμ‹€ν–‰ 정상 μ™„λ£Œ
RUN_ERRORmessage, codeμ‹€ν–‰ 였λ₯˜ μ’…λ£Œ
STEP_STARTEDstepNameν•˜μœ„ 단계 μ‹œμž‘
STEP_FINISHEDstepNameν•˜μœ„ 단계 μ™„λ£Œ

Text Message β€” 4개

μ΄λ²€νŠΈν•΅μ‹¬ ν•„λ“œμ˜λ―Έ
TEXT_MESSAGE_STARTmessageId, roleν…μŠ€νŠΈ 슀트림 μ‹œμž‘
TEXT_MESSAGE_CONTENTmessageId, deltaν…μŠ€νŠΈ 청크 λˆ„μ 
TEXT_MESSAGE_ENDmessageIdν…μŠ€νŠΈ 슀트림 μ™„λ£Œ
TEXT_MESSAGE_CHUNKmessageId, deltaStart+Content+End μžλ™ ν™•μž₯ 편의 이벀트

Tool Call β€” 5개

μ΄λ²€νŠΈν•΅μ‹¬ ν•„λ“œμ˜λ―Έ
TOOL_CALL_STARTtoolCallId, toolCallName툴 호좜 μ‹œμž‘
TOOL_CALL_ARGStoolCallId, delta툴 인자 JSON 청크
TOOL_CALL_ENDtoolCallId툴 인자 전솑 μ™„λ£Œ
TOOL_CALL_RESULTtoolCallId, content툴 μ‹€ν–‰ κ²°κ³Ό (슀트리밍 μ•„λ‹˜)
TOOL_CALL_CHUNKtoolCallId, deltaStart+Args+End μžλ™ ν™•μž₯ 편의 이벀트

State Management β€” 3개

μ΄λ²€νŠΈν•΅μ‹¬ ν•„λ“œμ˜λ―Έ
STATE_SNAPSHOTsnapshot전체 μƒνƒœ (ν”„λ‘ νŠΈμ—”λ“œ ꡐ체)
STATE_DELTAdelta (RFC 6902)JSON Patch 증뢄 μ—…λ°μ΄νŠΈ
MESSAGES_SNAPSHOTmessagesλŒ€ν™” νžˆμŠ€ν† λ¦¬ 전체 μŠ€λƒ…μƒ·

Activity β€” 2개

μ΄λ²€νŠΈν•΅μ‹¬ ν•„λ“œμ˜λ―Έ
ACTIVITY_SNAPSHOTmessageId, activityType, contentμ§„ν–‰ ν™œλ™ 전체 μŠ€λƒ…μƒ· (PLAN, SEARCH λ“±)
ACTIVITY_DELTAmessageId, patchν™œλ™ JSON Patch 증뢄 μ—…λ°μ΄νŠΈ

Special β€” 2개

μ΄λ²€νŠΈν•΅μ‹¬ ν•„λ“œμ˜λ―Έ
RAWevent, sourceμ™ΈλΆ€ μ‹œμŠ€ν…œ 이벀트 pass-through
CUSTOMname, valueμ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν™•μž₯ 이벀트

Reasoning β€” 7개

μ΄λ²€νŠΈν•΅μ‹¬ ν•„λ“œμ˜λ―Έ
REASONING_STARTmessageIdμΆ”λ‘  ν”„λ‘œμ„ΈμŠ€ μ‹œμž‘
REASONING_MESSAGE_STARTmessageId, roleμΆ”λ‘  λ©”μ‹œμ§€ 슀트림 μ‹œμž‘
REASONING_MESSAGE_CONTENTmessageId, deltaμΆ”λ‘  청크
REASONING_MESSAGE_ENDmessageIdμΆ”λ‘  λ©”μ‹œμ§€ μ™„λ£Œ
REASONING_MESSAGE_CHUNKmessageId, delta편의 이벀트 (μžλ™ ν™•μž₯)
REASONING_ENDmessageIdμΆ”λ‘  ν”„λ‘œμ„ΈμŠ€ μ™„λ£Œ
REASONING_ENCRYPTED_VALUEsubtype, entityId, encryptedValueμ•”ν˜Έν™”λœ chain-of-thought

Deprecated 5개: THINKING_* β†’ λͺ¨λ‘ REASONING_*으둜 λŒ€μ²΄ (v1.0.0 제거 μ˜ˆμ •)

3κ°€μ§€ 섀계 νŒ¨ν„΄

1. Start-Content-End νŒ¨ν„΄ (슀트리밍)
   TEXT_MESSAGE_START β†’ TEXT_MESSAGE_CONTENT (반볡) β†’ TEXT_MESSAGE_END
   TOOL_CALL_START    β†’ TOOL_CALL_ARGS (반볡)       β†’ TOOL_CALL_END
   REASONING_START    β†’ REASONING_MESSAGE_CONTENT   β†’ REASONING_END

2. Snapshot-Delta νŒ¨ν„΄ (μƒνƒœ 동기화)
   STATE_SNAPSHOT β†’ STATE_DELTA (반볡) β†’ STATE_SNAPSHOT (μž¬λ™κΈ°ν™” μ‹œ)

3. Lifecycle νŒ¨ν„΄ (μ‹€ν–‰ 경계)
   RUN_STARTED β†’ (Steps/Items) β†’ RUN_FINISHED | RUN_ERROR

AG-UI vs Codex vs Claude CLI 이벀트 λ§€ν•‘

의미AG-UICodexClaude CLI (NDJSON)
μ„Έμ…˜(λŒ€ν™”)threadId (RUN_STARTED 포함)thread.startedν”„λ‘œμ„ΈμŠ€ spawn
ν„΄ μ‹œμž‘RUN_STARTEDturn.startedsystem { subtype:"init" }
ν…μŠ€νŠΈ μ‹œμž‘TEXT_MESSAGE_STARTitem.startedcontent_block_start { type:"text" }
ν…μŠ€νŠΈ 청크TEXT_MESSAGE_CONTENTitem.updatedcontent_block_delta { type:"text_delta" }
ν…μŠ€νŠΈ μ’…λ£ŒTEXT_MESSAGE_ENDitem.completedcontent_block_stop
툴 μ‹œμž‘TOOL_CALL_STARTitem.startedcontent_block_start { type:"tool_use" }
툴 인자TOOL_CALL_ARGSitem.updatedcontent_block_delta { type:"input_json_delta" }
툴 μ’…λ£ŒTOOL_CALL_ENDitem.completedcontent_block_stop
툴 κ²°κ³ΌTOOL_CALL_RESULTβ€”μ—†μŒ (Claude λ‚΄λΆ€ μ‹€ν–‰)
μΆ”λ‘  μ‹œμž‘REASONING_START + REASONING_MESSAGE_STARTβ€”content_block_start { type:"thinking" }
μΆ”λ‘  청크REASONING_MESSAGE_CONTENTβ€”content_block_delta { type:"thinking_delta" }
μΆ”λ‘  μ’…λ£ŒREASONING_MESSAGE_END + REASONING_ENDβ€”content_block_stop
ν„΄ 성곡RUN_FINISHEDturn.completedresult { subtype:"success" }
ν„΄ μ‹€νŒ¨RUN_ERRORturn.failedresult { subtype:"error_*" }
μΈν„°λŸ½νŠΈ(μ»€μŠ€ν…€ 이벀트)β€”result { subtype:"error_during_execution" }
치λͺ…적 μ—λŸ¬RUN_ERRORerrorν”„λ‘œμ„ΈμŠ€ crash (stdout μ’…λ£Œ)
μƒνƒœ 동기화STATE_SNAPSHOT / STATE_DELTAβ€”β€”
단계 ꡬ뢄STEP_STARTED / STEP_FINISHEDβ€”β€”

섀계 μ² ν•™ 비ꡐ

ν•­λͺ©AG-UICodexClaude CLI
컨텐츠 νƒ€μž… κ΅¬λΆ„νƒ€μž…λ³„ 별도 μ΄λ²€νŠΈλ‹¨μΌ item.* 톡합content_block.type ν•„λ“œ ꡬ뢄
툴 κ²°κ³ΌTOOL_CALL_RESULT μ‘΄μž¬β€”μ—†μŒ (μ—μ΄μ „νŠΈ λ‚΄λΆ€ μ‹€ν–‰)
μΆ”λ‘ (Thinking)7개 μ „μš© μ΄λ²€νŠΈβ€”thinking 블둝 νƒ€μž…
μƒνƒœ λ™κΈ°ν™”μ „μš© 이벀트 3μ’…β€”β€”
Step κ°œλ…λͺ…μ‹œμ  이벀트 μŒβ€”β€”
μ„Έμ…˜ vs ν„΄ 뢄리threadId + runId λͺ…μ‹œ 뢄리thread + turn λΆ„λ¦¬ν”„λ‘œμ„ΈμŠ€=μ„Έμ…˜, result=ν„΄ μ’…λ£Œ

μ°Έκ³  λ¬Έμ„œ