Deep Agents Code 开发指南:从本地环境搭建、调试到 LangSmith 追踪与 CSS 热重载

原创2026-09-09 19:19:341,916 阅读
文章标签:人工智能AI AgentAgent 框架工具调用代码智能体

Deep Agents Code 开发指南:从本地环境搭建、调试到 LangSmith 追踪与 CSS 热重载

导读

本文基于 libs/code/DEVELOPMENT.md 编写,系统讲解 deepagents-code(终端编码 Agent,安装后提供 dcode / deepagents-code 两个命令)的本地开发全流程:包括基于 uv 的环境引导与 CI 级检查、LangSmith 追踪项目的开发/生产隔离、双进程架构下的日志排查、独立于发布版本的 dcode-dev 本地可编辑安装,以及借助 Textual devtools 实现 CSS 热重载。读完本文,你将能够独立 clone 该仓库、跑通 make check 全量检查、快速定位"启动崩溃"与"客户端运行异常"两类故障,并为 UI 开发建立高效的即时反馈工作流。

面向新读者:正式动手前,建议先阅读 libs/code/ARCHITECTURE.md,其中给出了 TUI、langgraph dev 服务子进程与 Agent 图三者的高层关系图,与本文的调试章节互相印证。

快速开始:用 uv 引导本地环境

deepagents-code 使用 uv 管理环境与依赖。若尚未安装 uv,先执行官方安装脚本:

curl -LsSf https://astral.sh/uv/install.sh | sh

然后 clone 仓库并引导 libs/code 包。make bootstrap 会完成三件事:创建虚拟环境、安装测试依赖、安装本地 git hooks(pre-commit 与 commit-msg),使推送前在本地就能跑与 CI 一致的检查:

git clone https://github.com/langchain-ai/deepagents.git
cd deepagents/libs/code
make bootstrap

如果只想同步依赖、不想安装 hooks,用 uv sync --group test 代替即可。注意 libs/code/pyproject.toml 中的 [dependency-groups] test 组除了 pytest 全家桶,还包含 textual-dev(供本文末尾的 CSS 热重载使用)、ruff、ty、hatchling 等开发工具。

在本地 checkout 中启动 TUI:

uv run deepagents-code

uv run 使用以 editable 方式安装包的项目环境,因此源码修改在下次启动时即生效。若希望得到一个持久化、且与已发布版本互不干扰的 dcode-dev 命令,请使用下文"本地开发安装"一节的方式。

测试与静态检查:make 目标一览

所有命令均应在 libs/code 目录下执行。打开 PR 前,务必运行完整的本地检查套件:

make check

make check 依次执行 lint、导入检查、单元测试,以及三类仓库级门禁:extras 与依赖同步校验(check_extras_sync.py)、pyproject.toml 与 _version.py 版本一致性校验、uv.lock 是否过期校验,最后还有一个对 workspace SDK 固定版本的 advisory 检查(见 libs/code/Makefile)。全部通过会打印 ✅ All local CI checks passed!。

迭代过程中可按需运行定向检查:

# 单元测试(禁止联网,pytest 通过 --disable-socket 强制离线)
make test

# 单个测试文件
make test TEST_FILE=tests/unit_tests/test_specific.py

# 集成测试(允许联网,默认 30 秒超时)
make integration_test
# 自动格式化(ruff format + ruff check --fix)
make format

# Lint + 类型检查(ruff、ty、commands-catalog 一致性检查、cwd 检查)
make lint

其中 make lint 实际执行四步(见 libs/code/Makefile):ruff check、ruff format --diff、ty check 类型检查、generate_commands_catalog.py --check(校验 COMMANDS.md 与斜杠命令注册表一致)以及 check_process_cwd.py 进程工作目录检查。运行 make help 可查看全部目标,其他常用目标还包括 test_watch(ptw 监听重跑)、coverage(XML 覆盖率报告)、benchmark 与 bench(CodSpeed 基准)等。

LangSmith 追踪:把开发流量与生产项目隔离

