Emacs AI 工作台 agent-shell:基于 ACP 协议与 Emacs Lisp 的智能编程助手集成

发布时间:2026/10/2 6:46:28
Emacs AI 工作台 agent-shell:基于 ACP 协议与 Emacs Lisp 的智能编程助手集成 1. 为什么要在 Emacs 里塞一个 AI 工作台第一次听说有人把 AI 助手直接做进 Emacs我的反应是这不是多此一举吗终端里开个窗口跑个命令行工具不就行了浏览器里开个网页版不也挺方便但真正在 Emacs 里写了几年代码、跑了几年工作流之后我慢慢理解了这个思路的合理性——Emacs 本身就是一个高度可编程的工作台把 AI 能力嵌进来等于给这个工作台装了一个能理解上下文、能调用工具、能持续对话的“副驾驶”。agent-shell这个项目的核心定位就是在 Emacs 内部提供一个 AI agent 的交互外壳。它不是简单的“聊天窗口”而是一个能跟 Emacs 生态深度绑定的工作流节点。你可以把它理解成以前你在 Emacs 里写代码、跑测试、查文档、改配置现在多了一个能跟你一起干这些事的搭档而且这个搭档就住在你的 Emacs 里能直接看到你当前 buffer 的内容、能调用你定义好的函数、能根据你的项目结构给出建议。这个项目解决的核心痛点有三个。第一上下文割裂。你在浏览器里跟 AI 聊代码得手动复制粘贴AI 看不到你的项目全貌你也得反复描述背景。第二工作流中断。写代码写到一半切到浏览器问个问题再切回来思路断了效率也掉了。第三工具链不统一。不同 AI 服务有不同的接口、不同的交互方式今天用这个明天用那个配置散落各处管理成本高。agent-shell适合谁来参考如果你是一个 Emacs 重度用户每天大部分时间都在 Emacs 里度过同时又在日常工作中频繁使用 AI 辅助编程、写作或信息处理那这个项目值得你花时间研究。如果你只是偶尔用 Emacs 改改配置文件那可能没必要折腾用现成的网页版或命令行工具更省事。但如果你追求的是“一个环境搞定所有事”的工作流那这个方向值得深入。我自己的使用场景是这样的写 Python 脚本时让 agent 帮我检查类型标注是否合理写技术文档时让 agent 根据当前 buffer 的内容帮我润色段落调试配置时让 agent 解释某段 Lisp 代码的执行逻辑。这些操作都不需要离开 Emacs也不需要手动复制粘贴上下文agent 直接读取当前环境响应速度很快思路也不会被打断。2. agent-shell 的整体设计与核心思路拆解2.1 为什么选择 ACP 作为通信协议agent-shell这个名字里的 “shell” 不是随便起的。它借鉴了 shell 的设计哲学提供一个统一的交互界面底层可以对接不同的执行引擎。你用的可能是 bash也可能是 zsh但交互方式是一致的。agent-shell也是这个思路上层是 Emacs 的交互界面底层通过 ACP 协议跟不同的 AI agent 通信。ACP 在这里指的是 Agent Client Protocol一种专门为 AI agent 交互设计的通信协议。为什么不用 HTTP 直接调 API因为 agent 的交互模式跟传统的请求-响应模式不一样。一个 agent 可能需要多轮对话、可能需要调用工具、可能需要流式输出、可能需要维护会话状态。HTTP 短连接做这些事情很别扭而 ACP 天生就是为这种场景设计的。我打个比方HTTP 调 API 就像你去餐厅点菜点完等着上菜吃完走人。ACP 更像你坐在吧台跟调酒师聊天你可以随时加单、随时问问题、随时让他根据你的口味调整配方。agent-shell选择 ACP就是为了让交互更自然、更连续、更符合“工作台”的定位。从技术实现角度看ACP 通常基于 WebSocket 或类似的持久连接机制支持双向通信。这意味着 agent 可以主动向 Emacs 推送消息比如“我发现了你代码里的一个问题”或者“我帮你把这段配置改好了”。这种主动性是传统 API 调用做不到的。2.2 Emacs Lisp 作为胶水层的优势agent-shell用 Emacs Lisp 来写这个选择非常关键。Emacs Lisp 在这个项目里扮演的是“胶水层”的角色它把 Emacs 的内部状态、用户的操作习惯、AI agent 的能力三者粘合在一起。具体来说Emacs Lisp 能做几件其他语言做不了或者做起来很麻烦的事。第一直接访问 Emacs 内部状态。当前 buffer 的内容、光标位置、选中的区域、打开的文件列表、甚至最近的操作历史这些信息在 Lisp 里都是随手可得的。agent 需要上下文的时候直接把这些信息打包发过去就行不需要用户手动提供。第二无缝集成 Emacs 的交互体系。agent-shell可以定义自己的 major mode可以绑定快捷键可以利用 Emacs 的补全框架、语法高亮、窗口管理。用户用起来的感觉就是“Emacs 原生功能”而不是“外挂了一个东西”。第三动态扩展和定制。Emacs Lisp 是解释执行的用户可以随时修改 agent 的行为、添加新的工具函数、调整交互流程改完立即生效不需要重启 Emacs。这种灵活性对于 AI 工作台来说非常重要因为每个人的工作流都不一样需要不断调整。我自己的配置里就加了好几个自定义函数比如“把当前选中的代码块发给 agent 并让它解释”、“让 agent 根据当前文件的内容生成单元测试”、“把 agent 的建议直接插入到光标位置”。这些函数都是用 Emacs Lisp 写的几十行代码就能搞定非常方便。2.3 模块化架构与可扩展性设计agent-shell的架构是模块化的大致可以分为三层。最底层是通信层负责跟 AI agent 建立连接、发送请求、接收响应。中间层是会话管理层负责维护对话历史、管理多个会话、处理上下文切换。最上层是交互层负责在 Emacs 里展示内容、接收用户输入、绑定快捷键。这种分层设计的好处是每一层都可以独立替换或扩展。比如你想换一个 AI 服务提供商只需要改通信层的配置上层完全不用动。你想加一个新的交互方式比如语音输入或者图片粘贴只需要扩展交互层底层通信不受影响。我特别欣赏的一点是agent-shell没有把 AI 服务写死。它通过 ACP 协议跟 agent 通信理论上只要 agent 实现了 ACP 接口就可以接入。这意味着你可以用本地的模型也可以用云端的服务可以今天用这个明天用那个切换成本很低。从扩展性角度看agent-shell预留了很多钩子hook和自定义变量。你可以定义 agent 在特定事件发生时做什么比如“当打开新文件时自动发送文件路径给 agent”、“当保存文件时让 agent 检查语法错误”、“当用户按下某个快捷键时让 agent 执行特定任务”。这些钩子让 agent 的行为可以高度定制化适应不同的工作场景。3. 核心细节解析与实操要点3.1 环境准备与依赖安装在开始配置agent-shell之前你需要确保几件事。第一Emacs 版本不能太老建议 27.1 以上因为项目用了一些较新的 Lisp 特性。第二你需要一个可用的 AI agent 后端可以是本地运行的也可以是远程服务。第三你需要基本的 Emacs Lisp 配置能力知道怎么改init.el或者early-init.el。安装方式有几种。如果你用straight.el或者elpaca这类包管理器可以直接从 Git 仓库拉取。如果用package.el可能需要手动配置源。我个人的建议是用straight.el因为agent-shell更新比较频繁用 Git 直接拉取能第一时间拿到新功能。;; 用 straight.el 安装 agent-shell (straight-use-package (agent-shell :type git :host github :repo your-repo/agent-shell))安装完之后你需要配置 agent 的连接信息。这部分通常包括 agent 的地址、端口、认证方式如果有的话。agent-shell一般会提供一个自定义变量来设置这些参数比如agent-shell-endpoint或者agent-shell-connection-config。注意如果你用的是本地 agent确保 agent 服务已经启动并且监听在正确的端口上。我踩过的坑是 agent 启动了但绑定的是 localhost而 Emacs 跑在另一个环境里导致连不上。后来改成绑定 0.0.0.0 或者用正确的地址才解决。3.2 会话管理与上下文传递agent-shell的会话管理是我觉得最实用的功能之一。你可以同时开多个会话每个会话有自己的上下文和历史记录。比如一个会话用来写代码一个会话用来写文档一个会话用来做研究。切换会话的时候上下文自动切换不会混淆。上下文传递是另一个关键点。agent-shell默认会把当前 buffer 的内容、光标位置、选中的区域作为上下文发给 agent。但这个行为是可以配置的。你可以设置只发送选中的区域或者只发送当前函数的定义或者发送整个项目结构。我自己的配置是这样的对于代码相关的会话发送当前函数的完整定义加上光标附近的几行对于文档相关的会话发送当前段落加上文档的标题结构对于通用问答只发送用户输入的内容。这样既能给 agent 足够的上下文又不会因为发送太多信息导致响应变慢。;; 自定义上下文发送策略 (setq agent-shell-context-function (lambda () (if (derived-mode-p prog-mode) (agent-shell-get-current-function) (agent-shell-get-current-paragraph))))会话历史的管理也很重要。agent-shell会把对话记录保存在内存里你可以随时回看之前的对话。如果你需要持久化可以配置保存到文件。我一般会把重要的会话保存下来方便以后查阅。3.3 快捷键绑定与交互优化Emacs 的快捷键体系是它的灵魂之一agent-shell自然也支持自定义快捷键。默认情况下它可能会绑定一些前缀键比如C-c a作为 agent 相关操作的入口。你可以根据自己的习惯调整。我建议把最常用的操作绑定到容易按的键上。比如“发送当前区域给 agent”绑定到C-c C-s“切换会话”绑定到C-c C-n“清空当前会话”绑定到C-c C-k。这些操作频率高键位要顺手。;; 快捷键绑定示例 (define-key agent-shell-mode-map (kbd C-c C-s) #agent-shell-send-region) (define-key agent-shell-mode-map (kbd C-c C-n) #agent-shell-next-session) (define-key agent-shell-mode-map (kbd C-c C-k) #agent-shell-clear-session)交互优化方面agent-shell支持流式输出也就是说 agent 的回复是逐字显示的不用等全部生成完才看到。这个体验很好感觉像在跟真人对话。另外它支持 Markdown 渲染代码块会高亮链接可以点击表格会对齐阅读体验比纯文本好很多。还有一个细节agent-shell会把 agent 的回复插入到当前 buffer 还是单独的 buffer这个可以配置。我一般用单独的 buffer因为不想污染正在编辑的文件。但有时候让 agent 直接修改当前 buffer 也很方便比如让它帮我重构一段代码。4. 实操过程与核心环节实现4.1 从零开始配置一个可用的 agent-shell假设你已经在 Emacs 里装好了agent-shell现在要从零配置一个能用的环境。第一步是确认 agent 后端已经就绪。我用的是一个本地运行的 agent监听在 8080 端口。启动 agent 之后用curl测试一下能不能通。curl http://localhost:8080/health # 返回 {status: ok} 说明 agent 正常运行第二步是在 Emacs 里配置连接信息。打开init.el加入以下配置(require agent-shell) (setq agent-shell-endpoint http://localhost:8080 agent-shell-session-timeout 300 agent-shell-streaming t agent-shell-context-mode auto) (agent-shell-mode 1)这里解释一下几个参数。agent-shell-endpoint是 agent 的地址。agent-shell-session-timeout是会话超时时间单位秒超过这个时间没有交互会自动断开。agent-shell-streaming开启流式输出。agent-shell-context-mode设置上下文模式auto表示根据当前 major mode 自动决定发送什么上下文。第三步是测试连接。在 Emacs 里执行M-x agent-shell-connect如果配置正确minibuffer 会提示连接成功。然后执行M-x agent-shell-open打开交互界面输入一句话测试一下。提示如果连接失败先检查 agent 是否在运行再检查端口是否被占用最后检查 Emacs 的配置有没有语法错误。我遇到过因为一个括号没闭合导致整个配置加载失败的情况排查了半天。4.2 用 agent-shell 辅助代码审查的完整流程代码审查是agent-shell的一个典型应用场景。假设你刚写完一个函数想让它帮你看看有没有问题。操作流程是这样的选中你要审查的代码区域。按下你绑定的快捷键比如C-c C-s。在弹出的 prompt 里输入你的要求比如“帮我检查这段代码的类型标注和边界条件”。agent 会读取你选中的代码结合上下文给出建议。你可以继续追问比如“第二个问题能详细说说吗”或者“帮我改一下”。我实际用下来agent 在几个方面特别有用。第一发现遗漏的边界条件。人写代码的时候容易忽略一些极端情况agent 会提醒你。第二检查类型标注的一致性。Python 的类型标注有时候会写错agent 能发现。第三建议更地道的写法。同样的逻辑agent 可能会给出更简洁或更高效的实现方式。# 审查前的代码 def process_items(items): result [] for item in items: if item 0: result.append(item * 2) return result # agent 建议的改进 def process_items(items: list[int]) - list[int]: Process positive items by doubling them. return [item * 2 for item in items if item 0]这个例子比较简单但能看出 agent 的建议包括添加类型标注、添加文档字符串、用列表推导式简化代码。这些改进不一定都要采纳但作为参考很有价值。4.3 让 agent 参与文档写作与内容生成除了代码agent-shell在文档写作方面也很实用。我写技术文档的时候经常让 agent 帮我做几件事。第一根据代码生成文档草稿。选中一个函数让 agent 根据函数签名和实现生成文档字符串。第二润色段落。选中一段文字让 agent 帮我改得更通顺、更专业。第三生成示例。让 agent 根据文档内容生成使用示例。;; 让 agent 根据当前函数生成文档 (defun my-agent-generate-docstring () Generate docstring for the function at point. (interactive) (let ((func-code (buffer-substring-no-properties (beginning-of-defun) (end-of-defun)))) (agent-shell-send-message (format 请为以下函数生成文档字符串\n\n%s func-code))))这个函数我用了很久写 Python 的时候特别方便。选中一个函数执行这个命令agent 就会生成一个符合 Google 风格或 NumPy 风格的文档字符串。我一般会再手动调整一下但草稿质量已经很高了省了不少时间。内容生成方面agent-shell可以帮你写 commit message、生成 changelog、起草邮件回复。这些任务的共同点是有明确的上下文当前修改的文件、最近的提交记录、邮件往来有相对固定的格式AI 做起来很擅长。5. 常见问题与排查技巧实录5.1 连接类问题排查连接问题是新手最容易遇到的。表现通常是执行连接命令后没有反应或者提示连接失败或者连接上了但发消息没响应。排查思路是这样的。第一步确认 agent 后端是否正常运行。用curl或者telnet测试端口是否可达。第二步检查 Emacs 的配置是否正确。特别是地址和端口有没有写错有没有被其他配置覆盖。第三步查看 Emacs 的*Messages*buffer里面通常会有错误信息。第四步如果 agent 有日志查看 agent 端的日志看看请求有没有到达。我遇到过一个比较隐蔽的问题agent 正常运行端口也对但 Emacs 就是连不上。后来发现是 Emacs 的url-request-extra-headers里有一个全局配置给所有请求加了一个 header导致 agent 拒绝了请求。这种问题只能通过看日志和逐步排查来解决。问题现象可能原因解决方法连接超时agent 未启动或端口错误检查 agent 状态和端口配置连接被拒绝防火墙或绑定地址限制检查 agent 绑定地址和防火墙规则连接成功但无响应协议不匹配或认证失败检查 ACP 版本和认证配置间歇性断开网络不稳定或超时设置过短调整超时参数或检查网络5.2 上下文传递异常的处理上下文传递异常的表现是agent 收到的内容跟你预期的不一样或者 agent 说“我看不到你的代码”或者 agent 基于错误的上下文给出建议。这个问题的根源通常在于上下文获取函数的行为不符合预期。agent-shell默认的上下文获取逻辑可能不适用于所有场景。比如在org-mode里它可能发送整个文档而不是当前段落在prog-mode里它可能发送整个文件而不是当前函数。解决方法是自定义上下文获取函数。你可以根据 major mode 或者文件类型来决定发送什么内容。我一般会写一个 dispatch 函数根据当前模式调用不同的获取逻辑。(defun my-agent-context () Get context based on current major mode. (cond ((derived-mode-p prog-mode) (my-agent-get-function-context)) ((derived-mode-p org-mode) (my-agent-get-subtree-context)) ((derived-mode-p text-mode) (my-agent-get-paragraph-context)) (t (buffer-substring-no-properties (point-min) (point-max)))))注意发送整个 buffer 作为上下文可能会导致 token 消耗过大响应变慢甚至超出 agent 的上下文窗口限制。建议根据实际需要控制发送内容的长度。5.3 性能优化与资源管理agent-shell用久了之后可能会遇到性能问题。表现包括Emacs 变卡、响应变慢、内存占用增加。这些问题通常跟会话历史积累、上下文发送过多、流式输出处理不当有关。优化措施有几个方向。第一定期清理会话历史。不需要的会话及时关闭重要的会话保存到文件后从内存中移除。第二控制上下文长度。不要每次都发送整个文件只发送必要的部分。第三调整流式输出的刷新频率。如果 agent 输出很快Emacs 频繁刷新会导致卡顿可以适当降低刷新频率。;; 限制会话历史长度 (setq agent-shell-max-history 50) ;; 控制上下文最大字符数 (setq agent-shell-max-context-chars 4000) ;; 调整流式输出刷新间隔秒 (setq agent-shell-stream-refresh-interval 0.1)我自己的经验是把agent-shell-max-context-chars设置在 3000 到 5000 之间比较合适。太小了 agent 看不到足够的信息太大了响应变慢。这个值可以根据你的 agent 模型的能力来调整模型上下文窗口大的可以设大一点。还有一个容易被忽略的点Emacs 的 GC 策略。agent-shell频繁创建和销毁对象可能会触发频繁的垃圾回收导致卡顿。可以适当调大gc-cons-threshold减少 GC 频率。(setq gc-cons-threshold (* 100 1024 1024)) ; 100MB这个设置会让 Emacs 在内存占用达到 100MB 时才触发 GC对于现代机器来说完全没问题但能显著减少卡顿。5.4 常见问题速查表问题类别具体表现排查方向解决方案连接失败无法建立连接网络、端口、配置检查 agent 状态和配置上下文错误agent 看不到代码上下文获取函数自定义上下文策略响应缓慢等待时间长上下文过长、网络延迟减少上下文、优化网络Emacs 卡顿操作不流畅GC 频繁、流式刷新过快调整 GC 阈值和刷新间隔会话混乱上下文串了会话管理配置检查会话隔离设置输出乱码显示异常编码问题统一使用 UTF-86. 进阶玩法与工作流整合6.1 多 agent 协作的尝试agent-shell支持同时连接多个 agent这个功能我最近才开始用但已经发现了一些有意思的玩法。比如我可以让一个 agent 负责代码生成另一个 agent 负责代码审查。生成完之后直接发给审查 agent形成一个小型的流水线。配置多个 agent 的方式是定义多个连接配置然后通过会话切换来使用不同的 agent。每个 agent 可以有不同的专长比如一个擅长 Python一个擅长 JavaScript一个擅长文档写作。(setq agent-shell-agents ((:name coder :endpoint http://localhost:8080 :specialty code) (:name reviewer :endpoint http://localhost:8081 :specialty review) (:name writer :endpoint http://localhost:8082 :specialty doc)))这种多 agent 协作的模式还在早期探索阶段实际用下来有一些挑战比如 agent 之间的上下文同步、任务分配的策略、结果合并的逻辑。但方向是有价值的特别是对于复杂任务单个 agent 可能不如多个专精 agent 协作效果好。6.2 与项目工具链的深度集成agent-shell最有价值的扩展方向是跟项目工具链集成。比如跟测试框架集成让 agent 根据测试失败的信息自动生成修复建议。跟版本控制集成让 agent 根据 diff 生成 commit message。跟构建系统集成让 agent 分析构建错误。我自己的配置里有一个函数在测试失败时自动把失败信息发给 agent让它分析原因并给出修复建议。这个函数挂在compilation-finish-functions上每次编译或测试结束都会触发。(defun my-agent-analyze-test-failure (buffer msg) Send test failure info to agent for analysis. (when (string-match-p FAILED\\|ERROR msg) (with-current-buffer buffer (let ((failure-info (buffer-substring-no-properties (point-min) (point-max)))) (agent-shell-send-message (format 测试失败了请分析原因并给出修复建议\n\n%s failure-info)))))) (add-hook compilation-finish-functions #my-agent-analyze-test-failure)这个集成用起来很顺手。以前测试失败要自己看日志、分析原因、想修复方案现在 agent 会先给一个分析我在此基础上判断和调整效率提升明显。6.3 自定义工具函数的开发agent-shell允许你定义自定义工具函数让 agent 可以调用。这个功能打开了很大的想象空间。你可以把日常操作封装成函数让 agent 帮你执行。比如“格式化当前文件”、“运行当前测试”、“部署到测试环境”。定义工具函数的方式通常是注册一个函数名和对应的实现agent 在需要的时候会调用。具体 API 可以参考项目的文档不同版本的实现可能略有差异。;; 注册一个自定义工具函数 (agent-shell-register-tool format-current-file Format the current file using the projects formatter. (lambda () (when (derived-mode-p python-mode) (pyvenv-activate (project-root (project-current))) (python-black-format-buffer))))这个功能的关键在于安全性。让 agent 调用你的函数意味着 agent 可以执行任意操作包括修改文件、运行命令。所以一定要控制好权限只注册那些安全的、幂等的函数。我一般只注册只读操作或者容易回滚的操作破坏性的操作还是手动执行。7. 我踩过的坑和实际使用体会配置agent-shell的过程中我踩过不少坑这里分享几个印象深刻的。第一个坑是上下文发送策略没调好。刚开始用默认配置发现 agent 经常看不到我选中的代码或者看到的代码不完整。后来发现是默认的上下文获取函数在某些 major mode 下行为不符合预期。改成自定义函数之后就好了。这个问题的教训是不要假设默认配置适合你的工作流该改就改。第二个坑是会话历史积累导致 Emacs 变慢。用了一段时间之后Emacs 开始卡顿特别是切换 buffer 的时候。排查发现是agent-shell的会话历史没有清理积累了几百条记录。后来设置了自动清理策略问题解决。建议定期检查会话历史不需要的及时清理。第三个坑是流式输出导致光标跳动。agent 输出的时候光标会跟着输出位置移动导致我无法同时做其他操作。后来发现可以配置输出到单独的 buffer或者关闭流式输出问题解决。这个看个人习惯我后来还是保留了流式输出但把输出 buffer 放在单独的窗口不影响主编辑区。实际使用下来agent-shell给我带来的最大价值是减少了上下文切换的成本。以前写代码遇到问题要切到浏览器、描述问题、复制代码、等待回复、复制答案、切回来、粘贴、调整。现在整个过程都在 Emacs 里完成流畅很多。虽然单次操作节省的时间不多但一天下来积累的效果很明显。另一个体会是agent 的建议不能全信。AI 有时候会给出看似合理但实际上有问题的建议特别是在涉及业务逻辑、边界条件、性能优化的时候。我的做法是把 agent 当成一个“有经验的同事”它的建议作为参考最终决策还是自己做。这样既能利用 AI 的效率又能避免被误导。最后分享一个小技巧给 agent 写清楚你的要求。同样的代码你说“帮我看看”和“帮我检查类型标注和边界条件”得到的回复质量差别很大。花几秒钟把要求写清楚能省很多来回沟通的时间。这个技巧适用于所有 AI 辅助工具不只是agent-shell。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询