@winches/agent-slack
v0.1.9
Published
绑定当前目录为 workspace 的 Slack agent 服务。
Readme
agent-slack
绑定当前目录为 workspace 的 Slack agent 服务。
安装
pnpm install # 源码方式:进入本仓库
pnpm build # 生成 bin/agent-slack.js
pnpm link --global # 或直接 node bin/agent-slack.js快速开始
cd your-project/
agent-slack onboard # 交互式配置 Slack/LiteLLM 凭证,生成 .agent-slack/
agent-slack doctor # 验证环境与凭证
agent-slack start # 启动(前台阻塞)在 Slack 里 @agent-slack 你好 即可开始对话。
配置示例
仓库内置了可复制的本地配置示例:
| 示例文件 | 复制到 | 说明 |
| --- | --- | --- |
| examples/config.example.yaml | .agent-slack/config.yaml | agent / provider / model / maxSteps / context / skills / daemon |
| examples/channel-tasks.example.yaml | .agent-slack/channel-tasks.yaml | Slack 频道任务监听规则 |
| examples/system.md | .agent-slack/system.md | workspace system prompt(Slack 场景默认骨架,鼓励按项目改写) |
| examples/.env.example | .agent-slack/.env.local | Slack / provider 凭证、debug、live E2E env |
这些文件是模板源(src/workspace/templates/ 下的 generator 直接读取它们),只包含占位符,不含真实凭证。.agent-slack/.env.local、session、logs、channel task ledger 仍应保持 git ignore。
目录
<your-project>/.agent-slack/
├── config.yaml # agent / model / skills 配置(可选,缺失则用默认值)
├── channel-tasks.yaml # 频道任务监听配置(可选,缺失则关闭)
├── system.md # system prompt(可选)
├── .env.local # 凭证(git ignore)
├── channel-tasks/ # 频道任务触发 ledger(JSONL,git ignore)
├── sessions/slack/ # 对话历史(JSONL)
├── memory/ # 长期记忆(Markdown)
├── skills/ # SKILL.md 增强
└── logs/ # 日志(JSON lines)命令
| 命令 | 说明 |
| --- | --- |
| agent-slack onboard | 交互式初始化当前目录(询问 Slack 三件套 + LiteLLM 并当场校验) |
| agent-slack start | 启动服务(前台阻塞,Ctrl+C 优雅退出) |
| agent-slack status | 打印 workspace 配置 + skills + 最近 session 摘要 |
| agent-slack doctor | 环境自检(Node / 目录 / 凭证 / Slack auth / LiteLLM /models / 模型可用 / skills) |
| pnpm e2e:list / pnpm e2e <id> | 手动运行 Slack live E2E(真实发送 Slack 消息) |
所有命令支持 --cwd <dir> 显式指定 workspace 目录。
Provider 切换(LiteLLM / Anthropic)
一期支持两种模型 provider,启动时选定(运行期不切换):
| Provider | 底层 | 必填 env | 适用 |
| --- | --- | --- | --- |
| litellm(默认) | LiteLLM OpenAI-compatible 网关 | LITELLM_BASE_URL / LITELLM_API_KEY | 多模型聚合、自建网关 |
| anthropic | Anthropic Messages API | ANTHROPIC_API_KEY(可选 ANTHROPIC_BASE_URL) | 直连 Anthropic / 自建 Claude 网关 |
行为配置走 config.yaml(方案 A:config 单一权威):
agent:
name: default
model: claude-sonnet-4-5 # provider 对应的模型 ID
provider: anthropic # litellm | anthropic
maxSteps: 50
context:
maxApproxChars: 1000000 # 只限制发给模型的历史视图,不裁剪 messages.jsonl
# effectiveContextTokens: 200000 # 显式 opt-in:设了就用真实 input_tokens 触发;不设回退字符估算
keepRecentMessages: 80 # 模型视图末尾保留的最近消息数;仅作 buildModelMessages 尾部窗口,不参与 autoCompact 触发
keepRecentToolResults: 20 # 最近 N 个工具结果保留完整;更旧结果仅在模型视图中压缩
autoCompact:
enabled: true # 达到预算阈值时自动压缩上下文,然后继续本轮回复
triggerRatio: 0.8 # token 路径:(effectiveContextTokens - 33_000) * 0.8;字符回退:maxApproxChars * 0.8
maxFailures: 2 # 同 session 连续失败 2 次后自动熔断凭证 / URL / debug 走 .env.local:
# Slack(必填)
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...
SLACK_SIGNING_SECRET=...
# LiteLLM(provider=litellm 时必填)
LITELLM_BASE_URL=http://localhost:4000
LITELLM_API_KEY=sk-...
# Anthropic(provider=anthropic 时必填)
ANTHROPIC_API_KEY=sk-ant-...
# ANTHROPIC_BASE_URL=https://api.anthropic.com/v1 # 可选:自建网关
LOG_LEVEL=info
# Slack live E2E(可选;真实发 Slack 消息)
# SLACK_E2E_CHANNEL_ID=C...
# SLACK_E2E_TRIGGER_USER_TOKEN=xoxp-...
# SLACK_E2E_TIMEOUT_MS=240000
# SLACK_E2E_RESULT_PATH=.agent-slack/e2e/result.json切换步骤:编辑 .agent-slack/config.yaml 的 agent.provider + 对应 agent.model,补齐 .env.local 凭证,重启进程。agent-slack onboard 在交互流程中会直接问一次 provider 并把选择写入 config.yaml。
不支持:运行期多 provider 并存 / per-session 切换 / Claude Agent SDK / OpenAI Responses API(后续 spec 评估)。
Slack 频道任务监听(可选)
默认只有 @agent-slack 会触发对话。如果需要“监听某个频道里指定用户或 bot 的消息,并自动在该消息 thread 中执行任务”,可以创建 .agent-slack/channel-tasks.yaml。文件缺失时功能关闭;保存后需要重启 agent-slack start 或 daemon 才生效。
推荐通过 dashboard 管理:
agent-slack dashboard打开 Channel Tasks tab 后,可以生成带中文注释的模板、编辑 raw YAML、保存前做 schema 校验、删除配置。Dashboard 会原样保存 YAML,不会重排或删除中文注释。
最小示例:
version: 1
enabled: true
rules:
- id: daily-watch
enabled: true
channelIds: [C0123456789]
source:
includeUserMessages: true
includeBotMessages: false
userIds: [U0123456789]
botIds: []
appIds: []
message:
includeRootMessages: true
includeThreadReplies: false
allowSubtypes: [none]
requireText: true
ignoreAgentMentions: true
task:
prompt: |
请阅读触发消息,判断是否需要处理,并给出简洁结论。
includeOriginalMessage: true
includePermalink: true
reply:
inThread: true
dedupe:
enabled: true字段说明:
userIds、botIds、appIds都是 allowlist。includeBotMessages控制是否处理“由 bot 发送”的bot_message;ignoreAgentMentions控制文本里 @当前 agent 时是否跳过,避免和app_mention重复。- 某些 Slack bot 消息可能带
bot_id/app_id但没有subtype;只要规则允许bot_message且botIds/appIds命中,运行时仍会按 bot 来源处理。 reply.inThread当前固定为true:根消息会创建 thread,thread 回复会沿用原 thread。- 运行时触发记录保存在
.agent-slack/channel-tasks/triggers.jsonl,用于 Slack 重试去重和审计,建议 git ignore。
Slack App 需要额外开启事件订阅和 scope:
| 能力 | Slack 配置 |
| --- | --- |
| 监听公开频道消息 | Event Subscriptions: message.channels;Bot Token Scope: channels:history |
| 监听私有频道消息(可选) | Event Subscriptions: message.groups;Bot Token Scope: groups:history |
| 回复 thread / reaction | 继续使用 chat:write / reactions:write |
| 解析用户名称 | 继续使用 users:read |
定时任务 / Scheduled Tasks(可选)
agent-slack 支持时间驱动入口:在 .agent-slack/scheduled-tasks.yaml 配 cron + prompt + IM 目标,daemon 跑起就会到点触发并把结果发到指定 Slack 频道或微信会话。
最简启用步骤:
- 复制模板:
cp .agent-slack/scheduled-tasks.example.yaml .agent-slack/scheduled-tasks.yaml(或运行agent-slack upgrade让框架自动补齐)。 - 顶层
enabled: true;至少一条 task 内部enabled: true。 - 重启 daemon:
agent-slack daemon restart。
立即手动跑一次(独立进程):
agent-slack scheduled-tasks run <id>每次运行的状态写到 .agent-slack/logs/scheduled-tasks.jsonl(每行一条 JSON,started/success/failed/skipped,含 runId / taskId / trigger / target / error / finalSummary)。
最小示例:
version: 1
enabled: true
tasks:
- id: daily-standup
enabled: true
description: 工作日早上 9 点总结昨日 PR/issue
cron: '0 9 * * 1-5'
# timezone: 'Asia/Shanghai' # 可选;默认本机时区
prompt: |
请总结最近 24 小时仓库的关键变更,列 3-5 条要点。
target:
im: slack
channelId: C0123456789
- id: weekly-report
enabled: false # 未启用就不会被 scheduler 注册,但仍可手动 run
cron: '0 17 * * 5'
prompt: |
生成本周工作小结,3 个 highlight + 下周计划。
target:
im: wechat
to: [email protected]Wechat target 用法:
微信服务端要求 bot 主动发消息必须带 context_token,这个 token 由对方上一条入站消息提供。配置流程:
- daemon 必须先跑起来:
agent-slack daemon start(首次会扫码登录)。 - 让那位联系人先给 bot 发过至少一条消息——daemon 会自动把
context_token落盘到.agent-slack/wechat/context-tokens.json(per-peer)。 - 把 target.to 填成那个联系人的 ilink_user_id(形如
[email protected])。
定位 microid 的方法:
- 自己微信账号的 ilink_user_id 在
.agent-slack/wechat/credentials.json的userId字段(用来推到 bot ↔ 自己的私聊)。 - 其他联系人的 microid 在 daemon 收到 ta 的入站消息后写到
context-tokens.json,直接cat查看。
若 store 未命中 target.to,scheduled 路径会抛 MissingContextTokenError,jsonl 写 failed 行,错误信息会指引你去补入站消息。
其他已知限制(首版):
- daemon SIGTERM 不 graceful drain:被打断的任务会在 jsonl 留
started无终态行(便于排查"为什么半截")。 - CLI 与 daemon 同时刻撞同一任务会双发:跨进程互锁成本高,撞同一时刻概率低,已知接受。
- 一期不做失败重试 / 多目标 fan-out。需要时复制任务。
- Schema 错误(cron 非法 / id 重复 / 目标 IM 未在
config.im.enabled启用)→ daemon 启动 / CLI 调用都会早失败。
CLI 退出码:
| code | 触发 |
|---|---|
| 0 | 成功 |
| 1 | 一般运行时错误 |
| 2 | rule id 不存在 |
| 3 | 微信凭证缺失(target=wechat 时) |
| 4 | 目标 IM 未在 config.im.enabled 启用 |
| 5 | yaml schema 错或文件不存在 |
完整设计见 docs/superpowers/specs/2026-05-10-scheduled-tasks-design.md。
Project Structure
src/
application.ts # DI root: createApplication()
index.ts # dev 入口(pnpm dev)
types/ # interface 先行(AgentExecutor/IMAdapter/EventSink/...)
agent/
ai-sdk/ # 一期唯一 AgentExecutor 实现
agents/ # compact / selfImprove 等辅助 agent 与 prompts 归口
im/
slack/ # 一期唯一 IMAdapter 实现
orchestrator/ # ConversationOrchestrator + SessionRunQueue + AbortRegistry
store/ # SessionStore / MemoryStore(文件系统)
workspace/ # WorkspaceContext 加载(config.yaml + system.md + skills/)
skills/ # SKILL.md loader(gray-matter)
logger/ # consola + redactor
bin/cli.ts # agent-slack CLI 入口(onboard/start/status/doctor)
tests/ # 跨模块集成测试
docs/superpowers/specs/ # 架构决策文档(design doc)