当启用 LangSmith 追踪且存在 LANGSMITH_API_KEY 时,deepagents-code 会把自己的 Agent 运行轨迹上报到 LangSmith。需要特别留意:仅设置 API Key 对由环境注入的 key 是不够的,还需要设置 LANGSMITH_TRACING=true。通过 /auth 界面保存的 key 会自动开启追踪,除非显式退出(例如 DEEPAGENTS_CODE_LANGSMITH_TRACING=false)。

默认情况下这些运行轨迹落在 deepagents-code 项目,但团队会把共享运行路由到一个 GA 项目(shared-deepagents-code),该项目由 LangSmith Engine 监控,对可疑问题触发高优先级 Slack 告警。

开发时严禁指向 GA 项目。 日常开发会产生失败用例、半成品分支与实验性运行,Engine 会把它们标记为问题——这些噪音会淹没对生产项目真正重要的告警,浪费团队分类时间。开发与生产运行应使用不同项目(这也符合 LangSmith 将开发/生产环境拆分到独立项目的最佳实践)。

通过 DEEPAGENTS_CODE_LANGSMITH_PROJECT 将本地运行路由到开发专用项目(该变量只覆盖 Agent 自身的追踪,不会改动你 shell 中面向用户代码的 LANGSMITH_PROJECT):

# 共享的开发桶,或你自己的私人项目——只要不是 GA 项目即可
export DEEPAGENTS_CODE_LANGSMITH_PROJECT=shared-deepagents-code-dev
uv run deepagents-code

同样要把该覆盖设置应用到本地开发安装(dcode-dev),而不只是临时 uv run 会话。持久化方式有两种:在配置文件 [tracing] 段设置 tracing.langsmith_project,或通过 /auth 界面设置。启动欢迎页(splash)和 /trace 命令都会显示当前运行写入的项目名——在进行会产生大量噪音的工作前,务必确认它不是 GA 项目。

当为 Engine 接入新的追踪项目时,先明确该项目性质:生产/GA 应用值得高优先级告警,而 staging 或活跃开发项目应使用更宽松的阈值(或干脆不接入 Engine),避免产生误报。

从源码看,DEEPAGENTS_CODE_LANGSMITH_PROJECT 等变量的规范定义集中在 libs/code/deepagents_code/_env_vars.py,该文件是所有 DEEPAGENTS_CODE_* 环境变量的唯一权威注册表,并有 tests/unit_tests/test_env_vars.py 漂移检测测试保证源码中不出现裸字符串字面量。

关于服务子进程的追踪配置约束

需要注意:一个服务子进程在其整个生命周期内只保留第一个 workspace 的追踪配置。共享该服务器的 workspace 必须使用匹配的追踪凭据、项目、端点、profile 选择器、追踪开关与脱敏策略。配置冲突的 workspace 在其设置影响缓存或并发运行之前就会被拒绝——此时请为该 workspace 启动独立服务器。如需更改服务器追踪配置,须重启服务器。

调试:双进程架构下的日志分流

Deep Agents Code 以两个进程运行:你交互的 Textual TUI(客户端) 与承载 Agent 图的 langgraph dev 子进程(服务端)。两者各自写各自的日志,而一个开关同时打开两者:

cd libs/code
export DEEPAGENTS_CODE_DEBUG=1
uv run deepagents-code

三个核心环境变量的行为如下表:

变量 作用
DEEPAGENTS_CODE_DEBUG 总开关。保留服务子进程日志(退出时向 stderr 打印其路径),并为客户端挂载 DEBUG 文件 handler。Truthy:1/true/yes/on(不区分大小写);Falsy:0/false/no/off/空/未设置。
DEEPAGENTS_CODE_DEBUG_DIRECTORY=<path> 覆盖客户端日志目录(默认 /tmp/deepagents_debug)。每个线程写入 <thread-id>.log。仅在 DEEPAGENTS_CODE_DEBUG 为 truthy 时生效;不影响服务子进程日志。
DEEPAGENTS_CODE_DEBUG_FILE=<path> 已废弃的兼容性覆盖。当 DEEPAGENTS_CODE_DEBUG_DIRECTORY 与 [debug].directory 均未设置时,按线程日志使用该路径的父目录。现有的 [debug].file 配置行为相同。

