대시보드
Morit Plugin3. 화면과 사용자 경험

Response UI와 Agent Timeline

Response UI는 capability 결과를 AI 메시지 안에서 시각화합니다. AI는 필요한 A2UI Native Tool을 선택하지만 Host는 우선 최종 텍스트 답변을 완료·저장합니다. 컴포넌트는 데이터 준비와 검증이 모두 성공한 뒤 해당 AI 메시지 본문 아래에 한 번에 자연스럽게 표시됩니다. Tool이 실패해도 답변 완료 상태는 바뀌지 않습니다.

Response extension

json
{
  "id": "school_life.day_response",
  "point": "response",
  "title": "오늘 학교 생활",
  "order": 10,
  "permissions": [],
  "config": {
    "ui_schema": 2,
    "a2ui": {
      "version": "v0.9",
      "description": "수업 정보가 실제 답변에 필요하고 표시할 항목이 있을 때만 사용합니다.",
      "schema": {
        "type": "object",
        "properties": {
          "timetable": {
            "type": "array",
            "items": {"type": "object"},
            "minItems": 1,
            "maxItems": 12
          }
        },
        "required": ["timetable"],
        "additionalProperties": true
      }
    },
    "theme": {"density": "compact"},
    "data_sources": [
      {
        "id": "result",
        "capability": "school_life.schedule.lookup",
        "trigger": "manual",
        "query": "",
        "arguments": {}
      }
    ],
    "view": {
      "type": "column",
      "props": {"spacing": 10},
      "children": [
        {
          "type": "text",
          "props": {"text": "{{data.result.summary}}", "style": "heading"}
        },
        {
          "type": "timeline",
          "props": {"source": "data.result.data.timetable", "empty_text": "수업 정보가 없습니다."},
          "children": [
            {
              "type": "text",
              "props": {"text": "{{item.period}}교시 · {{item.subject}}"}
            }
          ]
        }
      ]
    }
  }
}

Response point도 일반 Runtime v2와 같은 node, theme, app bar, navigation, binding, action 계약을 사용합니다. Host가 선택·검증한 capability 결과는 data namespace에 주입되므로 같은 결과를 얻기 위해 화면 mount 시 외부 요청을 반복하지 않습니다. 후속 refresh나 사용자가 누른 action에만 추가 capability를 호출합니다. 기존 a2ui 선언이 없는 Response extension은 지원하지 않습니다.

AI 선택과 Host 검증

서버는 모든 Tool 결과에 UI를 일괄 생성하거나 키워드 정규식으로 컴포넌트를 강제하지 않습니다. 최종 답변 모델은 통합 Registry Skill의 용도와 입력 Schema를 의미적으로 비교해 Native Tool을 선택합니다. provider 컴포넌트에는 위치·통화·검색어만 넘기고, Host가 비동기로 실시간 데이터를 조회합니다. generated 컴포넌트에는 답변에 근거한 차트 값만 Schema에 맞게 전달합니다. Plugin 결과는 Host가 검증한 후보 데이터만 사용합니다.

선택 뒤 Host는 다음을 모두 통과한 항목만 A2UI v0.9 DataPart로 저장하고 해당 AI 메시지에 붙입니다.

  • 실행 상태가 completed 또는 partial이고 실제 값이 있음
  • 질문·최종 답변과 capability 결과가 관련됨
  • 같은 데이터의 Response UI가 이미 선택되지 않음
  • 기본 컴포넌트별 필수 값과 URL 형식이 유효함
  • Plugin 컴포넌트의 schema, A2UI version, 설치 상태, Instance 권한과 capability 연결이 유효함

빈 데이터, 실패한 Tool, 무관하거나 중복된 결과, 불확실한 선택은 UI를 만들지 않습니다. 선택 모델 호출이나 렌더링이 실패해도 일반 텍스트 답변은 그대로 완료됩니다. 로딩 문구, skeleton, 빈 card는 렌더링하지 않고 준비가 끝난 컴포넌트만 한 번 표시합니다.

기본 A2UI Component Catalog

component표시 조건
weather현재 기온·상태 또는 예보가 하나 이상 유효함
world_clock1~8개 위치의 IANA timezone과 현재 시각이 유효함
chartlabel과 수치가 있는 행이 2개 이상임; bar, line, pie, scatter
image_galleryHTTPS 이미지와 원문 URL·출처명이 함께 있음
exchange_rate기준 통화, 상대 통화, 유한한 환율 값이 있음
article_list제목·출처·원문이 있는 서로 다른 기사 2개 이상
article_card제목·출처·요약·본문 일부·원문이 있고, 게시 시각·이미지는 제공될 때 표시
file_result실제 Morit item ID 또는 검증 가능한 다운로드 URL이 있음
image_preview실제 image item 또는 검증 가능한 preview URL이 있음
video_preview실제 video item/URL과 thumbnail URL이 함께 있음

weather, exchange_rate, world_clock, article_list, article_card, image_gallery는 provider mode이고 chart는 generated mode입니다. 기사와 이미지는 페이지 이동·다시 시도, gallery는 반응형 grid/carousel을 지원합니다. 표는 일반 Markdown으로 답변하고 단계별 텍스트 slider는 catalog에서 제거되었습니다. 각 renderer도 같은 필수 값을 다시 확인하고, 값이 바뀌거나 손상되면 해당 컴포넌트만 fallback합니다.

Plugin 컴포넌트의 동적 등록

