• **AG-UI(Agentโ€“User Interaction Protocol)**๋Š” AI ์—์ด์ „ํŠธ์™€ ์‚ฌ์šฉ์ž ๋Œ€๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‚ฌ์ด์˜ ์‹ค์‹œ๊ฐ„ ํ†ต์‹ ์„ ํ‘œ์ค€ํ™”ํ•˜๋Š” ์˜คํ”ˆ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ํ”„๋กœํ† ์ฝœ
  • ์—์ด์ „ํŠธ ๋ฐฑ์—”๋“œ๊ฐ€ ~16๊ฐœ์˜ ํ‘œ์ค€ ์ด๋ฒคํŠธ ํƒ€์ž…์„ ์ŠคํŠธ๋ฆฌ๋ฐ์œผ๋กœ emitํ•˜๋Š” ๊ฒฝ๋Ÿ‰ ์ถ”์ƒํ™” ๋ ˆ์ด์–ด
  • MCP(๋„๊ตฌ ์—ฐ๊ฒฐ), A2A(์—์ด์ „ํŠธ ๊ฐ„ ํ†ต์‹ )์™€ ํ•จ๊ป˜ ์—์ด์ „ํŠธ ํ”„๋กœํ† ์ฝœ ์Šคํƒ์˜ 3๋ฒˆ์งธ ์ถ• (Agent โ†” User)
  • CopilotKit์—์„œ LangGraphยทCrewAI ํŒŒํŠธ๋„ˆ์‹ญ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํƒ„์ƒํ•œ MIT ๋ผ์ด์„ ์Šค ์˜คํ”ˆ์†Œ์Šค

AG-UI๊ฐ€ ํ•ด๊ฒฐํ•˜๋ ค๋Š” ๋ฌธ์ œ

AG-UI ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋Š” ๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ํ•ต์‹ฌ ๋ฌธ์ œ๋ฅผ ๋ช…์‹œํ•œ๋‹ค.

1. ์ „ํ†ต์  ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๋ชจ๋ธ์˜ ํ•œ๊ณ„

Agentic applications break the simple request/response model that dominated frontend-backend development in the pre-agentic era.

์—์ด์ „ํŠธ๋Š” ์ผ๋ฐ˜ ์†Œํ”„ํŠธ์›จ์–ด์™€ ๋‹ค๋ฅธ ํŠน์„ฑ์„ ๊ฐ–๊ณ  ์žˆ์–ด ๊ธฐ์กด REST/GraphQL API๋กœ๋Š” ๋Œ€์‘์ด ์–ด๋ ต๋‹ค:

  • Long-running + streaming: ์—์ด์ „ํŠธ๋Š” ์žฅ๊ธฐ ์‹คํ–‰๋˜๋ฉฐ ์ค‘๊ฐ„ ์ž‘์—…์„ ์ŠคํŠธ๋ฆฌ๋ฐํ•œ๋‹ค (๋ฉ€ํ‹ฐํ„ด ์„ธ์…˜)
  • Nondeterministic UI control: ์—์ด์ „ํŠธ๊ฐ€ ๋น„๊ฒฐ์ •์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ UI๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค
  • Mixed IO: ํ…์ŠคํŠธยท์Œ์„ฑ ๊ฐ™์€ ๋น„๊ตฌ์กฐํ™” ๋ฐ์ดํ„ฐ์™€ tool callยทstate update ๊ฐ™์€ ๊ตฌ์กฐํ™” ๋ฐ์ดํ„ฐ๋ฅผ ๋™์‹œ์— ํ˜ผํ•ฉํ•œ๋‹ค
  • Recursive composition: ์„œ๋ธŒ ์—์ด์ „ํŠธ๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉฐ ์‚ฌ์šฉ์ž์™€ ์ƒํ˜ธ์ž‘์šฉํ•ด์•ผ ํ•œ๋‹ค

2. ๋ฒค๋”๋ณ„ ์ด๋ฒคํŠธ/ํ”„๋กœํ† ์ฝœ ํŒŒํŽธํ™”

