Skip to content

4t145/lark-acp

Repository files navigation

lark-acp

npm version npm downloads node version license

💖 觉得本项目有帮助、或者只是看着有点意思?动动发财的小手在右上角点个 ⭐ Star 吧——这是对作者最直接的鼓励。

⚠️ WIP:仍在迭代中,1.0 之前 CLI 选项与配置字段可能继续调整。

飞书/Lark 机器人接到任何符合 ACP(Agent Client Protocol) 的 AI Agent 上:用户在飞书里发消息,agent 在你的机器上跑,过程和结果都以一张可交互的飞书卡片呈现,工具调用授权、中断、跨进程恢复会话都在卡片里完成。

实际使用强烈建议配合飞书cli与其skill一起使用,本桥阶层会把会话信息注入上下文,通过飞书cli可以衔接各种飞书操作。

lark-acp 在飞书里的演示卡片


CLI: lark-acp

安装与运行

# 通过 npm / npx:
npx -y @4t145/lark-acp --help

# 或在仓库内本地构建:
bun install
bun run build
node dist/bin/lark-acp.js --help

命令格式

lark-acp [global-options] proxy --agent <preset> [-- <extra-args>...]
lark-acp [global-options] proxy -- <agent-cmd> [agent-args...]
lark-acp agents
lark-acp help
lark-acp version

两种启动方式:

  • --agent <preset> —— 使用内置预设,最常用。运行 lark-acp agents 查看完整列表。
  • -- <agent-cmd> —— 自定义命令,-- 后的所有参数原样转发给 agent。

两种方式可以组合:proxy --agent claude -- --debug 会在预设末尾追加 --debug 再启动。

全局选项必须放在 proxy 子命令之前。

内置 agent 预设

Preset 说明
claude Claude Code,需先在终端跑过 claude 完成登录。
claude-agent Claude Agent SDK 适配器,需要 ANTHROPIC_API_KEY
codex OpenAI Codex 适配器。
copilot GitHub Copilot CLI。
gemini Google Gemini CLI(实验性)。
opencode OpenCode,需要 opencode 已在 $PATH 上。

不在预设里的 agent,用 raw command:

lark-acp proxy -- node ./my-acp-server.js --port 9000

也可以在配置文件的 agents 字段里固化自己的预设(详见下文「配置文件」一节)。

全局选项

选项 说明
--cwd <dir> agent 工作目录(默认当前目录)
--config <path> 覆盖配置文件路径
--data-dir <dir> 覆盖会话存储目录
--idle-timeout <min> 闲置 N 分钟后释放会话(0 表示永不,默认 1440)
--max-chats <n> 最大并发会话数(默认 10)
--hide-thoughts 不在卡片里渲染思考过程
--hide-tools 不在卡片里渲染工具调用
--hide-cancel-button 不渲染卡片底部的"中断当前任务"按钮
--permission-mode <m> 工具授权策略:alwaysAsk(默认,弹卡片让用户选)/ alwaysAllow(自动允许)/ alwaysDeny(自动拒绝)
-h, --help 显示帮助
-v, --version 显示版本

配置文件

CLI 读取一份配置文件(默认 ~/.config/lark-acp/config.json),里面包含凭据和运行时默认值。优先级:CLI flag > 环境变量 > 配置文件 > 内置默认。

完整字段(都可选):