源码层面,truthy/falsy 的解析逻辑在 libs/code/deepagents_code/_env_vars.py 的 is_env_truthy / classify_env_bool:"0" 或 "false" 不会被 bool() 误判为开启。日志文件与目录的创建会收紧为仅属主可访问(POSIX 下目录 0o700、文件 0o600,Windows 下通过替换 DACL 实现),并拒绝符号链接(默认目录位于可写的临时目录,若不拒绝,植入的 symlink 可能把捕获的 MCP stderr 重定向到攻击者指定的文件),详见 libs/code/deepagents_code/_debug.py。

按症状选择要看哪份日志:

症状 应看日志 默认位置
应用启动即崩溃(单行失败横幅) 服务子进程日志——真正的 traceback 在其中 $TMPDIR/deepagents_server_log_*.txt
应用已启动但行为异常(UI、模型调用、斜杠命令) 客户端应用日志——deepagents_code 的 DEBUG 输出 /tmp/deepagents_debug/<thread-id>.log

启动崩溃 → 看服务子进程日志

TUI 只显示一行横幅,真正的异常位于子进程合并的 stdout/stderr 中。获取步骤:

  1. 带调试开关重新运行(见上)。应用退出、终端恢复后,日志被保留,其路径以 Server log preserved at: ... 打印到 stderr。

  2. 打开最新的日志。在 macOS 上 tempfile 解析为 $TMPDIR(/var/folders/.../T/ 下的路径):

    # 最新在前
    ls -lt ${TMPDIR:-/tmp}/deepagents_server_log_*.txt | head -5
    
    # 或者一边复现崩溃一边实时跟踪最新日志
    tail -F "$(ls -t ${TMPDIR:-/tmp}/deepagents_server_log_*.txt | head -1)"
    
  3. 搜索 Failed to initialize server graph。其下方的 traceback 会点名具体失败原因——MCP 配置校验、sandbox 初始化、模型解析、subagent 加载等。该行之上的内容都是 uvicorn/lifespan 的收尾输出,可忽略。

客户端问题 → 看应用日志

针对应用启动后才出现的问题,在另一个终端实时跟踪客户端日志并复现:

tail -f /tmp/deepagents_debug/<thread-id>.log

如需把日志写到别处,同时 export DEEPAGENTS_CODE_DEBUG_DIRECTORY=<path>。每个线程拥有独立的追加写入文件,应用内切换线程会切换当前日志文件。目录与文件均被收紧为仅属主可访问、拒绝符号链接;若任一步骤无法保证安全,则不会挂载文件 handler 并向 stderr 输出警告——此时请改用应用内 Debug Console。

关于敏感信息的重要提醒:stdio MCP 服务器的 stderr 会以 DEBUG 级别捕获到此日志中。每条记录占一行、上限 4096 字符;Unicode C 类别字符(含控制字符与格式字符)会被移除,ANSI 转义序列的 ESC 字节被移除但其余部分保留为字面文本,因此日志并非完全没有转义残留。文本来自服务器,可能包含凭据或其他敏感值。仅在接受该风险时启用 DEBUG 日志,且不要分享日志文件。

应用内 Debug Console(Ctrl+\)

在会话内按 Ctrl+\(或运行隐藏命令 /debug)可切换一个只读的 Debug Console 浮层(实现位于 libs/code/deepagents_code/tui/widgets/debug_console.py)。它展示两大部分:

  • 会话/运行时快照:版本、模型、线程、cwd、auto-approve、sandbox、MCP 服务器、token 用量、调试日志路径等,且支持逐行点击复制;
  • 近期 deepagents_code.* 日志记录的实时尾部:支持按日志级别过滤(All / min:DEBUG… / only:DEBUG… 等组合,DEBUG 级别选项仅在启用调试时出现),并按 Ctrl+L 清屏(缓冲区继续累积)、c 复制可见行。

关键实现细节:日志尾部由一个始终开启的内存环形缓冲区提供(_debug_buffer.install_log_buffer,在 libs/code/deepagents_code/_debug_buffer.py 中实现,挂载于 __init__.py 的包级 logger 上),因此无需 DEEPAGENTS_CODE_DEBUG 也能工作——开启该开关的作用是把捕获级别提升到 DEBUG 并追加上述文件 handler。缓冲区按日志级别分桶保留(每级别默认 1000 条,DEFAULT_CAPACITY),使 DEBUG 洪峰不会挤掉稀少的 INFO/WARNING/ERROR 记录;非标准级别名称共享 _other 桶,保证桶数量有界。每次刷新 tick(500ms)通过绝对发射序号增量拉取记录,跨级别仍保持时序一致。