LangGraph, CrewAI, Google ADK, AWS Strands, Mastra ๋“ฑ ๊ฐ ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ž์ฒด ๋„ค์ดํ‹ฐ๋ธŒ ์ด๋ฒคํŠธ ํฌ๋งท์„ ์‚ฌ์šฉํ•œ๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ฐ ๋ฒค๋”๋งˆ๋‹ค ๋ณ„๋„์˜ ad-hoc ์—ฐ๊ฒฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๋ฅผ AG-UI๋Š” ๋‘ ๊ฐ€์ง€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ํ•ด๊ฒฐํ•œ๋‹ค:

  • Flexible Event Structure: ์ด๋ฒคํŠธ๊ฐ€ AG-UI ํฌ๋งท๊ณผ ์ •ํ™•ํžˆ ์ผ์น˜ํ•˜์ง€ ์•Š์•„๋„ ๋จ โ€” AG-UI ํ˜ธํ™˜์ด๋ฉด ์ถฉ๋ถ„. ๊ธฐ์กด ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ตœ์†Œํ•œ์˜ ์ˆ˜์ •์œผ๋กœ ๋„ค์ดํ‹ฐ๋ธŒ ์ด๋ฒคํŠธ๋ฅผ ์ ์‘์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค
  • Middleware Layer: ๋А์Šจํ•œ ์ด๋ฒคํŠธ ํฌ๋งท ๋งค์นญ์„ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์—์ด์ „ํŠธ์™€ ์•ฑ ๊ฐ„์˜ ๊ด‘๋ฒ”์œ„ํ•œ ์ƒํ˜ธ์šด์šฉ์„ฑ์„ ๋ณด์žฅ

โ€œThis allows existing agent frameworks to adapt their native event formats with minimal effort.โ€ โ€” AG-UI Architecture Docs

ํ•ด๋‹น ๊ฐœ๋…์ด ํ•„์š”ํ•œ ์ด์œ 

  • ํ”„๋ ˆ์ž„์›Œํฌ๋งˆ๋‹ค ad-hoc์œผ๋กœ ํ”„๋ก ํŠธ ์—ฐ๊ฒฐ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋Œ€์‹  ํ‘œ์ค€ํ™”๋œ ์ด๋ฒคํŠธ ํ”„๋กœํ† ์ฝœ์ด ํ•„์š”
  • ๋ฒค๋” ๊ต์ฒด ์‹œ ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด ๋ฐฑ์—”๋“œ ์—์ด์ „ํŠธ๋งŒ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ๋Š” ์ถ”์ƒํ™” ๋ ˆ์ด์–ด ํ™•๋ณด
  • ํ•˜๋‚˜์˜ ์•ฑ์—์„œ ์—ฌ๋Ÿฌ ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋™์‹œ์— ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ ํ†ตํ•ฉ ์ธํ„ฐํŽ˜์ด์Šค ์—ญํ• 

AS-IS: ๋ฒค๋”๋ณ„ ad-hoc ์ŠคํŠธ๋ฆฌ๋ฐ ๊ตฌํ˜„

ad-hoc: โ€œ์ด๊ฒƒ์„ ์œ„ํ•ดโ€๋ผ๋Š” ๋ผํ‹ด์–ด. ๋ฒ”์šฉ์ ์ธ ํ‘œ์ค€ ์—†์ด ํŠน์ • ์ƒํ™ฉ์— ๋งž์ถฐ ์ฆ‰์„์—์„œ ๋งŒ๋“  ์ผํšŒ์„ฑ ๊ตฌํ˜„์„ ๋œปํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๊ฐ ๋ฒค๋” ํ”„๋ ˆ์ž„์›Œํฌ๋งˆ๋‹ค ๋ณ„๋„๋กœ ์ž‘์„ฑํ•˜๋Š” ์ „์šฉ ์–ด๋Œ‘ํ„ฐยทํŒŒ์‹ฑ ์ฝ”๋“œ๋ฅผ ์˜๋ฏธ.

