大模型应用
需要长期在线、有持久记忆和自我进化能力的 AI 同事时,用…
当你想让 AI 代理拥有独立 VM、跨会话记忆、运行时创建 MCP 工具、Slack/邮件/Telegram/Webhook 通道并能自我进化时,按此部署 Phantom。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
需要长期在线、有持久记忆和自我进化能力的特定
解决思路
- Docker 安装:执行 curl -fsSL https://raw.githubusercontent.com/ghostwright/phantom/main/docker-compose.user.yaml -o docker-compose.yaml 下载 compose file。
- Docker 安装:执行 curl -fsSL https://raw.githubusercontent.com/ghostwright/phantom/main/.env.example -o .env 下载 env 模板。
- Docker 安装:编辑 .env,按 Configuration 小节填入凭据。
- Docker 安装:执行 docker compose up -d 启动 Phantom,包含 Qdrant + Ollama。
- Docker 安装:执行 curl http://localhost:3100/health 检查健康。
- Docker 安装:执行 docker compose logs -f phantom 查看日志。
- 源码安装:执行 git clone https://github.com/ghostwright/phantom.git 并 cd phantom。
- 源码安装:执行 bun install 安装依赖。
- 源码安装:执行 cp .env.example .env 并编辑 .env。
- 源码安装:执行 docker run -d -p 6333:6333 qdrant/qdrant 启动 Qdrant,这是记忆功能必需。
- 源码安装:执行 bun run start 启动 Phantom。
- 源码安装:开发时执行 bun run dev 启用 hot reload。
- 配置 .env:设置 ANTHROPIC_API_KEY。
- 配置 .env:Slack 通道设置 SLACK_BOT_TOKEN=xoxb-、SLACK_APP_TOKEN=xapp-、SLACK_SIGNING_SECRET、OWNER_SLACK_USER_ID=U0XXXXXXXXX。
- 配置 .env:记忆设置 QDRANT_URL=http://localhost:6333、QDRANT_API_KEY(云 Qdrant 可选)、OLLAMA_URL=http://localhost:11434。
- 配置 .env:邮件可选设置 RESEND_API_KEY 和 PHANTOM_EMAIL。
- 配置 .env:Telegram 可选设置 TELEGRAM_BOT_TOKEN。
- 配置 .env:基础设施设置 PHANTOM_VM_DOMAIN 和 PHANTOM_PORT=3100。
- 配置 .env:自进化设置 EVOLUTION_VALIDATION_MODEL=claude-3-5-sonnet-20241022 和 EVOLUTION_ENABLED=true。
- 配置 .env:凭据保险库设置 CREDENTIAL_ENCRYPTION_KEY(为空则自动生成 AES-256-GCM key)。
- 常用命令:执行 docker compose up -d/down/logs -f phantom/pull 管理服务。
- 常用命令:执行 bun run start/dev/test/build 进行生产启动、开发、测试、构建 TypeScript。
- 常用命令:执行 curl http://localhost:3100/health 和 curl http://localhost:3100/status 检查健康与状态。
- 常用命令:访问 curl http://localhost:3100/mcp 作为 MCP server endpoint。
- 记忆系统:在 src/memory/memory-manager.ts 中 import QdrantClient from @qdrant/js-client-rest,并用 new QdrantClient({ url: process.env.QDRANT_URL }) 创建客户端。
- 记忆系统:实现 storeMemory(content, metadata):通过 Ollama 生成 embedding,然后 client.upsert('phantom_memory', { points: [{ id: crypto.randomUUID(), vector: embedding, payload: { content, timestamp: Date.now(), ...metadata } }] })。
- 记忆系统:实现 recallMemories(query, limit = 5):生成 query embedding,client.search('phantom_memory', { vector: queryEmbedding, limit, with_payload: true }),返回 results.map(r => r.payload?.content)。
- 动态 MCP 工具:定义 PhantomTool interface,包含 name、description、inputSchema、handler。
- 动态 MCP 工具:实现 registerDynamicTool(tool):先用 storeMemory(JSON.stringify(tool), { type: 'mcp_tool', toolName: tool.name }) 持久化工具定义,再调用 mcpServer.tool(tool.name, tool.description, tool.inputSchema, async (args) => executeToolHandler(tool.handler, args)) 注册。
- 动态 MCP 工具:从 @modelcontextprotocol/sdk/server/mcp.js import McpServer,并用 new McpServer({ name: 'phantom', version: '0.18.1' }) 创建 MCP server。
- 动态 MCP 工具:连接 Claude Code 时,在 claude_desktop_config.json 或 .cursor/mcp.json 中配置 mcpServers.phantom.url 为 http://your-phantom-vm:3100/mcp。
- Slack 通道:用 @slack/bolt 的 App({ token: process.env.SLACK_BOT_TOKEN, appToken: process.env.SLACK_APP_TOKEN, socketMode: true, signingSecret: process.env.SLACK_SIGNING_SECRET }) 创建 Slack app。
- Slack 通道:监听 slack.event('message'),若 event.subtype 存在则 return;读取 text 和 user,调用 recallMemories(userMessage) 获取上下文,再调用 runPhantomAgent({ message, userId, memories, channel }),最后 say({ text: response, thread_ts: event.ts })。
- Slack 通道:实现 notifyOwnerReady(),用 slack.client.chat.postMessage({ channel: process.env.OWNER_SLACK_USER_ID!, text: '👻 Phantom is online and ready.' }) 通知 owner。
- Claude Agent SDK:用 new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }) 创建 Anthropic 客户端。
- Claude Agent SDK:实现 runPhantomAgent({ message, userId, memories, channel }):调用 buildSystemPrompt(memories),再调用 anthropic.messages.create({ model: 'claude-opus-4-5', max_tokens: 8096, system: systemPrompt, messages: [{ role: 'user', content: message }], tools: await getAvailableTools() })。
- Claude Agent SDK:若 response.stop_reason === 'tool_use',调用 handleToolCalls(response, message, userId) 处理工具调用循环。
- Claude Agent SDK:将交互存为记忆,调用 storeMemory(`User ${userId} asked: ${message}. I responded: ${response.content}`, { type: 'interaction', userId, channel })。
- Claude Agent SDK:返回 extractTextContent(response.content)。
- Claude Agent SDK:实现 buildSystemPrompt(memories),在 system prompt 中列出 Relevant memories from past sessions,并说明可访问 VM、安装软件、构建工具、在 PHANTOM_VM_DOMAIN 提供网页、注册新能力。
- 安全凭据收集:使用 AES-256-GCM,KEY 来自 process.env.CREDENTIAL_ENCRYPTION_KEY,实现 encryptCredential 和 decryptCredential,格式为 iv:authTag:encrypted 的 hex。
- 安全凭据收集:实现 generateCredentialForm(service, fields):生成 randomBytes(32).toString('hex') token,用 storeCredentialRequest 存储 service、fields、expires: Date.now() + 3600000,返回 ${process.env.PHANTOM_VM_DOMAIN}/credentials/${token}。
- 自进化引擎:实现 runEvolutionCycle(),当 EVOLUTION_ENABLED 为 true 时,用 recallMemories('recent interactions', 50) 观察近期交互。
- 自进化引擎:用主模型 generateEvolutionProposals(recentMemories) 生成 EvolutionProposal(包含 observation、currentBehavior、proposedChange、rationale、version)。
- 自进化引擎:对每个 proposal 调用 validateProposal(proposal),用独立模型 EVOLUTION_VALIDATION_MODEL 校验,提示返回 JSON { approved: boolean, reason: string }。
- 自进化引擎:若校验通过,调用 applyEvolution(proposal) 和 versionEvolution(proposal),并用 notifySlack 通知 owner 已进化。
- VM 基础设施:用 promisify(exec) 包装 child_process.exec,执行 shell 和 Docker 命令。
- VM 基础设施:实现 provisionDatabase(projectName):找可用端口,randomBytes(16).toString('hex') 生成密码,执行 docker run -d --name phantom-pg-${projectName} -e POSTGRES_PASSWORD=${password} -e POSTGRES_DB=${projectName} -p ${port}:5432 postgres:16-alpine。
- VM 基础设施:provisionDatabase 后构造 postgresql://postgres:${password}@localhost:${port}/${projectName},用 encryptCredential 加密后 storeCredential,并 registerDynamicTool({ name: `query_${projectName}_db`, description: `Query the ${projectName} PostgreSQL database`, inputSchema: { sql: { type: 'string' } }, handler: `postgres:${connectionString}` })。
- VM 基础设施:实现 serveWebPage(slug, htmlContent),用 Bun.write 写入 /var/phantom/public/${slug}/index.html,返回 ${process.env.PHANTOM_VM_DOMAIN}/${slug}。
- Webhook 通道:向 http://your-phantom:3100/webhook/message POST,headers 包含 Content-Type: application/json 和 Authorization: Bearer ${process.env.PHANTOM_WEBHOOK_SECRET},body 包含 message、userId、context,解析返回的 response 和 taskId。
- 连接 Claude Code:在 ~/.claude/claude_desktop_config.json 或 .cursor/mcp.json 的 mcpServers.phantom.url 填 http://your-phantom-vm:3100/mcp。
- 连接 Claude Code:执行 claude mcp add phantom --url http://your-phantom-vm:3100/mcp 添加 MCP。
- 连接 Claude Code:执行 claude mcp list 验证连接。
- Docker Compose:phantom 服务使用 image ghostwright/phantom:latest、ports 3100:3100,传入 ANTHROPIC_API_KEY、SLACK_*、OWNER_SLACK_USER_ID、QDRANT_URL=http://qdrant:6333、OLLAMA_URL=http://ollama:11434、PHANTOM_VM_DOMAIN、RESEND_API_KEY,挂载 phantom_data:/var/phantom 和 /var/run/docker.sock:/var/run/docker.sock,depends_on qdrant 和 ollama,restart: unless-stopped。
- Docker Compose:qdrant 服务使用 image qdrant/qdrant:latest,挂载 qdrant_data:/qdrant/storage,restart: unless-stopped。
- Docker Compose:ollama 服务使用 image ollama/ollama:latest,挂载 ollama_data:/root/.ollama,restart: unless-stopped。
- Slack App 设置:到 api.slack.com/apps → Create New App → From manifest 创建应用。
- Slack App 设置:使用 manifest,设置 display_information.name 为 Phantom,bot_user.display_name 为 Phantom、always_online: true,app_home.messages_tab_enabled: true。
- Slack App 设置:在 oauth_config.scopes.bot 添加 channels:history、channels:read、chat:write、chat:write.customize、files:write、groups:history、im:history、im:read、im:write、mpim:history、users:read。
- Slack App 设置:在 settings.event_subscriptions.bot_events 添加 message.channels、message.groups、message.im、message.mpim,设置 interactivity.is_enabled: true 和 socket_mode_enabled: true。
- Slack App 设置:安装到 workspace,复制 Bot Token xoxb- 到 SLACK_BOT_TOKEN。
- Slack App 设置:生成带 connections:write 的 App-Level Token,复制到 SLACK_APP_TOKEN。
- Slack App 设置:复制 Signing Secret 到 SLACK_SIGNING_SECRET。
- Slack App 设置:在 Slack 点击个人资料复制 Member ID 到 OWNER_SLACK_USER_ID。
- 常见用法:在 Slack 对 @phantom 说,创建一个 MCP tool,查询 https://metrics.internal/api/v2 的指标,接受 metric_name 和 time_range 参数并返回 JSON。
- 常见用法:在 Slack 对 @phantom 说,每个工作日 9am 检查 GitHub repo myorg/myrepo 中超过 3 天的 open PR,并把摘要发到 #engineering。
- 常见用法:在 Slack 对 @phantom 说,构建展示最近 30 天部署频率的 dashboard,并让团队可分享;Phantom 会构建、在 https://your-phantom-domain/dashboards/deploy-freq 提供服务并发送链接。
- 常见用法:向 @phantom 询问记忆,例如上次告诉你的数据库架构、已经构建了哪些工具、总结关于 Project X 的一切。
- 排障 Phantom 未启动:执行 docker compose ps,查看 Qdrant 日志并 curl http://localhost:6333/health,查看 Ollama 日志并确认已拉取 embedding model。
- 排障记忆不持久:执行 curl http://localhost:6333/collections 检查 collections,执行 docker compose exec phantom curl http://qdrant:6333/health 检查连通性。
- 排障 Slack 收不到消息:确认 SLACK_APP_TOKEN 以 xapp- 开头而非 xoxb-,启用 Socket mode,执行 /invite @Phantom 邀请 bot,确认 OWNER_SLACK_USER_ID 是实际 ID 而非 display name。
- 排障 MCP tools 不出现在 Claude Code:curl http://localhost:3100/mcp,curl http://localhost:3100/mcp/tools,添加 MCP 配置后重启 Claude Code。
- 排障 Evolution 不触发:echo $EVOLUTION_ENABLED 应为 true,echo $EVOLUTION_VALIDATION_MODEL,docker compose logs phantom | grep -i evolv 查看进化周期日志。
- 排障 Docker socket permission denied:把 phantom 用户加入 docker 组,或执行 sudo docker compose up -d,或在 docker-compose.yaml 添加 user: root。
- API 使用:GET /health 健康检查;GET /status 代理状态和 uptime;GET/POST /mcp MCP server endpoint;GET /mcp/tools 列出已注册工具;POST /webhook/message 发消息给 agent;GET/POST /credentials/:token 安全凭据表单;GET /public/:slug 提供静态资源。
- 版本与回滚:docker compose logs phantom | grep -i evolved 查看进化历史。
- 版本与回滚:在 docker-compose.yaml 把 image 固定到 ghostwright/phantom:0.18.1。
- 版本与回滚:回滚时 docker compose down,修改 compose file 中的 image tag,再 docker compose up -d。
适用边界 · 注意事项
- 不想或不能使用 Anthropic API、Slack、Qdrant、Ollama、Docker、Resend 等依赖时不要用。
- 只需要简单聊天机器人,不需要持久记忆、动态 MCP 工具、自进化或独立 VM 时不要用。
- 没有可分配给 Phantom 的独立机器/VM、公开域名和 Docker 运行权限时不要用。