---
title: "mikan 開發心得：把 AI Coding Agent 搬進 Slack、Telegram 與 Discord"
url: https://geminixiang.com/posts/mikan-development-reflection/
description: "分享 mikan 這個多平台 AI coding agent 的開發心得：Slack / Telegram / Discord session model、sandbox 隔離、vault credential，以及開發 agent infra 時踩到的坑。"
published: 2026-05-25
category: "技術分享"
tags: ["AI Agent", "LLM", "Slack Bot", "Telegram Bot", "Discord Bot", "軟體架構"]
---

# mikan 開發心得：把 AI Coding Agent 搬進 Slack、Telegram 與 Discord

# mikan 開發心得：把 AI Coding Agent 搬進聊天室

> GitHub: [geminixiang/mikan](https://github.com/geminixiang/mikan)

最近在做一個 side project: **mikan**

一句話介紹的話，他是一個可以跑在 Slack / Telegram / Discord 上的 AI coding agent

可以在聊天室裡 @ bot，請他讀 repo、跑 command、改 code、查 session，或者透過 `/login` 把 credential 存進 vault，讓 agent 在 sandbox 裡面使用

> p.s. 目前 npm package 叫 `@geminixiang/mikan`，名字來源沒什麼深意，就是覺得 mikan 很可愛 🍊

這篇文章主要想記錄一下開發心得

不是完整教學，也不是很正式的 architecture review，比較像是做完一輪後，回頭看哪些地方比想像中麻煩、哪些設計還算滿意，以及我對 chat-based coding agent 的一些想法

## 開發契機

我現在蠻常使用 Claude Code / Pi 這類 coding agent，基本上已經回不太去了

但這些工具大多有一個使用前提: 你坐在 terminal 或 IDE 前面

可是實際工作中，很多事情不是從 terminal 開始，而是從聊天室開始

例如:

- Slack channel 裡有人貼一段 error log
- Telegram 群組有人問「這個 deploy 怎麼壞了」
- Discord 裡有人回報一個 issue
- thread 裡面討論了半天，最後還是要有人回去開 repo 處理

我就開始想，如果 coding agent 不只是 terminal 工具，而是直接住在聊天平台裡，會怎樣？

也就是說，agent 不只是回答「你可以怎麼做」，而是真的可以在當下對話的 context 裡做事

讀檔、改檔、跑測試、回報結果

mikan 就是從這個想法開始的

## 核心架構

![mikan architecture](@assets/images/posts/mikan-architecture.png)

mikan 做到後來，我覺得最重要的設計其實是這句:

> chat record、agent session、execution runtime 要分開

一開始很容易把這些東西混在一起

- 聊天平台的歷史 = agent context ?
- tool call 結果要不要直接塞回聊天室 ?
- command 直接在 host 上跑應該沒關係吧 ?

短期看起來都可以，反正 demo 會動

但一旦開始支援 Slack thread、Discord reply、Telegram reply chain，再加上多使用者、多 sandbox、多 credential，這些東西混在一起就會開始爆炸

所以 mikan 後來大概切成這幾層:

1. Platform adapters: Slack / Telegram / Discord 原生事件轉成統一格式
2. Session orchestration: 判斷這則訊息屬於哪個 agent session
3. Agent runner: 載入 model、memory、skills、structured session，然後執行 pi-coding-agent
4. Tools: read / bash / edit / write / event 等工具
5. Sandbox executor: host、container、image、firecracker、cloudflare bridge
6. Vault: credential 不放 workspace，而是在執行時注入 sandbox

如果用比較直覺的方式講:

- 聊天室是入口
- session 是工作記憶
- sandbox 是實際動手的地方
- vault 是 secret 的邊界

這幾個東西分開後，整個系統才比較不會變成一坨

## 最難的不是串平台 API

原本以為多平台 bot 最麻煩的是串 API

結果不是

真正麻煩的是 session model

Slack 有 thread，Discord 有 reply / thread，Telegram 沒有真正 thread 但有 reply chain。每個平台對「一段對話」的定義都不太一樣

但 agent 需要的是一個穩定的工作上下文

mikan 目前大概是這樣切:

| Platform | Session 規則 |
|----------|--------------|
| Slack | top-level / DM 共用 conversation session，thread 以 `conversationId:threadTs` 分支 |
| Discord | DM 用 channel，shared channel 的 top-level / reply 依 root message 切 session |
| Telegram | private chat 用 chat，群組靠 top-level message / reply chain 推出 session |

這件事情比我想像中重要很多

如果切太粗，兩個人在同一個 channel 叫 bot 做不同事情，context 會互相污染

如果切太細，每次都像新對話，agent 又完全沒有連續工作能力

所以現在我的感覺是:

> chat-based agent 的 session model，基本上就是產品體驗本身

使用者不會在意你底下怎麼存 jsonl

但他一定會在意:「我在這個 thread 繼續回，他到底知不知道我剛剛在講什麼？」

## log.jsonl 和 sessions/*.jsonl

mikan 裡面有兩種歷史紀錄

```text
<workspace>/<conversation>/
├── log.jsonl          # 平台對話紀錄，偏人類可讀
└── sessions/
    ├── current
    └── *.jsonl        # pi-coding-agent structured session
```

`log.jsonl` 記的是聊天室裡真的發生了什麼

誰說了什麼、bot 回了什麼、附件是什麼

`sessions/*.jsonl` 則是 agent 工作時真正需要的 structured context

包含 system prompt、tool calls、tool results、model response

這兩個東西一開始看起來有點重複，但實際上用途完全不同

- `log.jsonl` 適合 grep、稽核、debug platform event
- `sessions/*.jsonl` 適合恢復 agent 工作狀態
- thread / reply scope 可以有自己的 session file
- top-level session 用 `current` 指標管理

做 agent 系統後我越來越覺得，context 不是只有「使用者說了什麼」

agent 中間做過什麼也很重要

它讀了哪些檔案、跑了哪些 command、哪一步失敗，這些都是後續推理的一部分

## Sandbox

coding agent 最大的爽點是它可以動手

最大的風險也是它可以動手

所以 mikan 從一開始就把 executor 抽象出來，目前支援幾種模式:

| 模式 | 用途 |
|------|------|
| `host` | 本機開發最方便，但不注入 vault env |
| `container:<name>` | 在既有 Docker container 執行 |
| `image:<image>` | mikan 管理 per-conversation container，目前最推薦 |
| `firecracker:*` | microVM 實驗性支援 |
| `cloudflare:*` | Cloudflare sandbox bridge 實驗性支援 |

目前我會優先選 `image:<image>`

原因很現實，這是目前成本、維護性、隔離性之間比較合理的平衡

它大概會做到:

- 一個 conversation 對應一個 vault
- 一個 conversation 對應一個 managed container
- container 閒置後可以停掉
- vault env / file credential 只在執行時注入
- container 只能看到必要的 workspace 範圍

這樣 mikan 比較像一個可以多人共用的 agent service，而不是只有我自己在本機玩的 toy project

不過 `image:<image>` 不是終點，只是目前比較 pragmatic 的 default

我比較希望 mikan 的 sandbox 是一個可以持續強化的 runtime boundary

後續會慢慢看怎麼導入更完整的 sandbox backend，例如:

- [earendil-works/gondolin](https://github.com/earendil-works/gondolin)
- [kubernetes-sigs/agent-sandbox](https://github.com/kubernetes-sigs/agent-sandbox)

也就是說，不同部署情境可以選不同隔離等級

本機開發可以簡單一點，團隊共用或正式環境就需要更強的 boundary

> o.s. sandbox 永遠不是銀彈，只是讓你比較不容易當場爆炸

只要 agent 可以跑 command，就一定要思考:

- 它能看哪些檔案？
- 它能不能連網？
- 它拿到哪些 credential？
- CPU / memory 要不要限制？
- 它失控時要怎麼停？

這些都不是很潮的功能，但沒有這些東西，agent 很難放心給別人用

## Vault

credential 是另一個我很在意的點

如果 agent 要真的做事，它一定會需要 token

例如 GitHub token、雲端憑證、內部 API key 等等

但 secret 最不應該出現的地方就是聊天記錄和 repo workspace

所以 mikan 的 `/login` 走另一條路:

1. 使用者在 DM 裡輸入 `/login`
2. mikan 產生一個短效 onboarding link
3. 使用者在 web portal 裡填 API key 或走 OAuth
4. credential 寫入 `--state-dir` 底下的 vault
5. agent 執行 command 時，依 conversation / sandbox routing 注入 env 或 mount file

聊天室只負責觸發 login，不承載 secret 本身

這個設計不酷，但我覺得是 agent infra 很重要的底線

## Commands

mikan 有一些 chat commands:

- `/login`: credential onboarding
- `/session`: 開 read-only web session viewer
- `/new`: 重置目前 session
- `/model`: 切換模型
- `/pi-auto-reply on|off|status`: 控制群組自動回覆
- `/stop`: 中止目前執行

一開始我也覺得這些只是功能

後來發現不是

這些其實是 chat UI 裡的 control plane

因為聊天平台不像 terminal

沒有 `ctrl-c`，沒有 process list，也不一定看得到完整 stdout / stderr

當 agent 開始跑比較久的任務，如果沒有 `/stop`、`/session`、`/new` 這類控制手段，使用者會非常沒安全感

所以 command 的存在，其實是把 bot 從「一個可能亂跑的東西」變成「一個可以被控制的工作單元」

## 測試

mikan 的測試比我一開始預期多很多

包含 Slack / Telegram / Discord context、command parsing、session policy、sandbox executor、vault routing、login flow、event tool、session viewer 等等

原因很簡單，平台 API 的邊界情境太多

例如同樣是「回覆一則訊息」

Slack thread、Discord reply、Telegram reply chain 對 session 的影響完全不一樣

如果只靠手動測，很快就會壞掉

所以現在比較偏向把 platform event 轉成內部共用型別後，用 fake context 測核心邏輯

不要讓所有測試都真的依賴 Slack / Discord / Telegram API

這應該也是多 adapter 專案的老問題:

> 外部平台要薄，核心模型要厚

## 一些心得

### 1. context 不是越多越好

很多人會把長 context 當萬能解

但在 mikan 這種多 conversation、多 thread 的情境，真正重要的是 scope

錯的 context 比沒有 context 更糟

### 2. tool result 也是 UX

Agent 不是最後回答一句話就好

它中間讀了什麼、跑了什麼、失敗在哪裡，都會影響使用者信不信任它

所以 tool diagnostics、session viewer、log 這些東西很重要

雖然很無聊，但超重要

### 3. 不要太早硬抽象平台

Slack / Discord / Telegram 看起來都是 chat，但語意其實差很多

一開始就硬抽象，很容易做出一個看似漂亮，但其實不符合任何平台使用習慣的 interface

mikan 現在比較像是 adapter 裡保留平台差異，進 runtime 前再轉成共同模型

### 4. Sandbox / Vault 要比功能更早設計

如果等 bot 已經能做一堆事情後，才回頭補 credential isolation 和 sandbox，會很痛苦

Agent 產品最好一開始就想清楚:

- 它可以讀哪些檔案？
- 它可以跑哪些 command？
- 它拿到哪些 secret？
- 多人共用時，secret 會不會混在一起？
- 它失控時怎麼停？

### 5. Chat UX 和 CLI UX 是兩個世界

CLI 使用者可以忍受很多細節，因為他本來就在控制環境裡

聊天平台使用者期待的是: 我講一句話，它知道要做什麼，做完回報

這迫使 agent 必須更重視狀態、回覆節奏、錯誤訊息和可中止性

## 目前還不完美

mikan 現在還有很多可以改的地方

- Firecracker / Cloudflare sandbox 還偏實驗性
- 多人協作下的權限模型還可以更細
- session viewer 可以更像 observability console
- 長期 memory 和短期 session 的界線還能再打磨
- 不同模型在聊天平台上的成本與延遲策略還有很多可玩空間

但也因為這樣才好玩

做 mikan 的過程讓我更確定，AI coding agent 不會只停留在 IDE 或 terminal 裡

它會慢慢出現在 issue tracker、chat、CI、incident channel、文件系統裡，變成團隊工作流的一部分

## 總結

如果用一句話總結 mikan 的開發心得，我會說:

> 把 AI coding agent 放進聊天室，真正困難的不是讓它回話，而是讓它在正確的 context、正確的權限、正確的執行環境裡工作

LLM 會回答問題只是第一步

要讓它變成可靠的協作夥伴，還需要 session、sandbox、vault、commands、logs、tests 這些不性感但很重要的基礎設施

這些東西做好後，聊天平台就不只是通知工具，而可以變成一個多人共享的 agent workspace

這也是 mikan 想探索的方向

---

## 相關連結

- [mikan GitHub](https://github.com/geminixiang/mikan)
- [mikan npm package](https://www.npmjs.com/package/@geminixiang/mikan)
- [Pi Coding Agent](https://github.com/badlogic/pi-mono)

---

## About the author

**Ying Xiang Zhao** (geminixiang) — DevOps Engineer, Taipei, Taiwan.

Ying Xiang Zhao（geminixiang）是住在台北的 DevOps 工程師，工作橫跨雲原生基礎設施、CI/CD、ML 模型部署與全端開發。這個部落格記錄 infra、資安與 AI coding agent 的實戰筆記；作品包含開源專案 mikan（把 AI coding agent 帶進 Slack / Telegram / Discord）與 tiny-agent（用四種語言實作的極簡 coding agent），瀏覽器內的影片編輯器 Studio，並經營旅遊分帳工具 SentriPay。

**Open to work** — DevOps Engineer / Platform Engineer / Site Reliability Engineer / AI Infrastructure Engineer · Taipei, Taiwan / Remote. Résumé: https://geminixiang.com/about/ (JSON: https://geminixiang.com/resume.json)

Topics: DevOps, Cloud Native, Kubernetes, Docker, Terraform, Google Cloud, CI/CD, Security, AI coding agents, ML model deployment, TypeScript, Python

Projects:
- [mikan](https://github.com/geminixiang/mikan) — Self-hosted AI coding agent for Slack, Telegram, Discord and GitHub with per-conversation sandboxes
- [tiny-agent](https://github.com/geminixiang/tiny-agent) — Minimal AI coding agents in TypeScript, Go, Python and Rust, plus a book on how they work
- [SentriPay](https://sentripay.com) — Travel expense splitter with multi-currency conversion and shareable, live-synced trip ledgers
- [Studio](https://studio.geminixiang.com) — Browser-based video editor built on WebCodecs

[About](https://geminixiang.com/about/) · [Résumé](https://geminixiang.com/about/) · [LinkedIn](https://linkedin.com/in/geminixiang/) · [GitHub](https://github.com/geminixiang) · [Twitter](https://x.com/geminixiang)