sequenceDiagram
    autonumber
    participant App as Frontend App
    participant A1 as LangGraph Adapter
    participant A2 as CrewAI Adapter
    participant A3 as Google ADK Adapter
    participant LG as LangGraph Agent
    participant CR as CrewAI Agent
    participant GK as Google ADK Agent

    App->>A1: LangGraph ์ „์šฉ SSE ์—ฐ๊ฒฐ
    A1->>LG: LangGraph ๋„ค์ดํ‹ฐ๋ธŒ ์ด๋ฒคํŠธ
    LG-->>A1: astream_events() ํฌ๋งท
    A1-->>App: ํŒŒ์‹ฑ ๋กœ์ง A

    App->>A2: CrewAI ์ „์šฉ SSE ์—ฐ๊ฒฐ
    A2->>CR: CrewAI ๋„ค์ดํ‹ฐ๋ธŒ ์ด๋ฒคํŠธ
    CR-->>A2: kickoff() ํฌ๋งท
    A2-->>App: ํŒŒ์‹ฑ ๋กœ์ง B

    App->>A3: ADK ์ „์šฉ ์—ฐ๊ฒฐ
    A3->>GK: ADK ๋„ค์ดํ‹ฐ๋ธŒ ์ด๋ฒคํŠธ
    GK-->>A3: ADK ์ž์ฒด ํฌ๋งท
    A3-->>App: ํŒŒ์‹ฑ ๋กœ์ง C

    Note over App: ๋ฒค๋”๋งˆ๋‹ค ์–ด๋Œ‘ํ„ฐยทํŒŒ์‹ฑ ๋กœ์ง ๋ณ„๋„ ๊ตฌํ˜„<br/>๋ฐฑ์—”๋“œ ๊ต์ฒด ์‹œ ํ”„๋ก ํŠธ์—”๋“œ๋„ ์ „๋ฉด ์ˆ˜์ •

TO-BE: AG-UI ํ‘œ์ค€ ์ด๋ฒคํŠธ๋กœ ํ†ตํ•ฉ

sequenceDiagram
    autonumber
    participant App as Frontend App
    participant Client as AG-UI Client
    participant MW as AG-UI Middleware
    participant LG as LangGraph Agent
    participant CR as CrewAI Agent
    participant GK as Google ADK Agent

    App->>Client: runAgent(input)
    Client->>MW: ํ‘œ์ค€ RunAgentInput

    alt LangGraph ์‚ฌ์šฉ ์‹œ
        MW->>LG: ๋„ค์ดํ‹ฐ๋ธŒ ํ˜ธ์ถœ
        LG-->>MW: LangGraph ์ด๋ฒคํŠธ โ†’ AG-UI ๋ณ€ํ™˜
    else CrewAI ์‚ฌ์šฉ ์‹œ
        MW->>CR: ๋„ค์ดํ‹ฐ๋ธŒ ํ˜ธ์ถœ
        CR-->>MW: CrewAI ์ด๋ฒคํŠธ โ†’ AG-UI ๋ณ€ํ™˜
    else Google ADK ์‚ฌ์šฉ ์‹œ
        MW->>GK: ๋„ค์ดํ‹ฐ๋ธŒ ํ˜ธ์ถœ
        GK-->>MW: ADK ์ด๋ฒคํŠธ โ†’ AG-UI ๋ณ€ํ™˜
    end

    MW-->>Client: ๋™์ผํ•œ AG-UI ํ‘œ์ค€ ์ด๋ฒคํŠธ
    Client-->>App: Observable BaseEvent
    Note over App: ๋ฐฑ์—”๋“œ ๊ต์ฒดํ•ด๋„<br/>ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์Œ

Agentic Protocol Stack์—์„œ์˜ ์œ„์น˜

ํ”„๋กœํ† ์ฝœ์—ฐ๊ฒฐ ๋Œ€์ƒ์—ญํ• 
MCPAgent โ†” Tools & Data์—์ด์ „ํŠธ๊ฐ€ ์™ธ๋ถ€ ๋„๊ตฌยท๋ฐ์ดํ„ฐ ์†Œ์Šค์— ์—ฐ๊ฒฐ
A2A (Agent to Agent)Agent โ†” Agent์—์ด์ „ํŠธ ๊ฐ„ ์กฐ์œจยท์ž‘์—… ์œ„์ž„
AG-UIAgent โ†” User์—์ด์ „ํŠธ๋ฅผ ์‚ฌ์šฉ์ž ๋Œ€๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์—ฐ๊ฒฐ

์„ธ ํ”„๋กœํ† ์ฝœ์€ ์ƒํ˜ธ๋ณด์™„์ ์ด๋ฉฐ ํ•˜๋‚˜์˜ ์—์ด์ „ํŠธ๊ฐ€ ๋™์‹œ์— ์„ธ ๊ฐ€์ง€ ๋ชจ๋‘๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. AG-UI๋Š” MCP/A2A์™€์˜ ํ•ธ๋“œ์…ฐ์ดํฌ๋„ ์ œ๊ณตํ•˜์—ฌ AG-UI ํด๋ผ์ด์–ธํŠธ ์•ฑ์ด MCP/A2A ๊ธฐ๋ฐ˜ ์—์ด์ „ํŠธ๋ฅผ ํˆฌ๋ช…ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•ต์‹ฌ ์•„ํ‚คํ…์ฒ˜