{
  "credentials": {
    "appId": "cli_xxxxxxxxxxxxxxxx",
    "appSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  },
  "dataDir": "./var/lark-acp",
  "runtime": {
    "cwd": "/work/project",
    "idleTimeoutMinutes": 1440,
    "maxChats": 10,
    "hideThoughts": false,
    "hideTools": false,
    "hideCancelButton": false,
    "permissionMode": "alwaysAsk",
  },
  "agents": {
    // 在已有的内置预设上"打补丁"——只需要写要改的字段
    "claude": {
      "env": { "ANTHROPIC_BASE_URL": "https://my-proxy.example.com" },
    },
    // 新增一个用户自己的预设——必须同时给出 label 和 command
    "my-agent": {
      "label": "My ACP Agent",
      "command": "node",
      "args": ["./my-agent.js", "--acp"],
      "description": "本地自研 agent",
      "env": { "FOO": "bar" },
    },
  },
}

凭据可以用环境变量代替文件:LARK_ACP_APP_ID / LARK_ACP_APP_SECRET

lark-acp agents 会列出当前配置下所有可用的预设,并标出来源([built-in] / [user] / [overridden])。

在飞书开放平台 开发者后台 创建一个"自建应用",从「凭证与基础信息」页拿 App ID / App Secret;在「事件与回调」里把订阅模式切到 长连接 (WebSocket)。具体步骤见下文「飞书开发者后台配置」。

飞书开发者后台配置

飞书开放平台(海外版 Lark Developer)创建一个"自建应用"后,需要配置三块:权限事件回调,然后发布版本。

1. 添加权限

「权限管理 → 批量导入/导出权限 → 导入」,粘贴下面这份 JSON 后保存:

{
  "scopes": {
    "tenant": [
      "im:message",
      "im:message.group_msg",
      "im:message.p2p_msg:readonly",
      "im:message:readonly",
      "im:message:send_as_bot",
      "im:message:update",
      "im:message.reactions:write_only",
      "im:resource",
      "im:chat:readonly",
      "cardkit:card:write",
      "contact:user.base:readonly"
    ],
    "user": []
  }
}

每条权限对应的能力:

权限 用途
im:message / im:message:send_as_bot 以机器人身份回复用户消息
im:message.group_msg 在群聊中接收消息
im:message.p2p_msg:readonly 在单聊中接收消息
im:message:readonly 拉取消息上下文(@提及解析、富文本展开)
im:message:update 更新交互卡片(流式渲染思考 / 工具调用 / 终态)
im:message.reactions:write_only 给消息加 / 撤 emoji 反馈,标记任务进度
im:resource 下载用户上传的图片 / 文件二进制(按 message_id
im:chat:readonly 读群信息(注入到 prompt 上下文里:群名、群 id)
cardkit:card:write 发送 / 修改 v2 互动卡片
contact:user.base:readonly 读用户名(注入到 prompt 上下文里:发送者姓名)

2. 添加事件

「事件与回调 → 事件配置」,把订阅方式切到 使用长连接接收事件(不需要配置回调地址)。然后添加这一个事件,订阅身份选"应用身份":

事件名 event_type 用途
接收消息 im.message.receive_v1 用户发的每条消息进入桥接层

3. 添加回调

同一页「事件与回调 → 事件配置」下方的"卡片回调"区,添加:

回调名 event_type 用途
卡片回传交互 card.action.trigger 用户点击卡片按钮(授权选项 / 中断当前任务)

4. 发布版本

「版本管理与发布 → 创建版本」,按提示填写资料后提交审核 / 发布。应用可见范围根据实际需要选——只有可见范围内的用户才能在飞书里找到这个机器人并对话。

5. 启用

App ID / App Secret 填到 config.json(或环境变量 LARK_ACP_APP_ID / LARK_ACP_APP_SECRET),运行:

lark-acp proxy --agent claude

然后在飞书里搜到这个机器人、单聊或拉到群里直接发消息即可。

配置示例

最小配置(仅写一个文件,其它走默认)

# 1. 准备目录(首次使用时一次性执行)
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/lark-acp"

# 2. 写入凭据
cat > "${XDG_CONFIG_HOME:-$HOME/.config}/lark-acp/config.json" <<'EOF'
{
  "credentials": {
    "appId":     "cli_a1b2c3d4e5f60001",
    "appSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  }
}
EOF
chmod 600 "${XDG_CONFIG_HOME:-$HOME/.config}/lark-acp/config.json"

# 3. 启动桥接
lark-acp proxy --agent claude

完整配置(凭据 + 运行时默认值)

把常用默认值固化到文件,命令行只剩 proxy --agent

{
  "credentials": {
    "appId": "cli_a1b2c3d4e5f60001",
    "appSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  },
  "runtime": {
    "cwd": "/srv/projects/main",
    "idleTimeoutMinutes": 60,
    "maxChats": 20,
    "hideThoughts": true,
  },
}
lark-acp proxy --agent claude

CLI flag 会临时覆盖文件里的同名项。

systemd 托管

lark-acp 是前台进程,由进程管理器托管即可:

[Service]
Environment=LARK_ACP_APP_ID=cli_a1b2c3d4e5f60001
Environment=LARK_ACP_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ExecStart=/usr/local/bin/lark-acp --cwd /srv/projects/main proxy --agent claude
Restart=on-failure

快速示例

# 1. 接 Claude Code(最常用)
#    会话自动持久化,重启不丢上下文。
lark-acp proxy --agent claude

# 2. 接 OpenCode,工作目录指向具体项目
lark-acp --cwd /work/project proxy --agent opencode

# 3. 接 GitHub Copilot CLI,关掉思考输出
lark-acp --hide-thoughts proxy --agent copilot

# 4. 自研 ACP server
lark-acp proxy -- node ./my-acp-server.js --port 9000

类似的项目

  1. golang 版本,实现也很齐全,https://github.com/ri-char/Lark-ACP
  2. 另一个node版本,本项目由此重构而来 https://github.com/JiaqiZhang-Dev/lark-acp

本实现的不同

  1. 经过生产实践上的考虑,对permissionMode添加了代理层的设置
  2. 多个消息合并成一个卡片,避免在群聊中消息轰炸
  3. 作为库提供,方便二次开发

参考

License: MIT

About

Bridge Feishu/Lark chat messages to any ACP-compatible AI agent (Copilot, Claude, Codex, Gemini, OpenCode and more)

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors