什麼是 PocketHook Agent Server?#
代理伺服器將 PocketHook 變成一個完整的 AI 助理。無需自己編寫回應邏輯,只需連接一個大型語言模型(Claude、GPT、Gemini 等)來處理訊息、呼叫工具並傳回結構化的 PocketHook 回應——包括捷徑觸發。
伺服器運行在您自己的機器上。您的資料由您掌控。
這是一個起點。 伺服器附帶一組核心工具,並被設計為可由您擴展。新增您自己的整合——郵件、行事曆、文件、API——讓它成為您的。
功能#
- 多供應商 LLM — Anthropic、OpenAI、GitHub Copilot、Google、Mistral、Groq、xAI、OpenRouter、Ollama(本地)、LM Studio(本地)
- OAuth 認證 — GitHub Copilot 和 OpenAI Codex,透過裝置碼/瀏覽器流程
- 代理工具 — Shell 指令、檔案讀寫、目錄列表、網路搜尋、網頁擷取、開發伺服器管理
- 框架/使用者分離 — 框架檔案(
skills/、custom-tools/、config/)保持唯讀。您的自訂內容位於data/user/(技能、自訂工具、說明、型別化偏好)。框架更新不會覆蓋您的工作 - 型別化使用者偏好 — 將偏好的地圖應用程式或隧道網域等值儲存在
data/user/prefs.json中。在技能中以{{prefs.key}}參照,伺服器會在載入時進行替換 - 一次呼叫完成程式設計工作 —
run_code_job元工具建立一個 prompt 類型的背景工作(由您設定的 LLM 執行)並在單一步驟中向使用者傳送確認,取代容易出錯的「respond + create-job」模式 - 型別化協定工具 — 六個專用
respond_*工具(respond_text、respond_image、respond_buttons、respond_shortcut、respond_html、respond_sequence),加上型別化工作工具(create_once_job、create_cron_job)和型別化工作區工具(create_project、list_projects、delete_project)。在到達裝置之前,結構描述會拒絕格式錯誤的 URL、按鈕語法以及type/schedule組合 - 型別化客製化寫入器 —
create_user_skill和create_custom_tool以正確的前置資料建立使用者層 markdown,因此載入器一律能解析它們,代理也無需手寫這些檔案 - 背景工作 — 使用 cron 運算式或簡單間隔的一次性或重複工作
- 動態技能 — 將捷徑和行為規則定義為
.md檔案。僅緊湊索引載入到提示中;完整內容透過load_skill工具按需取得 - 自我管理技能 — 代理可以建立、編輯和刪除技能定義(寫入一律落在使用者層)
- 語意記憶 — 使用嵌入(Ollama、LM Studio 或 OpenAI)的向量搜尋。記憶由 LLM 自動分類到 wing/room/hall/status 維度
- 知識圖譜 — 帶有自動失效的時間三元組儲存。多值關係共存;單值事實自動替換
- PARA 方法(含專案結束串聯) — 每條記憶都標記了狀態(Project、Area、Resource、Archive)。專案結束時,單次
complete_project呼叫即可歸檔其向量、使與其 slug 關聯的所有計劃三元組失效並記錄完成 — 一次呼叫而非三次 - 混合召回 — 使用倒數排名融合將 FTS5 關鍵字搜尋與向量語意搜尋相結合
- 長期記憶 — 當語意記憶停用時,使用 SQLite + FTS5 全文搜尋作為備援
- 帶隧道契約的開發伺服器管理 — 啟動、停止和列出開發伺服器。當請求
tunnel: true時,伺服器會在啟動前和啟動後強制執行 — 無法連線的 localhost 伺服器絕不會被悄悄保留執行 - 自動 URL 清理 — 若代理在回應中留下
localhostURL,respond_*工具會將其改寫為對應的隧道 URL,讓您的手機總是收到可連線的連結 - 自訂工具 — 代理可以安裝 CLI 工具並將其註冊為新功能
- 版本控制 — 工作區檔案的自動 git 版本控制;技能和權限的設定備份
- Web 儀表板 — 背景工作的即時概覽,可按使用者自訂。
/dashboard和/api/jobs在設計上是未認證的——請在網路層(Tailscale ACL、防火牆、帶基本認證的反向代理)限制存取,或在不需要時設定DASHBOARD=false - HTTPS 隧道 — 內建 Tailscale、ngrok 和 Cloudflare Tunnel 支援
- 系統服務 — 在 macOS、Linux 或 Windows 上安裝為持久服務
- 速率限制 — 可設定閾值的逐令牌請求限制
需求#
- Bun 執行環境
- LLM 供應商的 API 金鑰或 OAuth 憑證
- (可選)Tailscale、ngrok 或 cloudflared(用於 HTTPS 隧道)
快速開始#
git clone https://github.com/pockethook-app/pockethook-agent-server.git
cd pockethook-agent-server
bun install
# 互動式設定 — 選擇供應商、模型、認證令牌、連接埠
bun run setup
# 啟動伺服器 + HTTPS 隧道
bun run dev:tunnel
設定精靈將引導您選擇 LLM 供應商、設定認證和設定工具權限。
執行後,將顯示的 URL 複製到 PocketHook 設定中:
| PocketHook 設定 | URL |
|---|---|
| 伺服器 URL | https://your-host |
| 健康檢查 URL | https://your-host/health |
| 輪詢 URL | https://your-host/jobs |
運作方式#
- 您在 PocketHook 中傳送訊息
- 伺服器將訊息連同對話歷史、召回的記憶和可用工具一起轉發給您選擇的 LLM
- LLM 處理訊息——它可以執行 Shell 指令、讀寫檔案、搜尋網路、排程背景工作、記憶事實或啟動開發伺服器
- 回應以 PocketHook 格式(
msg+shortcut+data+url)傳回 - PocketHook 顯示訊息並在您的裝置上執行捷徑
支援的 LLM 供應商#
| 供應商 | 認證 | 預設模型 |
|---|---|---|
| Anthropic | API 金鑰 | claude-sonnet-4-20250514 |
| OpenAI | API 金鑰 | gpt-4.1-mini |
| OpenAI Codex | OAuth | gpt-5.1-codex-mini |
| GitHub Copilot | OAuth | claude-sonnet-4 |
| Google (Gemini) | API 金鑰 | gemini-2.5-flash |
| Mistral | API 金鑰 | mistral-medium-latest |
| Groq | API 金鑰 | llama-3.3-70b-versatile |
| xAI (Grok) | API 金鑰 | grok-3-mini-fast |
| OpenRouter | API 金鑰 | anthropic/claude-sonnet-4 |
| Ollama(本地) | 無 | llama3.2 |
| LM Studio(本地) | 無 | qwen3.5-4b-mlx |
使用 bun run switch 隨時切換供應商。Ollama 和 LM Studio 完全在您的機器上執行——無需 API 金鑰,資料不會離開您的網路。
記憶#
記憶系統有三個層次,各自服務於不同的目的。
語意記憶的設計結合了 MemPalace(一種將記憶組織成 wing、hall 和 room 的記憶宮殿架構)和 Tiago Forte 的 PARA 方法(Projects、Areas、Resources、Archive——知識生命週期管理)的理念。
對話記憶#
帶有 FTS5 全文搜尋的 SQLite。所有訊息都附帶時間戳記和工作階段 ID 儲存。
- 短期 — 每個工作階段保留最近
MAX_HISTORY條訊息在記憶體中 - 長期 — 所有訊息持久化儲存在 SQLite 中,可透過 FTS5 關鍵字配對搜尋
- 每輪召回 — 當語意記憶啟用時,
MAX_RECALL控制每輪注入提示中相關記憶的數量 - 工作階段在
SESSION_TTL_MINUTES後過期,但長期記憶永久保留
使用 bun run memory 進行互動式調整。
語意記憶#
需要 VECTOR_MEMORY=true 和嵌入供應商(Ollama、LM Studio 或 OpenAI)。
每條記憶被嵌入為向量,並由 LLM 自動分類到四個維度:
- Wing — 實體:
user、person:john、project:blog、place:london - Room — 類型:
facts、preferences、events、decisions、requests - Hall — 主題:
personal、tech、health、travel、food、work - Status — PARA 分類:
project、area、resource、archive
當您提問時,實體擷取會將向量搜尋聚焦到最相關的 wing。結果使用倒數排名融合與 FTS5 關鍵字結果合併——這樣您可以同時獲得關鍵字配對和語意配對的最佳效果。
知識圖譜#
用於結構化、持久事實的時間三元組儲存:
- 三元組:
(subject, predicate, object)帶有valid_from/valid_until時間戳記 - 單值謂詞(
lives_in、partner)在更新時自動使舊值失效 - 多值謂詞(
child、friend、hobby)共存而不失效 - 知識圖譜事實與召回的記憶一起注入每次對話
當您告訴代理*「我搬到柏林了」*時,它會使舊的 lives_in 三元組失效並自動建立新的——全自動。
PARA 生命週期#
每條記憶都標記了 PARA 狀態:
- Project — 活躍的、有時間限制的工作
- Area — 持續的責任
- Resource — 參考資料(清單、推薦、教學)
- Archive — 已完成或已取消的專案
當專案完成時,代理使用語意相似度僅歸檔該專案的記憶,同時保留參考資料以供未來使用。
專案結束串聯#
說一句*「我要取消巴塞隆納之行」*,單次工具呼叫就能處理一切:
- 歸檔專案的向量(與巴塞隆納相關的 events、decisions、requests)。
- 使所有謂詞與專案 slug 相符的活躍知識圖譜三元組失效(
scheduled_visit_barcelona、planning_visit_barcelona、confirmed_visit_barcelona)。 - 將完成記錄為一個新三元組:
(user, "cancelled_visit_barcelona", "2026-04-15")。
配對會感知邊界 — 一個名為 revisit_barcelona 的不同專案會保持不變。代理不再需要以正確順序編排三次獨立呼叫,因此較小的模型也能正確處理。
如果 VECTOR_MEMORY 被停用或嵌入供應商無法連線,系統會無錯誤地退回到僅 FTS5 模式。
技能#
技能是 skills/ 目錄中的 .md 檔案,定義代理可以觸發的 iOS 捷徑和/或行為規則。它們使用動態載入:僅緊湊索引(標題、描述、捷徑列表)注入系統提示。代理透過 load_skill 工具按需載入完整內容,在新增更多技能時保持低令牌使用量。
每個技能檔案使用 YAML 前置資料:
---
title: Notes
description: Create notes on the user's device with a title and body
shortcuts: [newNote]
target: mac
sync_app: Notes
---
### New Note
Shortcut name: `newNote`
Creates a new note on the user's device.
Data fields:
- title (string, required): Note title
- content (string, required): Note body
前置資料欄位#
| 欄位 | 必填 | 描述 |
|---|---|---|
title | 是 | 人類可讀的名稱 |
description | 是 | 用於向代理展示的技能索引中的一句話描述 |
shortcuts | 是 | 檔案中定義的捷徑名稱陣列。對於僅包含行為規則的技能,使用 [] |
target | 否 | 捷徑執行位置:device(預設,傳送至 iOS)或 mac(在伺服器上執行) |
sync_app | 否 | 伺服器端執行後於背景喚起以觸發 iCloud 同步的應用程式(例如 Notes、Calendar、Reminders)。省略或使用 none 以略過 |
技能也可以是沒有捷徑的行為規則(例如「如何規劃家庭旅行」)。這種情況使用 shortcuts: []。
代理可以在被要求時建立和管理技能——讓它*「建立一個控制燈光的技能」*,它會為您編寫 .md 檔案。新建和編輯的技能一律落在您的使用者層(data/user/skills/),因此框架更新永遠不會覆蓋它們。請參閱下方的自訂您的代理章節。
在 Mac 伺服器上執行捷徑#
當技能設定了 target: mac 時,捷徑會透過 shortcuts run CLI 在 Mac 伺服器上靜默執行,而不是傳送到 iOS 裝置。這非常適合建立 iCloud 同步內容的操作——備忘錄、提醒事項、日曆事件——因為結果會自動同步到所有裝置,無需 PocketHook 應用程式做任何事情。
運作方式:
- 代理決定應該執行某個捷徑(例如「用今天的會議筆記建立一則備忘錄」)
- 伺服器以 PocketHook iOS 使用的相同包裝格式,透過 stdin 以 JSON 形式傳遞資料,呼叫
shortcuts run "shortcutName" - 如果設定了
sync_app,伺服器會短暫在背景開啟該應用程式(open -gj -a Notes)以強制 iCloud 同步,然後在 5 秒後關閉它 - 使用者在聊天中收到確認訊息;捷徑本身不會傳送到裝置
需求:
- 伺服器必須執行於 macOS 上——
shortcuts run僅限 macOS。在其他平台上,伺服器會記錄警告並退回到裝置執行 - 捷徑必須已安裝在伺服器 Mac 的 Shortcuts.app 中
- 捷徑應當接受 Dictionary 作為輸入(PocketHook 會將資料包裝為
{ context, timestamp, app, data })
何時使用 target: mac:
- iCloud 同步的操作(Notes、Reminders、Calendar)——結果無論如何都會同步到每台裝置
- 希望不佔用 iOS 裝置的長時間處理
- 不需要與 iPhone UI 互動的任何捷徑
何時保持 target: device(預設):
- 需要 iPhone 專屬功能的捷徑(相機、精確定位、本機應用程式自動化)
- 需要使用者互動式輸入的捷徑
- 使用僅限 iOS 應用程式 App Intents 的捷徑
背景工作#
讓代理排程工作,它會處理其餘的一切:
- 「每天早上8點檢查天氣並建立筆記」
- 「每小時執行這個腳本」
- 「30分鐘後提醒我檢查郵件」
工作支援 cron 運算式(0 8 * * *)和簡單間隔(30m、1h、2d)。結果在 PocketHook 輪詢 /jobs 端點時傳遞。
兩種執行類型:
- Shell — 執行 bash 指令,擷取輸出。完成後可觸發捷徑
- Prompt — 由擁有完整工具存取權限的 AI 代理處理,儲存完整的 PocketHook 回應
開發伺服器#
當代理在工作區建立 Web 專案(Hugo、Astro、Next.js、Flask、Go 等)時,它會主動提議進行服務:
- 預覽 — 在自動分配的連接埠上啟動本地開發伺服器以快速檢視
- 公開 — 啟動伺服器並透過 HTTPS 隧道暴露,使其可從任何地方存取
代理管理生命週期:啟動、停止和列出執行中的伺服器。主伺服器停止時,所有伺服器都會被清理。
隧道契約#
當代理請求隧道暴露啟動伺服器時,執行時會強制執行:若未安裝任何隧道工具(Tailscale、ngrok、cloudflared),伺服器將拒絕啟動。若在衍生之後隧道設定失敗,孤立的行程會被停止,並明確通知代理 — 讓它能回退到預覽模式,或請您安裝隧道。啟用隧道時,傳回的 URL 一律是隧道 URL,並附帶本機 URL 僅限主機的註記。
作為安全網,每個 respond_* 工具會對其訊息進行後處理:任何悄悄混入回覆的 localhost 或 127.0.0.1 URL,只要託管伺服器有對應的隧道,就會被自動改寫為對應的隧道 URL。當無法改寫時,您會在日誌中看到警告,而不是在手機上看到損壞的連結。
儀表板#
/dashboard 處的內建 Web 儀表板顯示背景工作的即時概覽。
設計上未認證。
/dashboard和/api/jobs都是開放的GET端點——任何能存取主機的人都可以列出工作。請在網路層(Tailscale ACL、防火牆、帶基本認證的反向代理)限制存取,或在不需要時設定DASHBOARD=false。PocketHook iOS 應用程式不使用這些端點。
它完全可自訂:
- 快速編輯 — 在
workspace/dashboard/中放置dashboard.html進行簡單自訂 - 完整專案 — 在
workspace/dashboard/中建立框架專案(Svelte、React、Vue 等),建構輸出到dist/
讓代理自訂您的儀表板,它會處理其餘的——每位使用者獲得獨特的、個人化的儀表板。
自訂工具#
代理可以安裝 CLI 工具並將其註冊為新功能——無需修改伺服器程式碼即可自我擴展。
例如,說*「安裝 Playwright 並用它來截圖」*。代理將:
- 安裝相依套件
- 建立工具定義(一個簡單的
.md檔案) - 在未來的對話中使用新工具
自訂工具熱重新載入——無需重啟。刪除 .md 檔案即可移除工具。
版本控制#
所有使用者資料都自動進行版本控制:
- 工作區檔案 — 使用
workspace/內的本地 git 儲存庫追蹤。每次寫入都建立自動提交。讓代理*「復原上次變更」*或手動使用git revert HEAD - 設定檔案 —
config/agent-instructions.md、config/personality.md、skills/和permissions.json在每次修改前備份。每個檔案最多 20 個版本
git 是可選的——如果未安裝,工作區變更不會被版本控制。設定備份始終有效。
自訂您的代理#
代理伺服器附帶一個極簡的框架基礎,並期望您在其上疊加自己的自訂內容。執行時將兩者分離,因此框架更新永遠不會破壞您的工作。
框架 vs 使用者#
pockethook-agent-server/
├── skills/ # 框架隨附的技能(唯讀)
├── custom-tools/ # 為框架隨附工具保留(唯讀)
├── config/
│ ├── agent-instructions.md # 框架代理說明(唯讀)
│ └── personality.md # 框架人格(唯讀)
└── data/user/ # 您的自訂放在這裡(被 git 忽略)
├── skills/ # 您自己的技能(依檔名覆蓋基礎)
├── custom-tools/ # 您安裝的自訂工具
├── instructions.md # 您對代理說明的追加內容
└── prefs.json # 以 {{prefs.key}} 參照的型別化值
使用者自訂內容透過專用的型別化工具(create_user_skill、create_custom_tool)寫入,因此產生的檔案一律符合載入器的格式。write 工具還會拒絕任何位於 skills/、custom-tools/ 或 config/ 下的路徑,並將代理重新導向至 data/user/* — 這樣即使是直接的檔案編輯也最終會落在使用者層。
關於基礎
custom-tools/目錄的說明。 目前它只包含一個載入器會忽略的範本(_example.md) — 代理為您安裝的每個工具都會進入data/user/custom-tools/。保留這個目錄是為了讓未來的框架版本能夠提供可選的內建工具而不會覆蓋您已安裝的內容。屆時工具名衝突時您的使用者層檔案仍然優先,因此無需遷移。
四種自訂方式#
| 您想變更什麼 | 放在哪裡 | 範例 |
|---|---|---|
| 捷徑或行為技能 | data/user/skills/<name>.md | 「建立一個記錄我運動的技能」 |
| 包裝為代理能力的 CLI 工具 | data/user/custom-tools/<name>.md | 「安裝 ffmpeg 並讓我用它做轉換」 |
| 全域規則(「一律用英文回覆」、「不要使用表格」) | data/user/instructions.md | 「從現在起,一律用3個要點摘要文章」 |
| 技能參照的型別化預設值 | data/user/prefs.json | 「我預設的路線起點是馬德里」 → {"routeOrigin": "Madrid"} |
您無需手動編寫這些檔案。只需告訴代理您想要什麼,它會自動選擇合適的層。
使用 {{prefs.*}} 的型別化偏好#
假設您編寫一個需要知道預設起點的路線規劃技能。不要將「Madrid」硬編碼到技能中,而是參照偏好:
- **起點**: {{prefs.routeOrigin}},除非使用者指定了不同的起點。
並將值儲存在 data/user/prefs.json 中:
{
"routeOrigin": "Madrid, Spain",
"preferredMapsApp": "apple",
"tunnel": { "domain": "my-host.ts.net" }
}
伺服器會在載入技能時替換佔位符。巢狀鍵({{prefs.tunnel.domain}})也可以使用。未知鍵保持不變,因此拼寫錯誤仍然可見。
直接編輯框架基礎#
如果您正在自架並想調整框架本身,可以直接編輯 config/agent-instructions.md、config/personality.md、skills/ 或 custom-tools/ — 當您使用檔案編輯器時伺服器不會阻止您。但代理不會在對話中寫入這些路徑。並且框架更新會覆蓋您的編輯。對於想保留的內容,請優先使用使用者層。
擴展伺服器#
- 自訂工具 — 讓代理安裝 CLI 工具;它們會自動落在
data/user/custom-tools/ - 新增技能 — 讓代理建立技能;檔案會進入
data/user/skills/ - 變更行為 — 讓代理套用全域規則;它會追加到
data/user/instructions.md - 設定權限 — 執行
bun run permissions控制代理可以使用的工具 - 新增內建工具 — 在
src/tools.ts中實作新的工具函數以進行更深入的整合(需要 fork 伺服器)
設定#
所有設定儲存在 .env(由 bun run setup 建立)中。主要選項:
| 變數 | 預設值 | 描述 |
|---|---|---|
AUTH_TOKEN | (必填) | 與 PocketHook 的共用密鑰 |
LLM_API_KEY | (必填) | LLM 供應商 API 金鑰 |
LLM_PROVIDER | anthropic | 供應商名稱 |
LLM_MODEL | claude-sonnet-4-20250514 | 模型 ID |
LLM_REASONING | off | 推理強度:off、minimal、low、medium、high、xhigh。較高等級會增加隱藏的思考令牌(較慢且較昂貴)。不支援的模型會忽略此項 |
PORT | 3000 | 伺服器連接埠 |
AGENT_NAME | PocketHook Assistant | 代理顯示名稱 |
MAX_HISTORY | 50 | 短期記憶中的訊息數 |
MAX_RECALL | 5 | 語意召回每輪傳回的記憶數(僅在 VECTOR_MEMORY=true 時) |
SESSION_TTL_MINUTES | 60 | 工作階段過期時間 |
VECTOR_MEMORY | false | 啟用語意記憶(需要嵌入供應商) |
EMBEDDING_PROVIDER | ollama | 嵌入供應商:ollama、lm-studio 或 openai |
EMBEDDING_MODEL | nomic-embed-text | 嵌入模型名稱 |
EMBEDDING_URL | (自動) | 嵌入 API URL |
EMBEDDING_API_KEY | — | OpenAI 嵌入 API 金鑰 |
LOG_LEVEL | info | 日誌等級:debug、info、warn、error |
RATE_LIMIT_MAX | 30 | 每視窗最大請求數 |
DASHBOARD | true | 啟用 Web 儀表板(/dashboard 路由) |
INSTANCE_NAME | (專案目錄基本名,去掉 pockethook- 前綴) | 用於系統服務標籤、日誌目錄和行程比對的後綴。在同一台機器上執行多個檢出時顯式設定 |
完整設定參考請查看 GitHub 儲存庫。
作為服務執行#
安裝為自動啟動的持久服務:
bun run service install
| 平台 | 後端 | 服務位置 |
|---|---|---|
| macOS | launchd | ~/Library/LaunchAgents/com.pockethook.${INSTANCE_NAME}.plist |
| Linux | systemd(使用者) | ~/.config/systemd/user/pockethook-${INSTANCE_NAME}.service |
| Windows | NSSM | PocketHook-${PascalCase(INSTANCE_NAME)}(位於 Windows 服務管理員中) |
INSTANCE_NAME 預設為去掉 pockethook- 前綴後的專案目錄基本名(例如,位於 pockethook-agent-server/ 的檢出會變成 agent-server)。在同一台機器上執行多個檢出而不衝突時請顯式設定 — 每個實例會保留自己的 data/ 和日誌。
使用 bun run service status、restart、stop 或 uninstall 管理。
安全#
- HTTPS 必需 — PocketHook 對所有 URL 強制要求 HTTPS
- Bearer 令牌認證 — 應用程式和伺服器之間的共用密鑰
- 速率限制 — 逐令牌限制防止濫用
- 沙箱工具 — Shell 指令和檔案存取受權限限制
- 封鎖模式 — 危險指令(
sudo、rm -rf /)預設被封鎖 - 工作目錄邊界 — 代理無法逃出其指定目錄
- 敏感檔案保護 —
.env、.git、*.key、*.pem被封鎖代理存取 - 自動版本控制 — 所有工作區變更透過 git 追蹤,便於回復