์„ค๊ณ„ ์›์น™

  1. Event-Driven Communication: ์—์ด์ „ํŠธ๊ฐ€ 16๊ฐœ ํ‘œ์ค€ ์ด๋ฒคํŠธ ํƒ€์ž…์„ ์ŠคํŠธ๋ฆฌ๋ฐ์œผ๋กœ emit
  2. Bidirectional Interaction: ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์—์ด์ „ํŠธ์— ์ „๋‹ฌํ•˜์—ฌ ํ˜‘์—… ์›Œํฌํ”Œ๋กœ ์ง€์›
  3. Transport Agnostic: SSE, WebSocket, Webhook ๋“ฑ ์ „์†ก ๋ฐฉ์‹์— ๋ฌด๊ด€
  4. Flexible Event Structure: ๋„ค์ดํ‹ฐ๋ธŒ ์ด๋ฒคํŠธ ํฌ๋งท์„ AG-UI ํ˜ธํ™˜ํ•˜๊ฒŒ ๋งคํ•‘๋งŒ ํ•˜๋ฉด ๋จ

๊ตฌ์„ฑ ์š”์†Œ

graph LR
    subgraph Frontend
        A[Application] --> B[AG-UI Client]
    end
    subgraph Backend
        C[AI Agent A]
        D[AI Agent B]
        E[Secure Proxy]
    end
    B <-->|AG-UI Protocol| E
    E --> C
    E --> D
  • Application: ์‚ฌ์šฉ์ž ๋Œ€๋ฉด ์•ฑ (์ฑ„ํŒ… UI, AI ๊ธฐ๋Šฅ์ด ์žˆ๋Š” ์•ฑ)
  • AG-UI Client: HttpAgent ๋“ฑ ํ†ต์‹  ํด๋ผ์ด์–ธํŠธ. run(input) โ†’ Observable<BaseEvent> ์ธํ„ฐํŽ˜์ด์Šค
  • Agents: ์š”์ฒญ ์ฒ˜๋ฆฌ ํ›„ ์ŠคํŠธ๋ฆฌ๋ฐ ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฑ์—”๋“œ ์—์ด์ „ํŠธ
  • Secure Proxy: ๋ณด์•ˆ ํ”„๋ก์‹œ (API ํ‚ค ๋ณดํ˜ธ ๋“ฑ)

16๊ฐœ ์ด๋ฒคํŠธ ํƒ€์ž… ์ฒด๊ณ„

AG-UI์˜ ๋ชจ๋“  ํ†ต์‹ ์€ BaseEvent๋ฅผ ์ƒ์†ํ•˜๋Š” ํƒ€์ž…๋“œ ์ด๋ฒคํŠธ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

interface BaseEvent {
  type: EventType;
  timestamp?: number;
  rawEvent?: any;
}

Lifecycle Events (์‹คํ–‰ ์ƒ๋ช…์ฃผ๊ธฐ)

์ด๋ฒคํŠธ์„ค๋ช…
RUN_STARTED์—์ด์ „ํŠธ ์‹คํ–‰ ์‹œ์ž‘. threadId, runId ํฌํ•จ
RUN_FINISHED์‹คํ–‰ ์„ฑ๊ณต ์™„๋ฃŒ. ์„ ํƒ์  result ํฌํ•จ
RUN_ERROR์‹คํ–‰ ์ค‘ ๋ณต๊ตฌ ๋ถˆ๊ฐ€ ์—๋Ÿฌ. message, code ํฌํ•จ
STEP_STARTED์‹คํ–‰ ๋‚ด ๋‹จ๊ณ„ ์‹œ์ž‘. stepName (๋…ธ๋“œ/ํ•จ์ˆ˜๋ช…)
STEP_FINISHED๋‹จ๊ณ„ ์™„๋ฃŒ

Text Message Events (ํ…์ŠคํŠธ ๋ฉ”์‹œ์ง€ ์ŠคํŠธ๋ฆฌ๋ฐ)