本地开发安装:独立的 dcode-dev

本地开发安装提供持久的 dcode-dev 命令,直接启动你的 checkout。它位于专用的可编辑 venv(~/.local/share/dcode-dev),并符号链接到 ~/.local/bin/dcode-dev,可与已发布的 dcode 并存而不互相干扰:

  • dcode / deepagents-code —— 已发布工具,经 curl -LsSf https://langch.in/dcode | bash 安装脚本安装;
  • dcode-dev —— 你的本地 checkout。

这样你可以对比发布版与本地版的行为差异,并在 checkout 出问题时回退到已知良好的构建。无论哪种方式,专用 venv 都能把开发二进制的依赖实验与仓库锁定的 uv sync 环境隔离。

设置

~/.local/bin 必须在 PATH 上才能解析符号链接(uv tool install 会自动添加自己的 shim 目录,但手写 symlink 不会)。将 <repo> 替换为你的本地 checkout 路径:

# 1. 为开发二进制创建隔离 venv
uv venv ~/.local/share/dcode-dev --python 3.13

# 2. 以 editable 方式安装你的 checkout
uv pip install --python ~/.local/share/dcode-dev/bin/python -e <repo>/libs/code

# 3. 以 dcode-dev 暴露到 PATH
ln -sf ~/.local/share/dcode-dev/bin/dcode ~/.local/bin/dcode-dev

--python 3.13 仅为示例——任何满足包 requires-python(当前为 >=3.12,<4.0,见 libs/code/pyproject.toml)的解释器都可以;省略该参数则让 uv 自行选择。

为什么用 uv venv + uv pip install -e,而不是 uv sync 或 uv tool install --editable? 这会在 workspace 锁定环境之外构建一个隔离 venv,使开发二进制可以按需重新解析依赖,而不打扰已发布的工具或仓库的 uv.lock。(这里的 uv pip 与 uv venv 是 uv 的一等子命令,而非裸 pip。)

更新

当 libs/code/pyproject.toml 中的依赖约束变化时,刷新开发 venv:

uv pip install --python ~/.local/share/dcode-dev/bin/python -e <repo>/libs/code --upgrade

验证

确认命令解析与 editable 导入正常(以下 dcode 检查假定已发布工具已按上述方式另行安装):

which dcode
which dcode-dev
dcode --version
dcode-dev --version
~/.local/share/dcode-dev/bin/python -c 'import deepagents_code; print(deepagents_code.__file__)'

Textual devtools:CSS 热重载开发

完成快速开始后,可借助 Textual 的 devtools 控制台,在开发过程中获得 CSS 热重载与实时的 self.log() 输出。

先创建一次开发包装脚本:

cat > /tmp/dev_deepagents.py << 'PYEOF'
"""Dev wrapper to run Deep Agents Code with textual devtools."""
import sys
sys.argv = ["deepagents"] + sys.argv[1:]

from deepagents_code.main import cli_main
cli_main()
PYEOF

两个命令均从 libs/code 运行:

终端 1 —— devtools 控制台:

uv run --group test textual console

终端 2 —— 带实时重载的 TUI:

uv run --group test textual run --dev /tmp/dev_deepagents.py

编辑任意 .tcss 文件并保存——变更立即生效。widget 代码中的任意 self.log() 调用都会显示在控制台中。

控制台选项

  • textual console -v —— 详细模式,显示全部事件(按键、鼠标等);
  • textual console -x EVENT —— 排除嘈杂的事件组;
  • textual console --port 7342 —— 自定义端口(需给 textual run 传匹配的 --port)。

为什么需要包装脚本?

textual run --dev 负责处理 devtools 连接,但它需要在项目虚拟环境内运行才能导入 deepagents_code。包装脚本正是为了弥合这一鸿沟——uv run --group test textual run --dev 确保 textual-dev(来自 test 依赖组)与 deepagents_code 在同一个环境中可用。

进一步阅读

登录后查看全文
deepagents