활성 Instance의 point: "response" extension은 capability 실행 시 plugin.<extension-id> 이름으로 현재 A2UI catalog에 동적 등록됩니다. AI에게는 Host가 확인한 ID, 설명, version, schema만 노출됩니다. a2ui.schema는 root object인 안전한 JSON Schema 부분집합이며 type, properties, required, additionalProperties, items, enum, 문자열·숫자·배열 bound를 지원합니다. schema는 최대 16 KiB, 깊이 6이며 object/list는 각 64개로 제한됩니다.

Plugin Response는 Runtime v2의 전체 layout, surface, theme, image, action과 binding을 사용할 수 있습니다. 단, extension 권한은 Manifest grant의 부분집합이어야 하고 data_sources 중 하나가 실제 실행 capability를 가리켜야 합니다. 패키지 설치, CLI validate, Host 로드, Flutter parse와 표시 직전 검증이 같은 규칙을 사용합니다.

한 container의 정보 순서

  1. 결과를 설명하는 짧은 제목 또는 summary
  2. 사용자가 요청한 핵심 데이터
  3. 출처·기간·갱신 시점 같은 보조 정보
  4. 필요한 후속 행동 1~2개

복사, 다시 시도, 다운로드 같은 메뉴도 같은 container의 Host chrome에 속합니다. 각 section을 별도 떠 있는 card로 만들지 않습니다. 긴 결과는 list limit과 상세 화면 이동을 사용합니다.

대화 UI를 깨뜨리지 않는 제약

  • 메시지 폭을 넘는 고정 width를 사용하지 않습니다.
  • Response 내부에 자체 채팅 입력창을 만들지 않습니다.
  • 무한 높이 목록 대신 요약과 상세 화면 이동을 제공합니다.
  • background refresh가 대화 scroll 위치를 바꾸지 않게 기존 높이와 데이터를 가능한 유지합니다.
  • 렌더링 오류는 해당 Response UI를 생략하고 이미 완료된 텍스트 답변을 유지합니다.
  • accessibility 순서는 AI 본문 다음, Response 제목, 내용, 행동 순으로 유지합니다.

Text fallback

Response UI를 표시할 수 없더라도 AI의 원래 텍스트 답변은 남아야 합니다. capability는 UI 전용 원시 JSON만 반환하지 말고 사람이 읽을 수 있는 summary를 함께 제공합니다. 빈 배열만 있거나 schema가 맞지 않으면 UI를 억지로 채우지 않습니다. 알 수 없는 node, 손상된 binding, 이미지 로드 실패는 전체 답변 성공을 숨기지 않습니다.

json
{
  "completed": true,
  "summary": "오늘은 6교시이며 점심은 카레라이스입니다.",
  "data": {
    "timetable": [],
    "meal": {}
  },
  "evidence": []
}

Agent Timeline

Agent Timeline은 모델의 숨겨진 추론이 아니라 사용자가 이해할 수 있는 실행 상태만 보여줍니다.

text
요청을 확인하고 계획했어요
  ├─ 학교 정보를 확인했어요
  ├─ 오늘 시간표를 불러왔어요
  └─ 결과를 정리했어요

Timeline event에는 도구 이름이나 내부 stack trace 대신 작업 이름, 상태, 필요한 사용자 행동을 기록합니다. 상태는 대체로 다음과 같습니다.

  • 진행 중
  • 완료
  • 재시도 중
  • 사용자 입력 필요
  • 일부 결과로 완료
  • 실패

Tool 하나가 실패했지만 대체 경로로 결과를 만들었다면 전체 timeline을 실패로 표시하지 않습니다. 실패한 단계와 복구 결과를 함께 설명합니다.

Code Interpreter 파일

Code Interpreter가 파일을 만들었다면 sandbox 내부 경로만 답변에 남기지 않습니다. 파일은 Host가 접근 가능한 artifact로 전달되고, AI 답변에는 실제 파일 이름·형식·크기와 다운로드 가능한 링크가 있어야 합니다. Response UI의 다운로드 action은 동일 artifact를 가리키며 존재하지 않는 경로나 가짜 링크를 생성하지 않습니다.

파일 생성 완료 조건은 AI Skill과 파일 산출물에 정리되어 있습니다.

이미지 artifact

image_generation·image_edit의 PNG/JPEG/GIF/WebP artifact는 생성 중 placeholder에서 완료 후 답변 내 inline 이미지로 바뀝니다. 여러 장은 gallery로 넘기며 원본 비율을 유지한 contain 렌더링, 전체 화면 InteractiveViewer, 다운로드, Android 공유를 제공합니다. 대화 재진입 때도 저장된 ai_tool_executions.result_summary.artifacts를 다시 사용합니다.

Artifact URL은 conversation·execution·attachment 소유권을 확인한 뒤 5분 signed URL로 만들며 만료나 일시 실패 시 새 URL을 받아 두 번 시도합니다. 앱은 redirect를 따르지 않고 HTTPS(개발 loopback 제외), MIME, magic byte, 실제 decode, 24 MiB, 4096 px, 16 MP를 확인합니다. SVG와 외부 실행 형식은 inline으로 열지 않고 기존 파일 카드로 fallback합니다. Plugin response의 URL 이미지는 앱이 직접 요청하지 않고 기존 인증 Host proxy와 network grant를 거치며 실패 시 이미지 단위 재시도를 제공합니다.