Start โ†’ Content(๋ฐ˜๋ณต) โ†’ End ํŒจํ„ด:

์ด๋ฒคํŠธ์„ค๋ช…
TEXT_MESSAGE_START๋ฉ”์‹œ์ง€ ์‹œ์ž‘. messageId, role
TEXT_MESSAGE_CONTENTํ…์ŠคํŠธ ์ฒญํฌ. delta (non-empty)
TEXT_MESSAGE_END๋ฉ”์‹œ์ง€ ์™„๋ฃŒ
TEXT_MESSAGE_CHUNKํŽธ์˜ ์ด๋ฒคํŠธ โ€” Start/Content/End ์ž๋™ ํ™•์žฅ. ์ฒซ ์ฒญํฌ์—์„œ TEXT_MESSAGE_START ์ž๋™ ์ƒ์„ฑ, ๊ฐ delta๋งˆ๋‹ค TEXT_MESSAGE_CONTENT ์ž๋™ emit, ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ ์‹œ TEXT_MESSAGE_END ์ž๋™ ์ƒ์„ฑ. LLM API์˜ ์ฒญํฌ ์ŠคํŠธ๋ฆฌ๋ฐ ํฌ๋งท์„ ๊ฑฐ์˜ ๊ทธ๋Œ€๋กœ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์–ด ๋ฐฑ์—”๋“œ ์–ด๋Œ‘ํ„ฐ ๊ตฌํ˜„ ๋ณต์žก๋„๋ฅผ ์ค„์ด๋Š” sugar syntax

TEXT_MESSAGE_CHUNK ์ฝ”๋“œ ์˜ˆ์ œ

// โŒ Start/Content/End ์ˆ˜๋™ ๊ด€๋ฆฌ (๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ)
yield { type: EventType.TEXT_MESSAGE_START, messageId: "msg-1", role: "assistant" };
for await (const chunk of llmStream) {
  yield { type: EventType.TEXT_MESSAGE_CONTENT, messageId: "msg-1", delta: chunk.text };
}
yield { type: EventType.TEXT_MESSAGE_END, messageId: "msg-1" };
 
// โœ… TEXT_MESSAGE_CHUNK๋กœ ๋‹จ์ˆœํ™” (ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ž๋™ ํ™•์žฅ)
for await (const chunk of llmStream) {
  yield {
    type: EventType.TEXT_MESSAGE_CHUNK,
    messageId: "msg-1",   // ์ฒซ ์ฒญํฌ์—์„œ๋งŒ role ํฌํ•จ ์‹œ START ์ž๋™ ์ƒ์„ฑ
    role: "assistant",
    delta: chunk.text,
  };
}
// ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ ์‹œ END ์ž๋™ ์ƒ์„ฑ

Tool Call Events (๋„๊ตฌ ํ˜ธ์ถœ ์ŠคํŠธ๋ฆฌ๋ฐ)

Start โ†’ Args(๋ฐ˜๋ณต) โ†’ End โ†’ Result ํŒจํ„ด:

์ด๋ฒคํŠธ์„ค๋ช…
TOOL_CALL_START๋„๊ตฌ ํ˜ธ์ถœ ์‹œ์ž‘. toolCallId, toolCallName
TOOL_CALL_ARGS์ธ์ž ์ฒญํฌ(JSON fragment). delta
TOOL_CALL_END๋„๊ตฌ ํ˜ธ์ถœ ์™„๋ฃŒ
TOOL_CALL_RESULT๋„๊ตฌ ์‹คํ–‰ ๊ฒฐ๊ณผ. content
TOOL_CALL_CHUNKํŽธ์˜ ์ด๋ฒคํŠธ โ€” Start/Args/End ์ž๋™ ํ™•์žฅ. ์ฒซ ์ฒญํฌ์—์„œ TOOL_CALL_START ์ž๋™ ์ƒ์„ฑ, ๊ฐ delta(JSON fragment)๋งˆ๋‹ค TOOL_CALL_ARGS ์ž๋™ emit, ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ ์‹œ TOOL_CALL_END ์ž๋™ ์ƒ์„ฑ. LLM API์˜ tool call ์ŠคํŠธ๋ฆฌ๋ฐ ํฌ๋งท์„ ๊ฑฐ์˜ ๊ทธ๋Œ€๋กœ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์–ด ๋ฐฑ์—”๋“œ ์–ด๋Œ‘ํ„ฐ ๊ตฌํ˜„ ๋ณต์žก๋„๋ฅผ ์ค„์ด๋Š” sugar syntax

