agent-chatlisted
Install: claude install-skill relayax/relayagent
# 에이전트 채팅 붙이기
에이전트 패키지의 화면(view)에 대화 기능을 넣는 방법을 다룬다. 결론부터 말하면
**채팅 UI 를 처음부터 만들 일은 거의 없다.** 기판(relay 데몬)이 완성된 채팅 클라이언트를
모든 패키지에 제공하고, 이 문서는 그것을 상황에 맞게 꽂는 방법이다.
## 기판이 주는 것
기판은 위젯 번들 한 벌을 정적 자산으로 서빙한다. 어느 패키지 화면에서든 URL 로 바로 불러 쓴다.
| 자산 | 무엇인가 |
|---|---|
| `/assets/chat-app.js` | 완성된 채팅 UI (ESM). 세션 탭, 첨부(선택·드래그·붙여넣기), 진행 표시, 이력 복원, 모델 설정 포함. `mount`·`mountTabs` 를 수출한다 |
| `/assets/chat-app.css` | 그 위젯의 스타일. **같이 링크해야 한다** — 빠뜨리면 마크업만 뜨고 레이아웃이 무너진다 |
번들은 하네스(에이전트 CLI)와의 연결지점이라 기판과 함께 갱신된다(no-store 서빙).
기판의 대화 API 가 바뀌면 번들도 같이 바뀌므로 화면이 깨지지 않는다. 직접 만든 채팅 UI 나
복사해 둔 사본에는 그 보장이 없다 — 조용히 어긋난다.
> 예전에는 `chat-widget.js`(UI)와 `chat-core.js`(headless) 두 자산이었다. 클라이언트 전송
> 계약 v1 컷에서 **한 번들로 합쳐졌고 구 이름은 서빙되지 않는다**. headless 소비는 아래
> 시나리오 4 를 보라.
## 좌표는 기판이 주입한다 — URL 을 파싱하지 마라
위젯은 자기가 어느 기판의 어느 인스턴스에 붙는지를 **주입으로만** 받는다. 패키지 view 를
서빙할 때 기판이 문서 머리에 심는다:
```html
<script>window.__RELAY_CONTEXT={base:"/pkg/<설치이름>",root:"",instanceId:"<설치이름>"};</script>
```
그래서 화면 코드는 설치 이름을 알 필요가 없다. **`location.pathname` 에서 `/pkg/<이름>/view`
를 파싱하던 구 관용구는 은퇴했다** — 마운트 문법(`/pkg/`·`/i/`)을 클라이언트가 조립하는 것은
계약 위반이고, 같은 패키지가 다른 마운트(조직 기판의 `/i/<id>`)에 서는 순간 깨진다.
좌표가 없으면 위젯은 조립을 시도하지 않고 콘솔에 판정을 남기며 마운트를 포기한다(fail-loud).
## 네 가지 시나리오
필요한 만큼만 내려가라. 위 시나리오로 충분하면 아래를 만들지 마라.
### 1. 대화만 있으면 된다 — 화면 없이
패키지가 대화형 도우미라 전용 화면이 필요 없는 경우. **아무것도 선언하지 않아도 된다** —
에이전트가 있고 `surfaces.view` 가 없으면 기판이 `/pkg/<이름>/view/` 에 전체 화면 대화를
세운다. 대화 표면은 선언이 아니라 `agents[]` 에서 도출된다.
첫 인사말만 얹고 싶으면 그 말을 하는 에이전트에 붙인다:
```yaml
agents:
-