본문으로 건너뛰기

OpenUI 사용

오픈UI생성 UI에 대한 개방형 표준입니다. 컴팩트 스트리밍 우선 언어(OpenUI Lang)를 React 런타임 및 내장 구성 요소 라이브러리와 결합하여 Model 출력이 스트리밍할 때 구조화된 UI로 렌더링될 수 있습니다.

OpenUI는 다음을 통해 Mastra에 연결됩니다.AG-UI protocol. The @ag-ui/mastra어댑터는 마스트라를 감쌉니다Agent그리고 OpenUI의 AG-UI 이벤트를 내보냅니다.agUIAdapter()클라이언트에서 구문 분석합니다.

전체 작업 예제를 보려면 다음을 참조하세요.mastra-chat example in the OpenUI repository.

통합 가이드
통합 가이드에 대한 직접 링크

Next.js API 경로에 Mastra를 포함하고 OpenUI를 연결하세요.<AgentInterface /> 채팅 화면을 AG-UI 프로토콜을 통해 연결합니다.

  1. 새로운 OpenUI 앱을 스캐폴드합니다.

    npx @openuidev/cli@latest create --name openui-mastra-chat

    새로 생성된 프로젝트 디렉터리로 이동합니다.

    cd openui-mastra-chat

    스캐폴드된 앱은 다음 구조를 가진 Next.js 프로젝트입니다.

    openui-mastra-chat
    └── src
    ├── app
    │ ├── api
    │ │ └── chat
    │ │ └── route.ts
    │ ├── globals.css
    │ ├── layout.tsx
    │ └── page.tsx
    ├── generated
    │ └── system-prompt.txt
    └── library.ts

    채팅 경로는 다음 위치에 있습니다.src/app/api/chat/route.ts, the chat surface in src/app/page.tsx, and the component library in src/library.ts. The OpenUI CLI writes src/generated/system-prompt.txt 를 라이브러리에서 생성하며, 라이브러리가 변경될 때마다 다시 생성합니다.

    OpenAI 키를 다음에 추가하세요..env.local:

    .env.local
    OPENAI_API_KEY=sk-...
    노트

    OpenUI에는 Model 공급자 키가 필요합니다. Mastra가 지원하는 공급자를 사용하고 다음 단계에서 Agent 구성을 조정하세요.

  2. Mastra 패키지와 Mastra용 AG-UI 어댑터를 설치합니다.

    npm install @mastra/core @ag-ui/mastra @ag-ui/core zod

    @ag-ui/mastra마스트라를 감싸다Agent in a MastraAgent that emits AG-UI protocol events. OpenUI's agUIAdapter() consumes those events on the client.

  3. 열려 있는src/app/api/chat/route.ts. Define any tools your agent needs with createTool from @mastra/core/tools:

    src/app/api/chat/route.ts
    import { createTool } from '@mastra/core/tools'
    import { z } from 'zod'

    const getWeather = createTool({
    id: 'get_weather',
    description: 'Get current weather for a city.',
    inputSchema: z.object({ location: z.string().describe('City name') }),
    execute: async ({ location }) => {
    return { location, temperature_celsius: 22, condition: 'Clear' }
    },
    })

    마스트라를 감싸다Agent in MastraAgent. Agent가 OpenUI 컴포넌트 라이브러리를 사용하는 방법을 알 수 있도록 생성된 system Prompt를 주입합니다:

    src/app/api/chat/route.ts
    import { MastraAgent } from '@ag-ui/mastra'
    import { Agent } from '@mastra/core/agent'
    import { readFileSync } from 'fs'
    import { join } from 'path'

    const systemPrompt = readFileSync(join(process.cwd(), 'src/generated/system-prompt.txt'), 'utf-8')

    const agent = new MastraAgent({
    agent: new Agent({
    id: 'openui-agent',
    name: 'OpenUI Agent',
    instructions: `You are a helpful assistant. Use tools when relevant.\n\n${systemPrompt}`,
    model: {
    id: 'openai/gpt-5.6-sol',
    apiKey: process.env.OPENAI_API_KEY,
    },
    tools: { getWeather },
    }),
    resourceId: 'chat-user',
    })

    내보내기POST handler는 Agent의 AG-UI 이벤트를 Server-Sent Events(SSE)로 스트리밍합니다:

    src/app/api/chat/route.ts
    import type { Message } from '@ag-ui/core'
    import { NextRequest } from 'next/server'

    export async function POST(req: NextRequest) {
    const { messages, threadId }: { messages: Message[]; threadId: string } = await req.json()
    const encoder = new TextEncoder()

    const stream = new ReadableStream({
    start(controller) {
    const subscription = agent
    .run({ messages, threadId, runId: crypto.randomUUID(), tools: [], context: [] })
    .subscribe({
    next: event => {
    controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\n\n`))
    },
    complete: () => {
    controller.enqueue(encoder.encode('data: [DONE]\n\n'))
    controller.close()
    },
    error: error => {
    controller.enqueue(
    encoder.encode(`data: ${JSON.stringify({ error: error.message })}\n\n`),
    )
    controller.close()
    },
    })

    req.signal.addEventListener('abort', () => subscription.unsubscribe())
    },
    })

    return new Response(stream, {
    headers: {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache, no-transform',
    Connection: 'keep-alive',
    },
    })
    }
  4. OpenUI 연결<AgentInterface /> chat surface to the route. Build an llm adapter with fetchLLM() and set streamAdapter to agUIAdapter() so OpenUI knows to parse AG-UI events.

    src/app/page.tsx
    'use client'

    import '@openuidev/react-ui/components.css'

    import { AgentInterface, agUIAdapter, fetchLLM } from '@openuidev/react-ui'
    import { openuiChatLibrary } from '@openuidev/react-ui/genui-lib'

    const llm = fetchLLM({
    url: '/api/chat',
    streamAdapter: agUIAdapter(),
    })

    export default function Page() {
    return (
    <div className="relative h-screen w-screen overflow-hidden">
    <AgentInterface llm={llm} componentLibrary={openuiChatLibrary} />
    </div>
    )
    }

    그만큼componentLibrary prop은 Model이 생성할 수 있는 컴포넌트를 제어합니다. openuiChatLibrary 를 자체 라이브러리로 교체하여 출력을 제한하거나 확장합니다.

  5. 개발 서버를 시작합니다.

    npm run dev

    열려 있는http://localhost:3000. 이제 OpenUI 채팅 화면을 통해 Mastra Agent와 채팅할 수 있으며, Model이 스트리밍하는 동안 구조화된 UI가 점진적으로 렌더링됩니다.

AG-UI를 사용한 스트리밍
AG-UI를 사용한 스트리밍에 대한 직접 링크

OpenUI는AG-UI protocol. 이는 AI Agent를 위한 전송 방식 독립적인 형식 지정 이벤트 스트림입니다. @ag-ui/mastra translates a Mastra Agent into this protocol:

  • 서버가 호출agent.run({ messages, threadId, runId, ... }) 를 사용하며, 내보낸 각 이벤트를 SSE 메시지로 직렬화합니다.
  • 클라이언트가 통과fetchLLM({ streamAdapter: agUIAdapter() }) to <AgentInterface />. 이는 SSE 스트림을 OpenUI Lang 렌더링을 구동하는 내부 이벤트로 파싱합니다.

threadId여러 요청에 걸쳐 대화를 하나로 묶습니다.runId identifies a single execution. Generate a fresh runId per request and persist threadId on the client.

구성 요소 라이브러리
구성 요소 라이브러리에 대한 직접 링크

OpenUI는 구성 요소 라이브러리에서 UI를 생성합니다. 라이브러리는 사용 가능한 구성 요소, 해당 소품, Model이 해당 구성 요소를 사용하도록 지시하는 방법을 정의합니다.

내장 라이브러리
내장 라이브러리에 대한 직접 링크

@openuidev/react-ui있는 그대로 사용할 수 있는 두 개의 라이브러리를 제공합니다.

  • openuiChatLibrary: 채팅 인터페이스용 구성 요소(카드, 양식, 표, 차트)입니다.
  • openuiDashboardLibrary: 대시보드 및 데이터가 많은 표면을 위한 구성 요소입니다.

도서관을 넘겨주세요<AgentInterface componentLibrary={...} /> 를 사용해 해당 컴포넌트를 Model에서 사용할 수 있도록 합니다.

라이브러리 사용자 정의
라이브러리 사용자 정의에 대한 직접 링크

출력을 제한하거나 확장하려면 다음에서 자신의 라이브러리를 정의하십시오.src/library.ts 를 만들고 컴포넌트의 일부를 내보냅니다. 해당 라이브러리를 <AgentInterface /> 에 전달하고 라이브러리가 변경될 때마다 system Prompt를 다시 생성합니다:

npx @openuidev/cli generate src/library.ts --out src/generated/system-prompt.txt

생성된 Prompt는 API 경로로 읽혀지고 Agent의 Prompt에 병합됩니다.instructions, 따라서 Agent는 어떤 컴포넌트를 출력할 수 있는지 정확히 알 수 있습니다.