TOOL_CALL_CHUNK ์ฝ”๋“œ ์˜ˆ์ œ

// โŒ Start/Args/End ์ˆ˜๋™ ๊ด€๋ฆฌ (๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ)
yield { type: EventType.TOOL_CALL_START, toolCallId: "tc-1", toolCallName: "search_web" };
for await (const chunk of llmStream) {
  yield { type: EventType.TOOL_CALL_ARGS, toolCallId: "tc-1", delta: chunk.arguments };
}
yield { type: EventType.TOOL_CALL_END, toolCallId: "tc-1" };
 
// โœ… TOOL_CALL_CHUNK๋กœ ๋‹จ์ˆœํ™” (ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ž๋™ ํ™•์žฅ)
for await (const chunk of llmStream) {
  yield {
    type: EventType.TOOL_CALL_CHUNK,
    toolCallId: "tc-1",          // ์ฒซ ์ฒญํฌ์—์„œ๋งŒ toolCallName ํฌํ•จ ์‹œ START ์ž๋™ ์ƒ์„ฑ
    toolCallName: "search_web",
    delta: chunk.arguments,      // JSON fragment: '{"q' โ†’ '":"hello' โ†’ '"}'
  };
}
// ์ŠคํŠธ๋ฆผ ์ข…๋ฃŒ ์‹œ END ์ž๋™ ์ƒ์„ฑ

State Management Events (์ƒํƒœ ๋™๊ธฐํ™”)

Snapshot-Delta ํŒจํ„ด:

์ด๋ฒคํŠธ์„ค๋ช…
STATE_SNAPSHOT์ „์ฒด ์ƒํƒœ ์Šค๋ƒ…์ƒท
STATE_DELTAJSON Patch (RFC 6902) ๊ธฐ๋ฐ˜ ์ฆ๋ถ„ ์—…๋ฐ์ดํŠธ
MESSAGES_SNAPSHOT๋Œ€ํ™” ํžˆ์Šคํ† ๋ฆฌ ์ „์ฒด ์Šค๋ƒ…์ƒท

Activity Events

์ด๋ฒคํŠธ์„ค๋ช…
ACTIVITY_SNAPSHOTํ™œ๋™ ๋ฉ”์‹œ์ง€ ์ „์ฒด ์ƒํƒœ. activityType (์˜ˆ: โ€œPLANโ€, โ€œSEARCHโ€)
ACTIVITY_DELTAJSON Patch ๊ธฐ๋ฐ˜ ํ™œ๋™ ์ฆ๋ถ„ ์—…๋ฐ์ดํŠธ

Reasoning Events (์ถ”๋ก  ๊ณผ์ • ์‹œ๊ฐํ™”)

์ด๋ฒคํŠธ์„ค๋ช…
REASONING_START / REASONING_END์ถ”๋ก  ๊ณผ์ • ์‹œ์ž‘/์ข…๋ฃŒ
REASONING_MESSAGE_START / CONTENT / END์ถ”๋ก  ๋ฉ”์‹œ์ง€ ์ŠคํŠธ๋ฆฌ๋ฐ
REASONING_ENCRYPTED_VALUE์•”ํ˜ธํ™”๋œ chain-of-thought (ZTR ์ง€์›)

Special Events

์ด๋ฒคํŠธ์„ค๋ช…
RAW์™ธ๋ถ€ ์‹œ์Šคํ…œ ์ด๋ฒคํŠธ ํŒจ์Šค์Šค๋ฃจ. event, source
CUSTOM์•ฑ ์ „์šฉ ์ปค์Šคํ…€ ์ด๋ฒคํŠธ. name, value

3๊ฐ€์ง€ ์ด๋ฒคํŠธ ํ๋ฆ„ ํŒจํ„ด

  1. Start-Content-End: ์ŠคํŠธ๋ฆฌ๋ฐ ์ฝ˜ํ…์ธ ์šฉ (ํ…์ŠคํŠธ ๋ฉ”์‹œ์ง€, ๋„๊ตฌ ํ˜ธ์ถœ)
  2. Snapshot-Delta: ์ƒํƒœ ๋™๊ธฐํ™”์šฉ (์ „์ฒด ์Šค๋ƒ…์ƒท โ†’ JSON Patch ์ฆ๋ถ„)
  3. Lifecycle: ์‹คํ–‰ ๋ชจ๋‹ˆํ„ฐ๋ง์šฉ (Started โ†’ Finished/Error)

