> ## Documentation Index
> Fetch the complete documentation index at: https://docs.myrmagent.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 다중 채널

> 채널 인식 출력을 통해 에이전트를 35개 이상의 메시징 플랫폼에 연결하세요.

# 다중 채널 통합

자동 형식 조정 기능을 갖춘 35개 이상의 채널 등 모든 메시징 플랫폼에서 에이전트에 액세스하세요.

## 지원되는 채널

| Category          | Channels                                                                  | Count |
| ----------------- | ------------------------------------------------------------------------- | ----- |
| Instant Messaging | Discord, Slack, Telegram, WhatsApp, Signal, Line, Matrix, Mattermost, IRC | 9     |
| China Ecosystem   | WeChat, WeCom, WeCom AIBot, DingTalk, Feishu, QQ, OneBot, WeChat Official | 8     |
| Developer         | GitHub (Webhook + PR Comment)                                             | 1     |
| Enterprise        | Microsoft Teams, Google Chat                                              | 2     |
| Voice             | Discord Voice (with DAVE E2E encryption)                                  | 1     |
| Other             | Email, SMS, iMessage, Webhook, Zalo                                       | 5     |

## iMessage 심층 통합

무료 오픈 소스 macOS 릴레이인 [BlueBubbles](https://bluebubbles.app/)를 통해 iMessage에 연결하세요. Myrm은 기본 iMessage 환경을 위해 전체 BlueBubbles Private API을 구현합니다.

| Feature                   | Description                                                                                         |
| ------------------------- | --------------------------------------------------------------------------------------------------- |
| Quoted Replies            | Agent responses reference the original message with a visible quote bubble                          |
| Read Receipts             | Incoming messages are marked as "Read" — users know the agent received their message                |
| Tapback Reactions         | Agent can react with native iMessage tapbacks (heart, thumbs up/down, laugh, exclamation, question) |
| Typing Indicator          | "Typing..." bubble appears while the agent processes (55s auto-refresh keepalive)                   |
| Webhook Auto-Registration | Configure once — webhook registers on start, unregisters on stop. No manual BlueBubbles setup       |
| Media Attachments         | Full support for images, videos, audio, documents, and contact cards (vCard)                        |
| Group Chat                | Supports group conversations with per-group context and sender identification                       |

### 설정

1. iMessage가 활성화된 macOS 컴퓨터에 [BlueBubbles](https://bluebubbles.app/)를 설치합니다.
2. GUI에서 **설정 > 채널 > iMessage**로 이동합니다.
3. BlueBubbles **API URL** 및 **비밀번호**를 입력하세요.
4. 선택적으로 **Webhook URL**을 제공합니다. 에이전트는 연결 시 이를 자동으로 등록합니다.
5. 인용된 답변, 읽음 확인 및 입력 표시에 대해 BlueBubbles에서 **비공개 API**를 활성화합니다.

### 우아한 저하

BlueBubbles Private API 또는 해당 도우미 프로세스를 사용할 수 없는 경우 이를 필요로 하는 모든 기능(입력 표시기, 읽음 확인, 인용된 응답)이 자동으로 건너뛰어집니다. 낭비되는 네트워크 요청도 없고 로그에 오류도 없습니다. 기본 메시징은 중단 없이 계속 작동합니다.

## 설정

플랫폼을 연결하려면 GUI에서 **설정 > 채널**로 이동하세요. 각 채널에는 연결 상태 표시기가 있는 자체 구성 패널이 있습니다.

API 자격 증명이 필요한 채널(DingTalk, Slack, Discord, WeCom 등)의 경우 **개발자 포털 링크**가 구성 양식 아래에 표시됩니다. 이를 클릭하면 봇/앱을 생성하고 자격 증명을 얻을 수 있는 플랫폼의 개발자 콘솔로 직접 이동할 수 있습니다. 12개 채널에는 직접 링크가 있습니다. 4개의 추가 채널에 텍스트 안내가 표시됩니다.

### 공용 Ingress 안내

일부 채널은 플랫폼이 **웹훅 콜백을 공용 URL로 푸시**하는 방식으로 메시지를 받습니다(LINE, Teams, WeChat Official, Zalo, SMS(Twilio), GitHub는 공개 주소가 필요합니다). 다른 채널은 **아웃바운드로 연결**되며 공개 주소가 필요 없습니다(Feishu WebSocket, Telegram 롱폴링, Email IMAP, IRC/Matrix).

Myrm은 **구성하기 전에** 어떤 채널이 공용 주소를 필요로 하는지 알려줍니다:

| 기능       | 제공되는 것                                                                                       |
| -------- | -------------------------------------------------------------------------------------------- |
| 자동 모드 감지 | **설정 > 채널** 페이지에 모든 내장 채널을 포괄하는 서버 측 전송 프로필을 기반으로 한 **인바운드/아웃바운드 배지**가 각 채널에 표시됩니다           |
| 설정 시 경고  | 공용 Ingress URL 없이 인바운드 채널을 구성하면 **WARNING**과 함께 설정 > 시스템 > 공용 Ingress로 이동하는 원클릭 수정 링크가 표시됩니다 |
| 터널 가이드   | 공인 IP가 없나요? [터널 가이드](/docs/guides/tunnel)를 따라 cpolar / NATAPP / frp로 로컬 에이전트를 노출하세요          |

이를 통해 "웹훅이 도착하지 않는" 디버깅 세션을 없앨 수 있습니다. 연결 전에 해당 채널이 공개 주소가 필요한지, 어디서 설정해야 하는지 정확히 알 수 있습니다.

> **정직한 경계**: Ingress 안내는 채널별 전송 분류일 뿐이며 실시간 연결 테스트가 아닙니다. 웹훅 전달은 여전히 터널/프록시가 플랫폼에서 접근 가능해야 합니다.

### WeChat(iLink를 통해)

QR 코드 로그인을 통해 1분 안에 개인 WeChat 계정을 연결하세요:

1. GUI에서 **설정 > 채널 > WeChat**으로 이동합니다.
2. **Scan to Connect**를 클릭하면 QR 코드 대화상자가 나타납니다.
3. 휴대폰에서 WeChat을 열고 QR 코드를 스캔하세요.
4. 휴대폰에서 확인하세요. 대화는 실시간으로 업데이트됩니다(SSE 스트리밍).
5. 완료 - WeChat이 연결되었습니다

로그인 흐름은 QR 생성 → 스캔 대기 → 확인 → 연결 등 실시간 상태 업데이트를 제공합니다. QR 코드가 만료되면 **재시도**를 클릭하여 새로운 QR 코드를 생성하세요.

**타이핑 표시기 신뢰성**: iLink 타이핑 티켓은 600초 후에 만료됩니다. 장기 실행 에이전트 작업(>10분)의 경우 시스템은 드리프트 안전을 위한 단조 시계를 사용하여 만료되기 전에(540초 임계값, 60초 안전 버퍼) 티켓을 사전에 새로 고칩니다. 이렇게 하면 에이전트가 완료되면 "입력 중..." 표시가 항상 사라지며 입력이 정지된 상태가 되지 않습니다.

### WeChat 공식 계정(초안 게시)

**구독/서비스 계정**(개인 WeChat 아님)의 경우 **AppID + AppSecret**을 구성하고 WebUI 확인 후 형식이 지정된 HTML을 **드래프트 상자**에 푸시합니다.

전체 가이드: [WeChat 공식 계정 게시](/docs/guides/wechat-official-publishing).

1. **설정 → 채널 → WeChat 공식** — AppID, AppSecret, IP 화이트리스트, 테스트 연결.
2. **wechat-article-formatter** → `.wechat.html` 아티팩트로 볼트 마크다운 형식을 지정합니다.
3. 채팅에서 미리보기 → **WeChat Draft로 푸시**(제목 + 표지, 첫 번째 인라인 이미지 자동 제안)
4. [mp.weixin.qq.com](https://mp.weixin.qq.com/) 초안 상자에서 수동으로 게시하세요.

<Note>
  Draft push is **HITL only** — no Agent draft tool (Prompt Cache–friendly, no accidental mass send).
</Note>

### WhatsApp(Baileys를 통해)

1. GUI에서 **설정 > 채널 > WhatsApp**으로 이동합니다.
2. **스캔하여 연결**을 클릭하세요. — WeChat과 동일한 QR 코드 대화 상자
3. 휴대폰에서 WhatsApp 열기 → **연결된 장치** → QR 코드 스캔
4. 자동으로 연결이 설정됩니다.

WeChat과 WhatsApp 모두 동일한 `AsyncLoginProtocol`, 즉 채널 전반에 걸쳐 일관된 UX를 사용합니다.

### 이메일(IMAP + SMTP)

1. **설정 > 채널 > 이메일**을 엽니다.
2. IMAP(받은 편지함) 및 SMTP(발신 편지함) 서버, 포트 및 자격 증명 구성
3. 저장 - 폴링이 자동으로 시작됩니다.

**스마트 전달 이메일 구문 분석**: 모든 이메일을 에이전트에 전달하면 자동으로 원본 이메일 내용에서 지침을 분리합니다.

* Gmail, Outlook, QQ Mail, 163 Mail, Foxmail 및 기타 주요 클라이언트 지원
* 3단계 감지: 제목 접두어(Fwd:/FW:/转发:/轉發:) → 본문 구분자 → MIME 첨부
* 전달할 때 "expense this" 또는 "translate to English"라고만 작성하세요. 상담원은 귀하의 지시사항과 전체 원본 이메일을 모두 본 다음 정확하게 실행합니다.
* 적응형 문자 집합 디코딩(gb2312/GBK/UTF-8)을 통한 전체 CJK 이메일 클라이언트 지원

**스마트 HTML 정리**: 이메일에 HTML(Amazon 주문, Jira 알림, Outlook 서식 있는 텍스트)만 포함된 경우 콘텐츠는 자동으로 정리 마크다운으로 변환됩니다. 즉, 콘텐츠 크기를 65\~74%(측정) 줄이면서 테이블, 링크 및 목록을 보존하므로 에이전트가 더 빠르고 정확하게 이해할 수 있습니다.

**다중 에이전트 이메일 라우팅**: 여러 에이전트가 구성된 경우 슬래시 명령으로 이메일 본문을 시작하여 특정 에이전트로 라우팅합니다.

* `/coder review this PR` → "코더" 에이전트로 라우팅
* `/accountant expense this` → 귀하의 "회계사" 대리인에게 전달됩니다.
* 명령 없음 → 기본 에이전트로 라우팅

### 텔레그램

텔레그램을 연결하는 두 가지 경로 — 상황에 맞는 것을 선택하세요:

**경로 A: 온보딩 마법사(처음 사용자에게 권장)**

초기 설정 마법사에서 모델 및 라우팅 기본 설정을 구성한 후 **Telegram Personal Assistant** 단계가 나타납니다.

1. **봇 토큰**을 붙여넣습니다([@BotFather](https://t.me/BotFather)에서 하나 가져옴).
2. 선택적으로 **Webhook URL**을 입력합니다(공용 도메인 뒤의 VPS/클라우드 배포에만 필요함)
3. 선택적으로 어시스턴트의 이름을 지정합니다(기본값은 `Myrm Assistant`).
4. **활성화**를 클릭합니다. 시스템이 토큰을 원자적으로 검증하고, 자격 증명을 작성하고, DM 정책을 "공개"로 설정하고, 기본 에이전트를 바인딩합니다.

단계가 실패하면 모든 변경 사항이 자동으로 롤백됩니다. 즉, 절반만 구성된 상태가 아닙니다. 또한 마법사는 동시 제출을 적절하게 처리합니다. 다른 요청이 이미 진행 중인 경우 자동으로 재시도하고 원시 오류 대신 친숙한 메시지를 표시합니다.

**경로 B: 설정 페이지(나중에 텔레그램 추가용)**

1. **설정 > 채널 > 텔레그램**으로 이동합니다.
2. **봇 토큰**과 선택적으로 **Webhook URL**을 입력하세요.
3. 저장 - 봇이 연결되어 메시지 수신을 시작합니다.

**Webhook 대 폴링**: 웹훅 URL이 없으면 봇은 긴 폴링을 사용합니다(로컬/데스크탑 설정에 적합). Webhook URL을 사용하여 Telegram은 업데이트를 서버에 푸시합니다(인터넷에서 봇에 접근할 수 있어야 하는 VPS/클라우드 배포에 필요).

**리치 메시지 렌더링**: Telegram은 Bot API 10.1을 통해 기본 리치 메시지를 지원합니다. — 테이블, LaTeX 수식 및 중첩 목록은 기본적으로 렌더링됩니다. 자세한 내용은 [텔레그램 리치 메시지](#telegram-rich-message-bot-api-101)를 참조하세요.

### SMS(Twilio)

1. **설정 > 채널 > SMS**를 엽니다.
2. Twilio **계정 SID**, **인증 토큰** 및 **전화번호**(E.164 형식, 예: `+15551234567`)를 입력합니다.
3. 자동 생성된 **Webhook URL**을 복사하여 Twilio 콘솔 > 전화번호 > 메시징 웹훅에 붙여넣습니다.
4. **연결 테스트**를 클릭하여 확인합니다.

* 양방향 : 모든 전화에서 SMS 수신 → 에이전트 프로세스 → SMS를 통해 응답
* 긴 메시지는 자연스러운 경계에서 자동으로 분할됩니다(세그먼트당 최대 1600자).
* Twilio 서명 확인은 합법적인 메시지만 처리되도록 보장합니다.

## 메시지 유형

모든 채널은 다음을 지원합니다.

* 플랫폼에 적합한 형식의 문자 메시지
* 이미지/문서/오디오/비디오 첨부 파일(`MediaType` 열거형)
* 자동 유형 감지 기능을 갖춘 파일 업로드

## 양방향 파일 전송

에이전트가 생성한 파일은 IM 채널에 자동으로 푸시되므로 수동으로 다운로드할 필요가 없습니다.

### 인바운드(사용자 → 상담원)

IM을 통해 에이전트에게 문서(PDF, Excel, Word 등)를 보내면 해당 내용이 자동으로 추출되어 LLM 컨텍스트에 삽입됩니다. 에이전트는 파일 읽기 도구를 호출할 필요 없이 파일을 즉시 이해합니다.

### 아웃바운드(상담원 → 사용자)

상담원이 파일(차트, 보고서, 스프레드시트, 컴파일된 문서)을 생성하면 자동으로 채팅에 미디어 첨부 파일로 전달됩니다. 지원되는 아티팩트 유형에는 코드 실행, 파일 쓰기 또는 문서 생성 도구를 통해 생성된 모든 파일이 포함됩니다.

| Feature          | Details                                                     |
| ---------------- | ----------------------------------------------------------- |
| Size limit       | 5 MB per file (larger files gracefully skipped)             |
| Failure handling | Automatic retry with media-strip fallback — text never lost |
| Supported types  | IMAGE, DOCUMENT, AUDIO, VIDEO (auto-detected from filename) |
| Multi-file       | All generated files delivered as separate attachments       |

### 아티팩트 딥 링크

대화형 아티팩트(HTML 페이지, PDF, 문서)의 경우 에이전트는 원시 파일을 보내는 대신 IM 메시지에 클릭 가능한 **딥 링크 버튼**을 자동으로 생성합니다. 버튼을 탭하면 사용자 브라우저에서 아티팩트가 직접 열립니다. 다운로드가 필요하지 않습니다.

| Feature            | Details                                                             |
| ------------------ | ------------------------------------------------------------------- |
| Trigger            | Automatically for shareable artifact types (HTML, PDF, Document)    |
| Security           | HMAC-signed, time-limited, read-only share tokens                   |
| Multiple artifacts | Each gets a named button (e.g. "💻 dashboard.html")                 |
| Redundancy removal | Raw file attachment is removed when a deep link is available        |
| Safe degradation   | Falls back to raw file if no public URL, DB error, or token failure |
| i18n               | Button labels localized (English / Chinese)                         |

## 채널 인식 출력 적응

Myrm은 **3중 레이어** 아키텍처를 사용하여 모든 플랫폼에서 출력이 깔끔하고 올바른 형식인지 확인합니다.

### 아웃바운드 소음 필터링

각 채널에는 사용자가 보는 콘텐츠를 제어하는 자체 `RenderStyle` 구성이 있습니다.

| Control                | Options                  | Default                                                     |
| ---------------------- | ------------------------ | ----------------------------------------------------------- |
| `reasoning_display`    | OFF / COLLAPSED / INLINE | OFF (WeChat, WeCom, WhatsApp) or COLLAPSED (Telegram)       |
| `tool_summary_display` | OFF / COMPACT / DETAILED | OFF (WeChat, WeCom, WhatsApp) or COMPACT (Feishu, DingTalk) |

기본적으로 IM 사용자는 **진행률 레이블, 최종 결과 및 결정 프롬프트**만 수신하며 도구 호출 매개변수, 추론 토큰 또는 사고 태그는 없습니다. `strip_thinking_tags()` 기능은 누출되는 모든 LLM 사고 블록을 제거하는 추가 안전망을 제공합니다.

진행률 라벨은 **입력 요약**으로 강화되므로 에이전트가 수행하는 작업을 정확하게 확인할 수 있습니다.

* `🔍 Searching: AI coding tools 2025` (단순히 "웹 검색 중..."이 아님)
* `📄 Reading: config/settings.yaml` (단지 "파일을 읽는 중..."이 아님)
* `⏳ **notion_query** — Search meeting notes`(사용자 정의 MCP 도구가 자동으로 적용됨)

모든 도구가 포함됩니다. 등록된 도구는 특정 작업을 표시하고, 등록되지 않은 도구(구성한 모든 MCP 서버 포함)는 입력 추출을 통해 일반적인 대체 기능을 가져옵니다. API 속도 제한을 피하기 위해 업데이트가 제한됩니다(최소 2초 간격).

### 사전 지침(channel\_output\_hints)

에이전트 초기화 시 채널별 형식 힌트가 시스템 프롬프트에 삽입됩니다. 이는 플랫폼이 콘텐츠를 생성하기 *전에* 플랫폼이 지원하는 것이 무엇인지 LLM에 알려줍니다.

* **텔레그램**: 테이블, LaTeX 및 중첩 목록은 Bot API 10.1 리치 메시지를 통해 기본적으로 렌더링됩니다. 힌트는 Rich를 사용할 수 없을 때만 활성화됩니다.
* **WhatsApp**: "마크다운은 렌더링되지 않습니다. 일반 텍스트만 사용하세요."
* **Discord**: "2000자가 넘는 메시지는 자동으로 분할됩니다."
* **음성**: "대화 중인 사람에게 말하듯이 말하세요."

28개의 채널 힌트가 사전 구성되어 있으며 KV 캐시에 안전합니다(초기화 시 한 번 주입됨).

### IM 행동 페르소나(자동 삽입)

제한된 IM 채널(메시지 편집 없음, 마크다운 지원 없음)의 경우 시스템은 자동으로 행동 전략을 주입합니다.

* **간결한 채팅 스타일**: 교과서가 아닌 채팅 대화 같은 답변
* **긴 콘텐츠 → 파일 + 요약**: 최대 200자를 초과하는 콘텐츠는 작업공간 파일에 기록됩니다. IM 답글에는 한 문장 요약 + 아티팩트 딥 링크만 포함됩니다.
* **집중적 설명**: 사용자 의도가 불분명할 때 최대 1\~2개의 주요 질문을 묻습니다.

자동 실행 채널: WeChat iLink, WeChat Official, Signal, iMessage, LINE, SMS, OneBot(QQ), IRC, Zalo, Voice(총 10개)

제로 구성 필요 — `ChannelCapabilities`에서 자동으로 감지됩니다. Markdown 또는 편집 지원 채널(Telegram, Discord, Slack 등)은 영향을 받지 않습니다.

### 사후 형식 다운그레이드(렌더러)

LLM이 힌트를 무시하더라도 렌더링 파이프라인은 형식 다운그레이드를 적용합니다.

* `supports_tables=false` → 글머리 기호 목록으로 변환된 마크다운 테이블
* `supports_latex=false` → 일반 텍스트로 제거된 LaTeX 수식
* IM 채널에서 HTML/SVG 코드 블록이 짧은 자리 표시자로 대체되었습니다.
* 출처가 없을 때 고아 인용 마커가 자동으로 정리됩니다.

### 메시지당 비용 표시

`enableCostEstimation`이 활성화되면(기본값: true) IM 채널의 각 에이전트 응답에는 사용된 모델, 토큰 수 및 예상 비용을 보여주는 비용 바닥글이 포함됩니다.\`\`\`
💰 claude-sonnet-4-20250514 | 2.5k tokens | \~\$0.0035

````

- **무료 답변은 숨겨집니다** — 캐시된 답변이나 자유 모델 답변에는 바닥글이 표시되지 않습니다.
- **Emoji 토글** — 데이터를 유지하면서 사용자 구성을 통해 `💰` 접두사를 비활성화합니다.
- **Feishu 카드** — 비용은 타임스탬프와 함께 기본 `note` 요소로 표시됩니다.
- **정밀도** — 정확한 추적을 위해 비용은 항상 소수점 이하 4자리로 표시됩니다.

이는 추가 구성 없이 자동으로 작동합니다. 비용 데이터는 스트리밍 중에 하네스 `token_usage` 이벤트에서 추출됩니다.

### 스마트 메시지 분할

긴 메시지는 자연스러운 경계에서 자동으로 분할됩니다.

- 코드 펜스 상태 머신은 코드 블록이 청크 전체에서 적절하게 닫히고 다시 열리도록 보장합니다.
- 공백 및 구두점 경계에서 지능적인 줄 분할
- 의미 보존을 위해 구성 가능한 오버플로 허용 오차
- 채널당 길이 제한(예: Discord 2000자, Telegram 4096 HTML / 32000 Rich Message)

### 텔레그램 리치 메시지(봇 API 10.1)

텔레그램 채널은 3계층 대체를 통해 기본 리치 메시지 렌더링을 지원합니다.

1. **리치 메시지** — 테이블, LaTeX 수식 및 중첩 목록이 기본적으로 렌더링됩니다(32KB 제한).
2. **HTML** — ASCII 고정폭 테이블 저하로 자동 변환됨(4096 UTF-16 제한)
3. **일반 텍스트** — HTML 구문 분석이 실패할 경우 최후의 수단

스트리밍은 초기 토큰 깜박임을 억제하기 위해 최소 임계값이 20자인 **깜박임 없는 초안 미리 보기**(`sendRichMessageDraft` → `sendMessageDraft` → `editMessageText`)를 사용합니다. CJK 콘텐츠는 완전한 Rich 형식을 수신하며 성능 저하나 해결 방법이 없습니다.

## 그룹 채팅 기능

### 허용정책

에이전트가 그룹 채팅에서 응답하는 시기를 제어하는 세 가지 미리 설정된 정책은 다음과 같습니다.

| Policy | DM | Group |
|--------|-----|-------|
| OPEN | Allow all | Allow all (no mention needed) |
| SELECTIVE | Allow all | Mention required |
| STRICT | Mention required | Mention required |

### 그룹 트리거 모드

그룹 채팅에서 상담원이 활성화되는 시점을 세밀하게 제어할 수 있습니다.

| Mode | Behavior |
|------|----------|
| ALL | Every message in the group triggers the agent |
| MENTION_ONLY | Only responds when @mentioned |
| PREFIX | Responds when message starts with a configured prefix (prefix is auto-stripped) |

### 주제 바인딩

3계층 세분성은 다양한 에이전트를 다양한 대화 범위에 바인딩합니다.

- **스레드 수준**: 특정 주제/스레드에 바인딩됨
- **채팅 수준**: 특정 그룹/대화에 연결됨
- **채널 수준**: 전체 채널에 바인딩됨

조회 순서는 스레드→채팅→채널이며 기본 에이전트로 안전하게 대체됩니다.

### 주제 작업공간 바인딩(Vault/프로젝트)

원격 메시지가 빈 JIT 샌드박스에 들어가지 않도록 각 IM 주제를 실제 작업 공간에 바인딩합니다.

| Method | How |
|--------|-----|
| **GUI** | **Settings → Channel Routing** → per-topic **Project** dropdown |
| **IM** | `/bind workspace=project:<uuid>` or `/bind workspace=/path/to/vault` |
| **Combined** | `/bind agent=my-agent workspace=project:<uuid>` |

각 에이전트가 실행되기 전에 시스템은 WebUI 세션과 동일한 `resolve_effective_chat_workspace` 체인을 사용하여 주제 바인딩을 채팅 SSOT(`project_id` 또는 `workspace_dir`)에 동기화합니다. 바인딩을 해제하면 채팅의 두 필드가 모두 지워집니다. 프로젝트 또는 경로를 사용할 수 없는 경우 빈 샌드박스를 자동으로 사용하는 대신 큰 소리로 실행이 실패합니다.

**정직한 한계:** IM `/status`에는 여전히 `project:uuid`(친숙한 이름이 아님)가 표시됩니다. GUI 경로 선택기가 없습니다. — GUI 사용자가 프로젝트를 바인딩합니다. 경로 바인딩은 IM 우선입니다.

**테스트 범위:** 9개 서버 pytest 사례(동기화, topic_config 유효성 검사, 바인딩 해제 지우기, Effective_workspace 체인). 프런트엔드 라벨 도우미: 3 vitest 사례.

**대 OpenClaw:** OpenClaw은 에이전트 구성 수준에서 `workspaceDir`을 바인딩합니다(에이전트당 하나의 작업 영역). Myrm은 주제 세분화로 바인딩되므로 동일한 에이전트가 서로 다른 저장소를 가리키는 서로 다른 전보 스레드를 제공할 수 있습니다.

### 흑요석 금고 쓰기 충실도

주제가 Obsidian 볼트에 바인딩되면 에이전트 편집 내용이 **실제 볼트 파일**(사본 아님)로 이동됩니다. Myrm은 두 가지 코드 수준 보호 장치를 추가합니다.

1. **머리말 보존** — 본문을 편집하는 동안 LLM이 `---` YAML 블록을 삭제하는 경우 쓰기 가드는 저장하기 전에 사전 편집된 머리말을 다시 삽입합니다(`date:`, `tags:`, Dataview 필드는 그대로 유지됩니다).
2. **볼트 노트가 더 예뻐지지 않습니다** — FormatObserver는 `.obsidian/` 볼트 루트 아래의 `.md` 파일을 건너뛰므로 자동 서식 지정이 메타데이터를 제거할 수 없습니다.

**정직한 제한:** 블록 수준 재주입만 가능합니다(필드별 병합 아님). Wikilink 무결성은 `obsidian-notes` 기술에 의존합니다. 아직 볼트 전체 백링크 검사는 없습니다.

**테스트:** 44 pytest 사례(2026년 7월): 하네스 가드 + 서버 파서 + 서비스 통합 + 형식 관찰자.

### 스레드 후속 조치

상담원이 스레드에서 응답한 후 해당 스레드에 대해 **GroupFollowUpTracker**가 활성화됩니다(TTL: 10분). 이 기간 동안 동일한 스레드의 후속 메시지에는 @멘션이 필요하지 않습니다. 즉, 사람이 하는 것처럼 에이전트가 자동으로 대화를 계속합니다.

후속 작업을 중지하려면 스레드에서 `/mute`, `/shutup`, `闭嘴` 또는 `别吵`를 보내세요. 에이전트가 즉시 응답을 중지합니다. 재활성화하려면 상담원을 다시 @mention하면 됩니다.

### 게스트 멘션

에이전트에 대해 명시적으로 활성화되지 않은 그룹에서도 사용자는 일회성 응답을 위해 에이전트를 @멘션할 수 있습니다(게스트 모드가 활성화된 경우). 이를 통해 화이트리스트에 그룹을 추가하지 않고도 임시 AI 지원이 가능합니다.

### 정확한 봇 ID 매칭

모든 채널 공급자는 정확한 봇 신원 일치를 수행합니다. Telegram은 `bot_username`을 확인하고, Feishu는 `bot_open_id`을 확인하고, Teams는 `app_id`을 확인하고, WhatsApp은 `mentionedJids`을 확인합니다. 즉, @멘션은 35개 이상의 모든 채널에서 잘못된 트리거 없이 항상 올바른 봇으로 정확하게 라우팅됩니다.

### GroupContextBuffer

그룹 채팅의 트리거되지 않은 메시지는 그룹별 링 버퍼에 누적됩니다. 트리거 메시지(예: @agent)가 도착하면 버퍼가 비워지고 컨텍스트로 주입되어 에이전트가 그룹 토론에 대한 대화 인식을 제공합니다.

### 세션게이트

동일한 대화의 신속한 메시지는 반송 처리되고(기본 300ms 기간) 단일 요청으로 병합되어 중복 처리가 방지됩니다.

## 결정적 사전 LLM 처리

모든 인바운드 메시지는 모델에 도달하기 전에 LLM 비용이 전혀 들지 않는 5개 계층 처리를 거칩니다. 이는 일반적인 작업이 토큰을 소비하지 않고 밀리초 내에 응답함을 의미합니다.

| Layer | What it does | Latency |
|-------|-------------|---------|
| **Message Dedup** | TTL-based deduplication (`channel:message_id`) prevents Webhook retries from triggering duplicate processing | <0.1ms |
| **Slash Commands** | 21 system commands + dynamic Skill bindings + Agent routing — O(1) registry lookup | <0.1ms |
| **Risk Detection** | Compiled regex engine blocks or warns on sensitive content; ReDoS-safe with audit trail | <1ms |
| **FAQ Semantic Cache** | Embedding similarity + score/gap dual verification — cache hits return template answers instantly (40–100× faster than LLM) | 5–20ms |
| **Policy + Session Gate** | DM/Group policy enforcement, message debouncing (300ms), merge, and concurrency control | <1ms |

### 이것이 사용자에게 의미하는 것

- **일반적인 질문에 즉시 답변** — FAQ 조회는 LLM을 완전히 건너뛰어 시간과 비용을 모두 절약합니다.
- **민감한 콘텐츠는 자동으로 차단됨** — 수동 조정 없이 규정 준수 가능
- **대기 시간이 없는 빠른 명령** — `/stop`, `/new`, `/status`은 즉시 실행됩니다.
- **신속한 메시지는 적절하게 처리됨** — 버스트 메시지는 중복 처리되지 않고 병합됩니다.
- **토큰 낭비 없음** — AI 추론이 정말로 필요한 메시지만 모델에 도달합니다.

## 에이전트가 시작한 알림

에이전트는 구성된 채널에 사전에 알림을 푸시할 수 있으므로 수동 폴링이 필요하지 않습니다.

### 작동 방식

1. **에이전트 설정 → 알림 채널**에서 **현재 실행 중인** 통합(사람이 읽을 수 있는 이름이 포함된 동적 목록 - 새 채널은 프런트엔드 릴리스 없이 나타남)에서 채널을 선택한 다음, 페어링된 연락처에서 수신자를 선택합니다(또는 수동으로 ID를 입력합니다).
2. 에이전트는 경고가 필요할 때 `channel_notify_tool`을 호출합니다(작업 완료, 이상 탐지, 예약된 보고서 준비).
3. 선택적으로 파일 또는 이미지 첨부 - 올바른 미디어 유형 감지를 통해 로컬 경로 및 URL이 자동으로 확인됩니다.
4. 전달은 동시 성공/실패 결과(중요 채널 메시지와 동일한 재시도 정책)를 위해 `send_tracked`를 사용하며, 실행 후 잊어버리는 대기열 삭제가 아닙니다.

> **알림 전달 대비**: **에이전트 설정 → 알림 채널**은 `channel_notify_tool`만 허용 목록에 추가합니다. **설정 → 알림 전달**은 **시스템 이벤트**(OAuth, 예산, 페어링, 채널 상태)를 라우팅합니다. 그것들은 서로 바꿔 사용할 수 없습니다.

### 보안

| Layer | Protection |
|-------|-----------|
| Whitelist | Only user-configured targets are reachable — no arbitrary recipients |
| Rate limit | Per-session cap prevents notification spam (default: 10 per session) |
| Content cap | Messages exceeding `max_body_length` (4000 chars) are automatically truncated |
| Attachments | Local paths must stay within the agent workspace (`declared_allowed_roots`); URL filenames parsed safely (handles query params) |
| Audit trail | Every notification target used is recorded in session state |
| Sub-agent isolation | Sub-agents cannot call `channel_notify_tool` by default (harness L1 blocklist) |
| Failure visibility | Sync delivery failures enter DLQ and trigger a WebUI toast (presync dedupe; not persisted across restarts) |
| Layer | Server `outbound_notify/` (business layer, not harness kernel), co-located with ChannelGateway |

> **테스트 적용 범위(2026-07-07)**: **127 pytest + 1 라이브 에이전트 스트림 E2E(MiniMax-M2.7, RUN_E2E_TESTS=1) + 7 vitest + Chrome 전체 사용자 흐름 round42(소스 채팅 도구 단계 + 수신자 받은 편지함 UI)** 통과 — ChatChannel 인앱 받은 편지함 전달, DLQ/토스트 체인, 하위 에이전트 격리, 첨부 경로 샌드박스, 동적 실행 채널 선택기가 확인되었습니다.

### 예시 시나리오

- 예정된 작업은 오전 3시에 완료됩니다. → 상담원이 요약 + 보고서 PDF를 텔레그램으로 보냅니다.
- 장기 실행 코드 분석 완료 → 결과 + 생성된 차트가 Slack 채널로 푸시됨
- 모니터링 데이터에서 이상 징후 감지 → 구성된 대상에 대시보드 스크린샷을 전송하여 알림

## 웹 푸시(오프라인 알림)

브라우저를 닫은 후에도 중요한 알림을 받습니다. 기본 앱이 필요하지 않습니다.

PWA가 닫히거나 백그라운드 상태가 되면 서버는 W3C 웹 푸시 표준(VAPID)을 통해 푸시 알림을 보냅니다. 여기에는 IM 채널이 구성되지 않았거나 사용자가 단순히 브라우저 기본 알림을 원하는 시나리오가 포함됩니다.

### 지원되는 이벤트

| Event | Example |
|-------|---------|
| Approval request | Agent needs permission to execute a sensitive operation |
| Goal completed | Background task finished successfully |
| Goal failed | Task encountered an unrecoverable error |
| Goal verification | Results ready for your review |
| Health alert | System detected a service disruption |
| Budget alert | Usage approaching configured limits |
| Background task done | Long-running task completed |
| System notification | Security events, pairing requests, OAuth callbacks |

### 설정

1. **설정 > 시스템 > 푸시 알림**으로 이동합니다.
2. **활성화** 전환 - 브라우저에서 알림 권한을 요청합니다.
3. 완료되었습니다. 브라우저 탭을 닫아도 알림이 도착합니다.

**테스트** 버튼을 사용하면 배송을 즉시 확인할 수 있습니다.

### 플랫폼 노트

| Platform | Support |
|----------|---------|
| Desktop browsers (Chrome, Firefox, Edge) | ✅ Full support |
| Android (Chrome, Firefox) | ✅ Full support |
| iOS / iPadOS (Safari 16.4+) | ✅ Requires "Add to Home Screen" (PWA mode) |
| Tauri desktop app | N/A — uses native OS notifications instead |

iOS에서 카드는 앱이 독립형 PWA 모드에서 실행되고 있는지 자동으로 감지하고 필요한 경우 설치 가이드를 표시합니다.

### 보안 및 유지 관리

- **VAPID 키 자동 생성** — 서버는 처음 부팅할 때 키를 생성하고 유지하며 구성은 필요하지 않습니다.
- **만료된 구독 정리** — 푸시 실패(410/404)가 발생하면 오래된 구독이 자동으로 제거됩니다.
- **타사 서비스 없음** — 푸시는 브라우저 공급업체 엔드포인트(Google FCM, Apple APN, Mozilla 자동 푸시)로 직접 이동됩니다.
- **Tauri-인식** — 기본 알림이 이미 작동하는 데스크톱 앱 빌드에서는 설정 카드가 숨겨집니다.

### 원클릭 승인 딥링크

푸시 알림을 탭하면 홈페이지뿐 아니라 정확한 채팅과 **승인 서랍**이 열립니다.

- **승인 요청**은 `/{chat_id}?approval={id}`으로 이동합니다. WebUI는 전역 ApprovalDrawer를 열고 깨끗한 URL에 대한 쿼리 매개변수를 제거합니다.
- **서비스 워커 라우팅**은 동일한 출처 경로를 삭제하고 채팅 탭이 이미 열려 있으면 포커스 전용 대신 `navigate()`을 호출합니다. 따라서 열려 있는 탭에 대한 새 승인은 여전히 서랍을 엽니다(OpenClaw의 SW는 경로 이름만 비교하고 이를 놓칩니다).
- **Chrome MCP E2E 검증** — 핫 탭 + 콜드 스타트 딥링크 경로(2026-07)

## 백그라운드 작업 자동 응답

IM 채널에서 `/btw`를 통해 백그라운드 작업을 시작하면 작업이 완료되면 결과가 자동으로 원래 대화로 다시 푸시됩니다.

- **스레드 정확도 전달** — 작업을 시작한 정확한 스레드에 응답이 도착합니다.
- **현지화된 알림** — 메시지는 사용자의 언어 기본 설정(영어, 중국어 등)을 존중합니다.
- **실패 경고** — 작업이 실패하면 무음 대신 오류 요약이 표시됩니다.
- **신뢰할 수 있는 전달** — 모든 채널 메시지와 동일한 재시도 인프라를 사용합니다.
- **무중단** — 알림 설정과 독립적으로 실행됩니다. 방송이 아닌 직접 답변입니다

Discord에서 작업을 시작하고 다른 것으로 전환한 후 다시 돌아와서 스레드에서 대기 중인 결과를 찾아보세요.

## 목표 달성 자동 응답

IM 채널에서 `/goal set`을 통해 목표를 시작하면 목표가 완료되면 완료 결과가 원래 대화로 자동으로 푸시됩니다.

- **스레드 정확도 전달** — 목표를 시작한 정확한 스레드에 응답합니다.
- **현지화된 알림** — 메시지는 목표를 만들 때 사용한 언어(영어, 중국어, 일본어, 중국어 번체)를 따릅니다.
- **딥링크 버튼** — "브라우저에서 계속"을 선택하면 WebUI의 실행 요약과 함께 전체 목표 세부정보가 열립니다.
- **성공 및 실패 범위** — 완료된 목표와 실패한 목표 모두 알림을 트리거합니다.
- **일관된 인프라** — `/btw` 백그라운드 작업 알림과 동일한 전달 파이프라인을 사용합니다.

Telegram에서 목표를 시작하고 앱을 닫은 후 몇 시간 후에 다시 돌아와 구조화된 결과를 찾으세요. 원클릭 버튼을 사용하면 브라우저에서 전체 세부정보를 볼 수 있습니다.

## 장기 작업 하트비트(제자리에서 편집)

에이전트가 출력을 보내지 않고 오랜 기간 동안 복잡한 작업을 수행하는 경우 자동으로 실시간 하트비트 메시지를 제공하므로 채팅에 여러 알림이 넘치지 않고 중단되지 않았음을 알 수 있습니다.

### 작동 방식

1. 병렬 배경 모니터는 마지막 활동(전송된 메시지, 진행률 업데이트 등) 이후의 시간을 추적합니다.
2. 2분간의 침묵 후 발신 IM 채널로 하트비트 메시지가 전송됩니다.
3. 후속 하트비트에서는 경과 시간, 걸음 수 및 단계가 업데이트되어 **동일한 메시지가 그 자리에서 편집**됩니다. 새 메시지는 생성되지 않습니다.
4. 채널이 메시지 편집을 지원하지 않는 경우 단일 메시지만 전송됩니다(스팸 없음).
5. 작업당 최대 3개의 하트비트 주기
6. NORMAL 우선순위를 사용합니다. 휴대폰에서 푸시 알림을 실행하지 않고 하트비트가 자동으로 도착합니다.

### 예시 메시지

> ⏳ 작업 — 3분(12단계, 데이터 분석)

작업이 진행됨에 따라 메시지가 업데이트됩니다.

> ⏳ 작업 — 5분(18단계, 코드 생성)

### 스마트 무음 감지

단순 간격 타이머와 달리 모니터는 **에이전트가 출력을 생성할 때마다 재설정**됩니다. 에이전트가 1분에 진행률 업데이트를 보내는 경우 해당 시점부터 2분 무음 기간이 다시 시작됩니다. 이렇게 하면 상담원이 적극적으로 통신할 때 불필요한 미리 알림을 피할 수 있습니다.

### 채널 인식 적응

하트비트는 채널이 메시지 편집(`ChannelCapabilities.edit`)을 지원하는지 여부를 자동으로 감지합니다. Telegram 및 Discord와 같은 채널은 바로 편집을 지원합니다. 단일 하트비트 메시지를 받지 않는 채널은 스팸을 방지하기 위한 추가 업데이트가 없습니다.

편집 작업이 실패하는 경우(예: 메시지가 너무 오래되어 편집할 수 없음) 시스템은 정상적으로 새 메시지 전송으로 돌아갑니다.

### 세부정보

| Aspect | Behavior |
|--------|----------|
| Silence threshold | 120 seconds (configurable via `_SILENCE_REASSURANCE_THRESHOLD`) |
| Max heartbeats | 3 per task (configurable via `_MAX_REASSURANCE_COUNT`) |
| Update mode | Edit-in-place (falls back to single send for channels without edit support) |
| Priority | NORMAL — silent delivery, no push notification |
| Language | Fully internationalized (English, Simplified Chinese, Traditional Chinese, Japanese — extensible via `.ftl` files) |
| Typing indicator | Runs in parallel — "Typing..." keeps showing during the silence window |
| Prompt cache | Zero impact — heartbeat is outbound-only, never modifies the system prompt |
| Error handling | Send/edit failures are logged silently; the main task is never interrupted |

## 채팅 내 상담원 전환

IM 채널 내에서 직접 구성된 에이전트 간에 전환하세요. 웹 UI를 열거나 구성 파일을 편집할 필요가 없습니다.

### 텔레그램(`/agent` 명령)

1. 채팅에서 `/agent`을 보내세요.
2. 사용 가능한 모든 에이전트를 나열하는 InlineKeyboard가 나타납니다. 현재 바인딩된 에이전트에는 확인 표시 표시기가 표시됩니다.
3. 원하는 에이전트를 탭하세요. 선택기 메시지가 확인 텍스트("Switched to: AgentName")로 대체됩니다.
4. 이 항목의 모든 후속 메시지는 새 에이전트(독립 시스템 프롬프트, 모델, 도구, 메모리)로 이동합니다.

### 빠른 전환 명령

구성 등록 바로 가기 명령(예: `/claude`, `/gpt`)에서 `command_bindings`을 정의하는 에이전트.

**이중 모드 라우팅:**

- `/cc fix this bug` — **원샷 라우팅**: 이 메시지는 Claude 에이전트에 의해 처리되지만 바인딩은 변경되지 않습니다. (다음 메시지는 이전 에이전트로 전달됩니다.)
- `/cc`(인수 없음) — **영구 바인딩**: 모든 후속 메시지에 대해 기본 에이전트를 Claude로 전환합니다.

이 디자인은 일시적으로 다른 에이전트가 필요할 때 앞뒤로 전환하는 데 따른 마찰을 제거합니다.

### 주제 바인딩 세분성

에이전트 바인딩은 **3계층 해결** 계층 구조를 따릅니다.

| Level | Scope | Example |
|-------|-------|---------|
| Thread | A single reply thread within a group | Different threads bound to different agents |
| Chat | A DM conversation or entire group | Default for most use cases |
| Channel | All conversations from one channel source | Fallback when no thread/chat binding exists |

### i18n 지원

모든 선택기 및 확인 메시지는 완전히 국제화되었습니다. 에이전트는 사용자의 언어 기본 설정을 자동으로 해결합니다(현재 영어 및 중국어, `.ftl` 번역 파일을 통해 확장 가능).

## 교차 장치 작업 동기화

모든 백그라운드 작업은 서버 측에 저장되며 데스크톱 앱, 웹 UI 또는 모바일 브라우저 등 연결된 클라이언트에서 액세스할 수 있습니다.

- **단일 정보 소스** — 작업 상태는 단일 장치가 아닌 서버의 Kanban 시스템에 있습니다.
- **어디서나 실시간 업데이트** — SSE 이벤트는 상태 변경(완료, 실패, 진행)을 연결된 모든 클라이언트에 동시에 푸시합니다.
- **일관된 UI** — 데스크톱(Tauri)에는 동일한 웹 UI 프런트엔드가 포함되어 있어 여러 표면에서 경험이 동일합니다.
- **IM 채널 통합** — BtwTaskNotifier는 UI 업데이트와 동시에 IM 채널에 결과를 푸시합니다.
- **IM Kanban 관리** — Telegram, Discord, Slack 등에서 직접 `/kanban`(또는 `/kb`)을 사용하여 채팅을 종료하지 않고도 작업을 생성, 나열, 편집, 완료, 차단 및 보관할 수 있습니다. LLM 비용 없음 - 명령이 에이전트 파이프라인을 완전히 우회합니다.

데스크탑에서 작업을 시작하고, 휴대폰에서 진행 상황을 확인하고, Telegram에서 `/kanban`을 통해 작업을 관리하고, Slack에서 완료 알림을 받으세요. 이 모든 것이 아무런 구성 없이 이루어집니다.

## 크로스 플랫폼 핸드오프

맥락을 잃지 않고 한 플랫폼에서 다른 플랫폼으로 대화를 전환하세요.

**두 가지 진입점:**
- **웹 UI** — 사이드바에서 대화를 마우스 오른쪽 버튼으로 클릭 → "전송 대상..." → 대화 상자에서 아이콘 및 상태 표시기를 사용하여 연결된 모든 채널을 자동 검색 → 한 번의 클릭으로 선택 및 전송
- **IM 명령** — IM 채널(Telegram, Discord, Slack 등)에 `/handoff <target_channel>`를 입력하세요.

**작동 방식:** 핸드오프는 단일 원자 DB 업데이트에서 세션 키를 대상 채널에 다시 바인딩합니다. — 밀리초의 대기 시간, 제로 데이터 복사, 전체 프롬프트 캐시 보존. 대상 키가 이미 다른 세션에서 사용되고 있는 경우 충돌을 피하기 위해 자동으로 바인딩이 해제됩니다.

**세션 정책:** `persistent`(재설정 안 함), `daily`(구성된 시간에 재설정) 또는 `idle`(비활성 후 재설정)의 세 가지 모드는 전송 후 세션 작동 방식을 제어합니다. 에이전트 신원(`agent_id`)은 전송 전반에 걸쳐 보존되므로 동일한 에이전트 성격, 도구 및 메모리가 새 채널에서 계속됩니다.

**테스트 적용 범위:** 17개의 단위 테스트 + 7개의 API 통합 테스트 = 모든 엣지 케이스(충돌 해결, 동일 채널 거부, 비활성 페어링, 에이전트 보존, 정책 모드)를 다루는 24개의 테스트입니다.

### 자동 "브라우저에서 계속" 버튼

에이전트의 모든 IM 응답에는 하단에 **"브라우저에서 계속"** 버튼이 포함되어 있습니다. 이를 탭하면 도구 호출 단계, 코드 차이점 및 파일 기록이 포함된 전체 웹 UI 대화 페이지가 한 번의 클릭으로 열립니다.

- **정확한 라우팅** — 버튼은 데이터베이스 Chat UUID(IM 플랫폼의 피어 ID 아님)를 사용하여 `/{chatUUID}`에 연결되므로 항상 올바른 대화가 열립니다.
- **백그라운드 작업 알림** — `/btw` 백그라운드 작업이 완료되면 IM 알림에도 버튼이 포함됩니다.
- **우아한 성능 저하** — 대화형 버튼을 지원하지 않는 채널(예: WeChat)은 자동으로 텍스트 링크로 대체됩니다. 공개 URL을 사용할 수 없는 경우 응답을 차단하지 않고 버튼이 자동으로 생략됩니다.
- **WebUI 필터링** — 이미 웹 UI에 있는 메시지에는 버튼이 표시되지 않습니다(중복 자체 링크 없음).

**테스트 범위:** URL 구성, DB UUID 확인, 채널 필터링, 오류 처리 및 정상적인 성능 저하를 다루는 22개 테스트(11개 단위 + 8개 통합 + 3회귀).

## 세션 연속성 및 컨텍스트 보존

IM을 통한 원격 제어는 상황을 결코 잃지 않습니다. 4개의 레이어가 원활한 연속성을 보장합니다.

| Layer | What it does |
|-------|-------------|
| **Session Strategy** | Choose Persistent (never reset), Daily (fresh each morning), or Idle (reset after N minutes of inactivity) |
| **Auto-Reset Notification** | When a session resets, the agent is told "this is a fresh conversation" and the user sees a notice — no hallucinated references to prior context |
| **History Backfill** | On cold start, the last 15 messages from the channel are automatically replayed into the session so the agent has immediate context |
| **Shared Context** | Cross-agent and cross-channel memory sharing — work started on desktop continues seamlessly when you switch to mobile IM |

전송 중에 작업 공간 컨텍스트를 잃는 메시지 전달 아키텍처(예: Coze → Claude Code)와 달리 Myrm의 에이전트는 작업 공간에서 직접 실행됩니다. 전체 파일 시스템 액세스 권한이 있고, 린터를 실행하고, git 상태를 확인하고, 프로젝트 트리를 탐색할 수 있습니다. IDE 상태 동기화 레이어가 필요하지 않습니다.

## IM에서 실행 취소, 재시도 및 파일 되돌리기

IM 채널에서 `/undo` 또는 `/retry`을 보내 에이전트의 마지막 차례를 롤백하세요(**자동 파일 복원 포함**).

| Command | What happens |
|---------|-------------|
| `/undo` | Deletes the last user + assistant message pair **and** reverts any files the agent modified during that turn |
| `/retry` | Deletes the last assistant reply, reverts its file changes, **then** re-sends your original question for a fresh answer |

**작동 방식:** 에이전트가 메시지를 처리할 때 에이전트의 SnapshotStore에서 데이터베이스까지 일관된 `message_id`이 추적됩니다. `/undo`에서 시스템은 삭제된 메시지 ID를 검색하고 해당 파일 스냅샷을 조회한 후 복원합니다. 사용자에게 현지화된 확인 메시지가 표시됩니다(예: "↩ 실행 취소: 2개의 메시지가 제거되었습니다. ↩ 3개의 파일을 되돌렸습니다.").

**중요한 이유:** 경쟁업체(OpenClaw, Hermes, DeerFlow)는 데스크톱 GUI 또는 CLI에서만 파일 되돌리기를 지원합니다. 다른 제품은 IM 채널 내의 실행 취소/재시도 명령에 연결된 파일 되돌리기를 제공하지 않습니다. 즉, 에이전트가 휴대폰에서 파일을 안전하게 편집하도록 할 수 있습니다. 문제가 발생하면 `/undo` 명령 하나로 모든 것이 해결됩니다.

## 채널 자가 치유 및 안정성

모든 채널은 상태를 지속적으로 모니터링하고 장애로부터 자동으로 복구하는 **ChannelGateway**에서 실행되며 사람의 개입이 필요하지 않습니다.

### 건강 루프

게이트웨이는 정기적인 상태 확인 주기(60초 간격)를 실행합니다. 채널이 두 번 연속 검사에 실패하면 **DEGRADED** 상태가 되고 자가 복구 파이프라인이 트리거됩니다.

1. **지수 백오프** — 재시작 지연 시간이 5초에서 최대 300초로 증가하여 리소스 스래싱을 방지합니다.
2. **지터** — 25% 무작위 변형으로 여러 채널에 동시에 장애가 발생하는 경우 천둥소리가 나는 것을 방지합니다.
3. **전체 재시작** — `stop()`(모든 핸들 해제)을 실행한 다음 `start()`(새 초기화)를 실행합니다.
4. **상태 브로드캐스트** — EventEmitter를 통해 실시간으로 프런트엔드 `ConnectionBadge` 업데이트

### 메시지 복구(InboundJournal)

충돌 기간 동안 수신된 메시지는 **손실되지 않습니다**. `InboundJournal`은 처리되기 전에 들어오는 메시지를 유지합니다. 다시 시작하면 처리되지 않은 항목이 라우팅 파이프라인을 통해 자동으로 재생되므로 사용자는 충돌이 발생한 것을 전혀 알 수 없습니다.

### 배달 못한 편지 대기열

여러 번 재시도한 후 전달에 실패한 메시지는 전체 메타데이터가 포함된 DLQ로 이동됩니다. 검사, 재시도 또는 보관이 가능하며 자동으로 사라지는 것은 없습니다.

### 일반 재연결 루프

WebSocket 기반 채널(Discord, Slack, Feishu 등)은 지수 백오프 및 지터가 있는 공통 `reconnect_loop` 유틸리티를 공유합니다. 이는 모든 장기 연결에서 일관되고 검증된 재연결 동작을 제공합니다.

### 플랫폼별 속도 제한

각 채널에는 플랫폼의 API 제한에 맞게 조정된 자체 **TokenBucket** 속도 제한기가 있습니다. WeChat 채널에는 전용 매개변수가 있습니다.

| Channel | Rate | Effect |
|---------|------|--------|
| WeChat (iLink) | 2 msg/s | Prevents personal account throttling |
| WeChat Official | 1 msg/s | Respects Official Account API quotas |

플랫폼이 속도 제한 오류(예: WeChat errcode 45011/45015/45047 또는 iLink errcode -2)를 반환하면 시스템은 다음을 수행합니다.

1. 플랫폼별 `retry_after` 지연을 사용하여 오류를 `RateLimitError`에 매핑합니다.
2. `retry_after` 값을 고려하여 지수 백오프로 재시도
3. 모든 재시도가 소진되면 DLQ로 폴백합니다. 문자 메시지는 자동으로 삭제되지 않습니다.

### 회로 차단기 및 우아한 성능 저하

채널의 아웃바운드 API에 반복적인 오류가 발생하면 두 개의 보완적인 보호 계층이 활성화됩니다.

**채널 수준 회로 차단기** — 5회 연속 전송 실패 후 회로가 트립되고 30초 동안 아웃바운드 디스패치를 일시 중지합니다. 메시지는 PriorityQueue(최대 256개)에 안전하게 대기하고 회로가 닫히면 전달됩니다. 이는 성능이 저하된 플랫폼 API의 범람을 방지합니다.

**스트리밍 단계적 성능 저하** — 라이브 스트리밍 업데이트(예: 실시간 메시지 편집) 중에 오류가 발생하면 강제 중지 대신 5단계 점진적인 속도 저하가 발생합니다.

| Level | Multiplier | Effect |
|-------|-----------|--------|
| NORMAL | 1× | Standard update frequency |
| DEGRADED_1 | 2× | Slightly slower updates |
| DEGRADED_2 | 4× | Noticeable delay, still responsive |
| DEGRADED_3 | 8× | Significant delay |
| DEGRADED_4 | 16× | Maximum slowdown, updates still delivered |

핵심 원칙: **사용자는 항상 업데이트를 받습니다** — 성능 저하 중에는 느리게 도착할 수 있지만 완전히 멈추지는 않습니다. 이는 피드백이 전혀 없는 갑작스러운 30초 정전 기간을 생성하는 기존 회로 차단기보다 우수합니다.

### 이것이 사용자에게 미치는 영향

- **다운타임 제로 경험** — 일시적인 네트워크 문제 또는 플랫폼 중단이 스스로 해결됩니다.
- **메시지 손실 없음** — 서버가 충돌하더라도 재시작 시 대기 중인 메시지가 복구됩니다.
- **계정 금지 없음** — 채널당 속도 제한으로 플랫폼 API 할당량 초과를 방지합니다.
- **표시 상태** — 채널 상태는 색상으로 구분된 배지를 통해 설정 > 채널에서 항상 표시됩니다.
- **수동으로 다시 시작하지 않음** — 채널이 스스로 치유됩니다. 결과만 볼 뿐 회복 과정은 볼 수 없습니다
- **갑자기 정전 없음** — 스트리밍 업데이트가 갑자기 중지되는 대신 정상적으로 저하됩니다.

## GitHub 채널 및 CI/CD 통합

**GitHub 채널**은 에이전트를 저장소 이벤트를 수신하고 PR 댓글로 응답하는 자동화된 코드 검토자로 전환합니다.

### 지원되는 이벤트

| Event | Trigger | Agent Action |
|-------|---------|-------------|
| `pull_request` | PR opened / updated | Automatic code review + comment |
| `issues` | Issue created / updated | Triage, labeling, response |
| `issue_comment` | New comment on Issue/PR | Contextual reply |
| `push` | Commits pushed | Change analysis |
| `pull_request_review` | Review submitted | Follow-up discussion |



### 설정

1. **설정 > 채널 > GitHub**으로 이동합니다.
2. **개인 액세스 토큰**(댓글 게시 범위는 `repo`)을 입력하세요.
3. **Webhook 비밀번호**를 입력하세요(서명 확인용).
4. GitHub 저장소 설정에 웹훅 URL(`https://your-server/channels/github/webhook`)을 추가하세요.

### 보안

모든 수신 웹훅은 **X-Hub-Signature-256**(HMAC-SHA256)을 사용하여 확인됩니다. 잘못된 서명은 401 응답으로 거부됩니다.

### CI/CD 파이프라인 통합

GitHub 외에도 모든 CI/CD 플랫폼(Jenkins, GitLab CI, 云效, CodePipeline)은 REST API을 통해 에이전트를 트리거할 수 있습니다.```bash
curl -X POST https://your-server/api/chats/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "Review the latest commit on branch feature/xyz"}'
````

**Webhook 채널**은 구조화된 JSON을 사용자가 지정한 URL에 게시하여 외부 시스템에 결과를 전달할 수 있습니다.

## 원격 승인(HITL)

IM 채널을 통해 에이전트를 원격으로 제어할 때 위험성이 높은 도구 호출(파일 편집, 셸 명령)은 업계 유일의 IM 기반 HITL 시스템인 **채널 내 승인 프롬프트**를 트리거합니다.

### 작동 방식

1. 에이전트가 위험한 도구 호출을 발견했습니다.
2. 승인/거부 버튼이 포함된 메시지가 IM 채널로 전송됩니다.
3. 일괄 명령을 승인, 거부 또는 사용합니다.
4. 귀하의 결정에 따라 상담원이 재개되거나 중단됩니다.

### 승인 방법

| Method           | Example                                                          |
| ---------------- | ---------------------------------------------------------------- |
| Slash commands   | `/approve`, `/deny`, `/approve-always`                           |
| Deny with reason | `/deny <reason>` — Agent uses your reason to adjust its approach |
| Quick shortcuts  | `1` (approve), `2` (deny), `y`, `n`                              |
| Emoji reactions  | 👍 (once), ♾️ (always), 👎 (deny)                                |
| Batch            | `/batch a,d,a` (approve, deny, approve)                          |
| Chinese          | `同意`, `拒绝`, `是`, `不`                                             |

### 대화형 버튼(ActionButton)

대화형 요소(Telegram InlineKeyboard, Slack Block Kit, Discord 버튼, Feishu 카드, MS Teams 적응형 카드)를 지원하는 채널의 승인 프롬프트에는 기본 **승인/거부 버튼**이 포함됩니다. 버튼을 클릭하면:

1. 데이터베이스에서 승인을 해결합니다. (PENDING 전용 - 중복 클릭은 안전하게 무시됩니다.)
2. 원본 메시지를 편집하여 결과를 표시합니다(예: "Alice가 승인함")
3. 중단된 에이전트를 자동으로 재개합니다.

이는 WebUI 승인과 함께 작동합니다. 두 경로 모두 동일한 영구 기록으로 이어집니다.

### 보안

* **그룹 채팅 보호**: 원래 요청자 또는 구성된 공동 승인자만 승인할 수 있습니다.
* **멱등성 보호**: 이미 해결된 승인은 다시 해결하거나 상태를 뒤집을 수 없습니다(DB 수준 PENDING 확인).
* **타임아웃 가드**: 응답하지 않은 승인 자동 거부(구성 가능)
* **지속적 허용 목록**: '항상 허용' 결정은 다시 시작해도 유지됩니다.
* **재시도 방지**: 3회 거부 후 에이전트가 재시도를 중지합니다.

## 아웃바운드 HITL(초안 검토)

기업 판매 및 고객 서비스 시나리오의 경우 AI가 생성한 답변을 보내기 전에 사람의 검토가 필요할 수 있습니다. Myrm의 **아웃바운드 HITL**은 상담원의 답변을 초안으로 가로채어 명시적인 승인이 필요합니다.

### 구성

각 주제는 **설정 → 채널 라우팅**을 통해 독립적으로 구성할 수 있습니다.

| Setting    | Options                 | Description                                             |
| ---------- | ----------------------- | ------------------------------------------------------- |
| Reply Mode | Auto / Draft Review     | Auto sends immediately; Draft Review holds for approval |
| Timeout    | 1 min – 1 hour          | How long to wait before auto-action                     |
| On Expiry  | Auto Reject / Auto Send | What happens when nobody reviews in time                |

### 작동 방식

1. IM 채널에 메시지 도착 → 에이전트가 응답 생성
2. 응답을 가로채서 `ApprovalRecord`으로 저장합니다(전송되지 않음).
3. 검토자는 WebUI Approval Drawer 또는 IM ActionButton에서 초안을 봅니다.
4. **승인** → 해당 채널에 메시지가 전송됩니다.
5. **거부** → 메시지가 삭제됩니다.
6. **시간 초과** → 자동 전송 또는 자동 거부 구성 가능

### 리뷰 채널

* **WebUI Approval Drawer**: 원본 고객 메시지, AI 생성 초안, 채널/주제 정보 표시
* **IM ActionButtons**: 채널 승인 알림의 승인/거부 버튼

### 사용 사례

| Scenario                        | Why Draft Review                                |
| ------------------------------- | ----------------------------------------------- |
| Customer quotes/pricing         | Incorrect prices create legal liability         |
| Contract terms                  | AI may hallucinate non-standard clauses         |
| Compliance-regulated industries | Financial/medical communications require review |
| Brand-sensitive communications  | Tone and accuracy matter                        |

## 지능형 무음 필터링

에이전트의 시스템 프롬프트에 "주의가 필요한 항목이 없을 때 `[SILENT]`로 답장"과 같은 지침이 포함되어 있으면 Myrm은 전달되기 전에 이러한 자동 응답을 자동으로 감지하고 필터링합니다.

* **그룹 채팅**: 상담원이 언급되고 확인되며 주목할 만한 내용이 발견되지 않음 → 메시지가 전송되지 않음(소음 없음)
* **예약된 작업**: 정기 확인이 정상으로 돌아옴 → 자동으로 자동으로 실행, 문제가 발견된 경우에만 푸시
* **자리 표시자 정리**: "처리 중..." 자리 표시자 메시지가 자동으로 제거됩니다.

### 탐지 규칙

| Format                         |        Silent?       |
| ------------------------------ | :------------------: |
| `[SILENT]`                     |           ✅          |
| With whitespace `  [SILENT]  ` |           ✅          |
| Wrapped in markdown fence      |           ✅          |
| `[SILENT] nothing to report`   | ❌ Delivered normally |
| Contains other text            | ❌ Delivered normally |

이렇게 하면 "필요할 때만 알림" 환경이 보장됩니다. 에이전트는 의미 있는 말이 있을 때만 IM 채널에 메시지를 보냅니다.

## 깊은 Feishu 통합

Myrm의 Feishu 지원은 기본적인 메시징 그 이상입니다. 내장된 SDK는 6개의 기능 모듈을 깊이 통합하여 Feishu 문서, 스프레드시트, Wiki 및 댓글을 대화에서 직접 작동할 수 있도록 해줍니다.

### 지원되는 기능

| Module      | Capability                                 | Use Case                                            |
| ----------- | ------------------------------------------ | --------------------------------------------------- |
| Drive Meta  | File listing, metadata, permission queries | "List all documents in the shared folder"           |
| Docx Blocks | Block-level document read/write            | "Read meeting minutes and extract action items"     |
| Comments    | Batch query, create, reply to comments     | "@AI in a document comment, AI auto-replies"        |
| Wiki        | Knowledge base node search                 | "Find the deployment guide in Wiki"                 |
| Bitable     | Multi-dimensional table CRUD               | "Write analysis results to project tracking table"  |
| CardKit     | Card message streaming updates             | "Send progress card and update status in real-time" |

### 일반적인 작업 흐름

**시나리오: 회의록 읽기 → 작업 항목 추출 → 스프레드시트에 쓰기**\`\`\`
User: Please read last week's project meeting minutes, extract all action items, and write them to the project tracking Bitable

```

에이전트가 자동으로:
1. Drive Meta를 통해 대상 문서 찾기
2. Docx Blocks를 사용하여 전체 문서를 읽습니다.
3. LLM은 구조화된 작업 항목(담당자, 마감일, 우선순위)을 추출합니다.
4. Bitable을 통해 프로젝트 추적 테이블에 쓰기

**시나리오: 문서 댓글 기반 Q&A**

사용자가 Feishu 문서 댓글에서 AI를 @멘션하는 경우:
1. Feishu WebSocket은 댓글 이벤트를 실시간으로 푸시합니다.
2. 상담원은 댓글 내용 + 문서 컨텍스트를 읽습니다.
3. 댓글 스레드에 대한 답변 및 자동 게시를 생성합니다.

### 설정

1. **설정 > 채널 > Feishu**로 이동합니다.
2. 앱 ID, 앱 비밀번호 입력
3. **WebSocket 긴 연결** 활성화(공용 IP 필요 없음)
4. 필요에 따라 Feishu 앱 권한을 활성화합니다.
   - `drive:drive` — 문서 액세스
   - `wiki:wiki` — 위키 액세스
   - `bitable:bitable` — 테이블 작업
   - `im:message` — 메시징
   - `contact:user.id:readonly` — 사용자 식별

### WeCom 듀얼 채널

WeCom은 두 가지 통합 모드를 제공합니다.

| Mode | Use Case | Features |
|------|----------|----------|
| Standard Webhook | Enterprise self-built apps | Crypto verification + passive reply + active push |
| AI Bot | Intelligent customer service | Official AI Bot protocol + streaming replies |

두 모드 모두 다음을 지원합니다.
- XML 메시지 암호화/복호화(AES-CBC)
- 콜백 서명 검증(위조방지)
- 메시지 중복 제거(중복 처리 방지)

### WeChat 개인 듀얼 채널

| Mode | Protocol | Features |
|------|----------|----------|
| iLink | Third-party protocol layer | Personal account messaging + group chat |
| Official Account | Official API | Passive reply + template messages + draft box HITL |
```