์‚ฌ์šฉ์ž ์งˆ์˜ ์‹œ ์ด๋ฒคํŠธ ํ๋ฆ„ ์˜ˆ์‹œ

โ€œ์˜ค๋Š˜ ๋‚ ์”จ ์–ด๋•Œ?โ€ ์งˆ์˜ ์‹œ ์‹ค์ œ ์ด๋ฒคํŠธ ์ˆœ์„œ:

RUN_STARTED

REASONING_START
REASONING_MESSAGE_CONTENT  { delta: "๋‚ ์”จ ๋„๊ตฌ๋ฅผ ์จ์•ผ๊ฒ ๋‹ค..." }
REASONING_END

TOOL_CALL_START  { toolCallId: "tc-1", toolCallName: "get_weather" }
TOOL_CALL_ARGS   { delta: '{"location":"seoul"}' }
TOOL_CALL_END
TOOL_CALL_RESULT { content: "์„œ์šธ ๋ง‘์Œ 22๋„" }

TEXT_MESSAGE_START   { messageId: "m1", role: "assistant" }
TEXT_MESSAGE_CONTENT { delta: "์˜ค๋Š˜ ์„œ์šธ์€ ๋ง‘๊ณ  22๋„์ž…๋‹ˆ๋‹ค." }
TEXT_MESSAGE_END

RUN_FINISHED
(MESSAGES_SNAPSHOT)  โ† ์„ ํƒ์ . ์ „์ฒด ๋Œ€ํ™” ํžˆ์Šคํ† ๋ฆฌ ๋™๊ธฐํ™”

์ด๋ฒคํŠธ ์—ญํ•  ๋ถ„๋ฆฌ

์ด๋ฒคํŠธ ์ข…๋ฅ˜UI ํ‘œํ˜„๋Œ€ํ™” ํžˆ์Šคํ† ๋ฆฌ ๊ธฐ๋ก
REASONING_*์ ‘์„ ์ˆ˜ ์žˆ๋Š” โ€œThinkingโ€ฆโ€ ์˜์—ญโŒ
TOOL_CALL_*์ž‘์€ ๋ฐฐ์ง€/์ธ๋””์ผ€์ดํ„ฐโŒ
TEXT_MESSAGE_*๋ฉ”์ธ ์‘๋‹ต ์˜์—ญโœ…

ํ•ต์‹ฌ: ๊ณผ์ •(REASONING/TOOL_CALL)๊ณผ ๊ฒฐ๊ณผ(TEXT_MESSAGE)๋Š” ๋ชจ๋‘ ์ด๋ฒคํŠธ๋กœ ์ „๋‹ฌ๋œ๋‹ค. ๋‹จ, TEXT_MESSAGE๋งŒ messages ๋ฐฐ์—ด์— ๊ธฐ๋ก๋˜์–ด ๋‹ค์Œ LLM ํ˜ธ์ถœ ์‹œ ์ปจํ…์ŠคํŠธ๋กœ ์ „๋‹ฌ๋œ๋‹ค. ๊ณผ์ • ์ด๋ฒคํŠธ๋ฅผ โ€œ์ˆจ๊ธด๋‹คโ€๋Š” ๊ฒƒ์€ ํ”„๋กœํ† ์ฝœ ๋™์ž‘์ด ์•„๋‹ˆ๋ผ ํ”„๋ก ํŠธ์—”๋“œ์˜ UI ์„ค๊ณ„ ์„ ํƒ์ด๋‹ค.

Building Blocks (๊ธฐ๋Šฅ ๋ธ”๋ก)

๊ธฐ๋Šฅ์„ค๋ช…
Streaming Chat์‹ค์‹œ๊ฐ„ ํ† ํฐยท์ด๋ฒคํŠธ ์ŠคํŠธ๋ฆฌ๋ฐ, ์ทจ์†Œ/์žฌ๊ฐœ
MultimodalityํŒŒ์ผ, ์ด๋ฏธ์ง€, ์˜ค๋””์˜ค, ํŠธ๋žœ์Šคํฌ๋ฆฝํŠธ ๋“ฑ ๋‹ค์ค‘ ๋ชจ๋‹ฌ
Generative UI (static)๋ชจ๋ธ ์ถœ๋ ฅ์„ ์•ฑ์ด ์ œ์–ดํ•˜๋Š” ์•ˆ์ •์  ์ปดํฌ๋„ŒํŠธ๋กœ ๋ Œ๋”๋ง
Generative UI (declarative)์—์ด์ „ํŠธ๊ฐ€ UI ํŠธ๋ฆฌ์™€ ์ œ์•ฝ์„ ์ œ์•ˆ, ์•ฑ์ด ๊ฒ€์ฆยท๋งˆ์šดํŠธ
Shared State์—์ด์ „ํŠธโ†”์•ฑ ๊ฐ„ ํƒ€์ž…๋“œ ์Šคํ† ์–ด. ์ด๋ฒคํŠธ ์†Œ์‹ฑ diff + ์ถฉ๋Œ ํ•ด๊ฒฐ
Frontend Tool Calls์—์ด์ „ํŠธ โ†’ ํ”„๋ก ํŠธ์—”๋“œ ์‹คํ–‰ ์•ก์…˜ ํ•ธ๋“œ์˜คํ”„
Interrupts (HITL)์ค‘๊ฐ„์— ์Šน์ธยทํŽธ์ง‘ยท์žฌ์‹œ๋„ยท์—์Šค์ปฌ๋ ˆ์ด์…˜
Sub-agents์Šค์ฝ”ํ”„๋œ ์ƒํƒœยทํŠธ๋ ˆ์ด์‹ฑยท์ทจ์†Œ๊ฐ€ ์žˆ๋Š” ์ค‘์ฒฉ ์œ„์ž„

์ฝ”๋“œ ์˜ˆ์ œ: HttpAgent ์‚ฌ์šฉ

import { HttpAgent, EventType } from '@ag-ui/core';
 
const agent = new HttpAgent({
  url: "https://your-agent-endpoint.com/agent",
  agentId: "unique-agent-id",
  threadId: "conversation-thread"
});
 
agent.runAgent({
  tools: [...],
  context: [...]
}).subscribe({
  next: (event) => {
    switch(event.type) {
      case EventType.TEXT_MESSAGE_CONTENT:
        // UI์— ์ŠคํŠธ๋ฆฌ๋ฐ ํ…์ŠคํŠธ ํ‘œ์‹œ
        break;
      case EventType.TOOL_CALL_START:
        // ๋„๊ตฌ ํ˜ธ์ถœ ์‹œ์ž‘ ํ‘œ์‹œ
        break;
      case EventType.STATE_DELTA:
        // JSON Patch๋กœ ๋กœ์ปฌ ์ƒํƒœ ์—…๋ฐ์ดํŠธ
        break;
    }
  },
  error: (err) => console.error("Agent error:", err),
  complete: () => console.log("Agent run complete")
});

์ง€์› ํ†ตํ•ฉ ํ˜„ํ™ฉ

Agent ํ”„๋ ˆ์ž„์›Œํฌ

ํ”„๋ ˆ์ž„์›Œํฌ์ƒํƒœ๋น„๊ณ 
LangGraphโœ… SupportedํŒŒํŠธ๋„ˆ์‹ญ
CrewAIโœ… SupportedํŒŒํŠธ๋„ˆ์‹ญ
Microsoft Agent Frameworkโœ… Supported1st Party
Google ADKโœ… Supported1st Party
AWS Strands Agentsโœ… Supported1st Party
Mastraโœ… Supported1st Party
Pydantic AIโœ… Supported1st Party
Agno, LlamaIndex, AG2โœ… Supported1st Party
OpenAI Agent SDK๐Ÿ› ๏ธ In Progress์ปค๋ฎค๋‹ˆํ‹ฐ

SDK

TypeScript(๊ณต์‹), Python, Kotlin, Golang, Dart, Java, Rust, Ruby ์ง€์›

ํด๋ผ์ด์–ธํŠธ

ํด๋ผ์ด์–ธํŠธ์ƒํƒœ
CopilotKitโœ… Supported (1st Party)
Terminal + Agentโœ… Supported (Community)
React Native๐Ÿ› ๏ธ Help Wanted

์ฐธ๊ณ  ๋ฌธ์„œ