ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Deep Agents Code(dcode)架构解析:Textual 终端客户端 + 回环 LangGraph 服务器 + ACP 双运行时设计

Deep Agents Code(dcode)架构解析:Textual 终端客户端 + 回环 LangGraph 服务器 + ACP 双运行时设计 Deep Agents Codedcode架构解析Textual 终端客户端 回环 LangGraph 服务器 ACP 双运行时设计【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagentsdeepagents-code命令名dcode是构建在deepagentsSDK 之上的参考型终端编码 Agent 产品它把 SDK 的 Agent 编排能力与终端体验、持久化会话、工具、技能和可选沙箱执行整合在一起。本文基于 openwiki/architecture/code-agent.md 及其引用的源码完整拆解 dcode 的普通客户端-服务器与ACP stdio两条刻意分离的运行时路径说明启动装配、配置交接、工作区绑定、图构建与清理机制。读完你将掌握 dcode 进程模型的边界划分、DEEPAGENTS_CODE_SERVER_*环境变量协议、持久化工作区绑定的校验逻辑以及 ACP 模式下为什么不启动 langgraph dev、不使用 RemoteAgent。一个产品两条刻意分离的运行时路径dcode 是deepagentsSDK 的batteries-included参考实现SDK 提供 Agent harnessdcode 展示如何把 harness 与终端体验、持久化、工具、技能和可选沙箱组合成一个可用的编码 Agent 产品。仓库中的 ARCHITECTURE.md 给出了大图产品被切成终端客户端和Agent 服务器两个运行半区——客户端负责呈现与输入收集服务器负责运行编码 Agent 图、连接模型、工具、内存、技能和 backend。与一个大进程里什么都干的方案不同dcode 在进程模型上就有两条有意分开的路径见 code-agent.md普通交互模式与 headless非交互模式运行一个终端客户端 一个由客户端自己拥有的本地langgraph dev服务器进程。客户端拥有呈现、输入与审批approval服务器拥有模型、图、工具、内存、技能、backend 与 checkpoint。dcode --acp模式在 stdio 上运行一个进程内 ACP 服务器。它构建本地会话图既不启动langgraph dev也不使用RemoteAgent。关键判断在于这不是一种可以互换的传输层而是一条所有权边界ownership boundary。对普通服务器路径的改动必须独立地针对 ACP 路径重新评估两条路径共享底层 SDK harness但进程拓扑、配置输入、checkpointer 生命周期完全不同。普通客户端-服务器运行路径交互与 headless 的同一套服务端运行时交互模式使用 Textual 应用负责渲染与用户交互headless 模式复用同一个服务器运行时和同一个RemoteAgent只为单个用户任务服务——它把 UI 替换为 stdout 流式输出--quiet会抑制工具与文件操作提示让 stdout 只包含响应文本见 code-agent.md 与 non_interactive.py 对应的行为。一次请求在两种模式下遵循相同形状ARCHITECTURE.md客户端接收用户输入 → 发送给 Agent 服务器 → 服务器运行 Agent 并流式返回事件 → 客户端渲染事件并收集需要的人工响应 → 会话状态被持久化以便后续继续。完整时序普通本地路径的完整流程如下该图仅描述普通路径ACP 单独描述执行前的工作区绑定让服务器端图选择具备权威性启动装配项目上下文、临时工作区与配置交接start_server_and_get_agent 的启动顺序server_manager.py 中的start_server_and_get_agent是普通路径的启动入口它依次完成捕获项目上下文用显式cwdProjectContext.from_user_cwd(Path(cwd))或捕获当前项目上下文_capture_project_context()预检显式 MCP 配置在 spawn 任何子进程之前调用_preflight_validate_mcp_config校验--mcp-config路径的合法性解析ServerConfig通过ServerConfig.from_cli_args(...)把所有 CLI 参数归一化为一个类型化配置脚手架临时 LangGraph 工作区tempfile.mkdtemp(prefixdeepagents_server_)创建临时目录_scaffold_workspace在其中生成pyproject.toml、langgraph.json和一个生成的 checkpointer 模块启动服务器ServerProcess(host, port, ...)server.start()server.wait_for_graph_ready(agent)等待图就绪返回已配置的 RemoteAgent创建RemoteAgent(url, graph_nameagent)调用agent.set_workspace(cwd, session_workspace_claim, config_fingerprint)后返回(agent, server, None)。临时工作区里发生了什么脚手架生成的 checkpointer 模块有一个精妙之处见 code-agent.md 的 Startup, generated workspace, and configuration handoff它从环境变量读取应用会话数据库路径并产生AsyncSqliteSaver而不是把路径硬编码进生成的源码。这保证了临时目录里的生成文件不携带任何机器相关的绝对路径。生成的图引用是deepagents_code.server_graph:make_graph见 server_graph.py。当使用这个内置引用时langgraph.json还会追加 dcode 的offload HTTP 应用并启用自定义路由鉴权而自定义图引用custom graph reference不会提供/offload服务——这也是客户端在aoffload中把 404 明确报告为This server does not provide dcodes /offload operation的原因见 remote_client.py。本地启动默认绑定127.0.0.1和端口0由操作系统挑选临时端口ephemeral port而不是占用langgraph dev惯例的 2024 端口server_manager.py中port: int _EPHEMERAL_PORT。DEEPAGENTS_CODE_SERVER_*一份共享的配置模式客户端通过DEEPAGENTS_CODE_SERVER_*环境变量把解析后的启动配置导出给服务器子进程。ServerConfig 是一个 frozen dataclass其文档字符串明确了设计意图应用 spawn 一个langgraph dev子进程并通过带DEEPAGENTS_CODE_SERVER_前缀的环境变量传递配置这个模块提供双方共享的单一ServerConfig变量集合、序列化格式和默认值都只在一处定义。应用用to_env()写入服务器图用from_env()读回。to_env()与from_env()是客户端/服务器共享的同一套 schemato_env、from_env序列化、默认值与变量集合在一处维护。核心字段包括环境变量后缀含义默认值MODEL模型规格串如anthropic:claude-opus-4-7None由服务器选默认NoneSUMMARIZATION_MODEL仅用于上下文压缩摘要的模型None复用主模型NoneMODEL_PARAMS传给 chat model 构造器的额外 kwargstemperature、max_tokens 等JSON 编码NoneMAX_RETRIES显式--max-retriesNoneASSISTANT_ID服务器上调用的 Agent 图标识DEFAULT_AGENT_NAMESYSTEM_PROMPT系统提示词覆盖None用默认NoneAUTO_APPROVE是否自动批准所有工具调用falseINTERRUPT_SHELL_ONLY仅 shell 工具走 HITL其余走中间件校验falseSHELL_ALLOW_LISTshell 命令白名单逗号分隔None禁用白名单NoneINTERACTIVE是否交互会话trueENABLE_SHELL/ENABLE_ASK_USER/ENABLE_MEMORY/ENABLE_SKILLS各子系统开关true/false/true/trueENABLE_INTERPRETER是否启用CodeInterpreterMiddlewarejs_eval本地模式专属falseINTERPRETER_PTCinterpreter.ptc的调用级覆盖safe/all/工具名列表NoneALLOW_FS_TOOLSFilesystemMiddleware的文件系统工具白名单JSON 数组必须包含read_fileNone全部RUBRIC_MODEL/RUBRIC_MAX_ITERATIONS评分中间件的 grader 模型与迭代数NoneAUTO_CLASSIFIER_MODELAuto 模式的分类器模型None回退链RECURSION_LIMIT主 Agent 的 LangGraphrecursion_limit图步骤预算None由运行时配置解析SANDBOX_TYPE/SANDBOX_ID/SANDBOX_SNAPSHOT_NAME/SANDBOX_SETUP沙箱后端、复用 ID、快照/蓝图名、setup 脚本NoneCWD/PROJECT_ROOT用户的原始工作目录与检测到的项目根NoneMCP_CONFIG_PATH/NO_MCP/TRUST_PROJECT_MCPMCP 配置路径与信任控制None/false/NoneTRUST_PROJECT_EXTENSIONS/EXTENSION_PATHS项目 Python 扩展信任与单次运行扩展false/[]有几个值得展开的细节布尔值约定_read_env_bool使用true/false大小写不敏感缺失回退默认值JSON 读取失败即关闭fail closed_read_env_json对格式错误的 JSON 直接抛ValueErrorALLOW_FS_TOOLS的安全语义_read_env_allow_fs_tools在服务器子进程内执行——该变量是安全控制任何无法识别的形状[]、未知工具名都必须抛错关闭而非退化为不受限文件系统ServerConfig.__post_init__还强制要求列表非空且包含read_filepost_init值校验shell_allow_list非空、rubric_max_iterations/recursion_limit必须为正整数、不能是布尔值这些不变量都在__post_init__集中维护。配置解析层级解析器数字越小的 rank 越优先managed policy受管配置→ CLI 参数 → 保留的 reload 值 → 环境变量 → 用户config.toml→ 类型化默认值见 configuration/resolver.py 与 config-layering 概念。配置还有一个单次生成generation模型ARCHITECTURE.md配置文件被读取进一个进程范围的共享 generation首次读取构建后复用运行期间编辑config.toml不会影响读者直到 generation 前进in-app 写默认配置路径会刷新 generation或/reload。环境层始终是活性的——EnvProvider在解析时读取os.environ因为进程在 dotenv 引导和每次 cwd 切换时会改变它。子进程环境即安全边界start_server_and_get_agent走完配置后_apply_server_config(config)把DEEPAGENTS_CODE_SERVER_*变量写入子进程环境。子进程环境同时是一道安全边界启动敏感的继承变量包括PYTHONPATH在服务器解释器启动前会被剥离原始的PYTHONPATH仅通过独立通道转发给审批门控的 shell 执行使用子进程 profile 被钉在客户端启动 profile 上见 code-agent.md。远程边界与持久化工作区身份RemoteAgentRemoteGraph 的薄适配层remote_client.py 中的RemoteAgent是 LangGraphRemoteGraph的薄 dcode 适配器。底层客户端负责HTTP/SSE 解析、messages-tuple流模式协商、命名空间提取和中断检测。dcode 在此基础上归一化线程 ID把流式返回的消息字典转换为 Textual 适配器需要的消息对象让状态快照保持服务器的序列化形式不做反序列化见aget_state的实现提供aensure_thread在 LangGraph dev 服务器中checkpoint 持久化与 HTTP 线程注册是分离的——服务器重启后磁盘上可能仍有 checkpoint 状态但 live 线程行不存在该方法用if_existsdo_nothing做幂等的 HTTP 侧注册aensure_thread。首次使用前的工作区绑定在第一次使用某个线程之前RemoteAgent会把它自己的 cwd、工作区策略与配置指纹 POST 到/dcode/threads/{thread_id}/workspace并缓存返回的描述符abind_workspace/_request_workspace见 remote_client.py。它还单独确保远程 HTTP 线程记录存在——因为持久化的 checkpoint 数据可能在没有 live 线程行的服务器重启后存活。服务器侧做三件事workspace.py规范化_canonical_directory要求绝对路径、禁止..穿越、resolve(strictTrue)且必须是目录workspace.py计算身份与资源键workspace_id canonical_fingerprint({cwd, project_root})resource_key canonical_fingerprint({workspace_id, config_fingerprint})resolve_workspace——资源键把目录身份和资源策略指纹绑定在一起成为运行时的不可变选择依据原子持久化_bind用BEGIN IMMEDIATEINSERT OR IGNORE把绑定写入会话 SQLite 的dcode_thread_workspaces表workspace.py列包含thread_id、schema_version、workspace_id、cwd、project_root、generation、resource_key、config_fingerprint、workspace_config_json。绑定不可变冲突即拒绝绑定是不可变的后续的 bind 或执行上下文必须匹配该工作区的workspace_id与配置指纹否则服务器抛WorkspaceConflictError_binding_conflict区分线程已绑定到不同工作区、配置漂移、项目策略漂移三种原因见 workspace.py。策略被分成两组_server_config.pySESSION_WORKSPACE_FIELDS会话字段客户端可从自己的 CLI 标志声明allow_fs_tools、auto_approve、enable_shell、sandbox_type、shell_allow_list等声明它们只证明双方一致PROJECT_WORKSPACE_FIELDS项目字段服务器必须按项目目录解析、绝不接受客户端声明extension_paths、mcp_config_path、sandbox_setup、trust_project_extensions、trust_project_mcp——每项都授予限定在某个 checkout 范围内的代码执行MCP 服务器、沙箱 setup 命令、Python 扩展可声明的客户端就能用一个目录的配置去执行另一个目录的信任决策。resolve_workspace_server_config.py处理跨目录策略启动项目保留其策略原样任何其他项目从零开始——MCP 与沙箱 setup 被丢弃drop而不是重新发现扩展信任从该项目的信任存储重新读取。_same_workspace_project按设备与 inode 比较目录失败即关闭。对于携带上下文的调用make_graph要求非空thread_id与匹配的工作区负载读取持久化绑定并选择该绑定的运行时而不是信任调用方选定的 cwd见 server_graph.py 的make_graph有execution时经require_thread_workspace校验后返回绑定运行时无执行上下文时回退到get_server_runtime。这使工作区绑定先于执行成为服务器图选择的权威来源。图装配与运行时作用域create_cli_agent组合入口create_cli_agentagent.py是组合入口它把以下要素组装为编译后的图与复合 backendserver_graph.py 展示了服务端的实际调用参数解析后的模型含model_params、profile_overrides、cli_max_retries内置工具与 MCP 工具可选沙箱sandbox_backendsandbox_type文件系统与审批策略fs_tools、auto_approve、interrupt_shell_only、shell_allow_list内存、技能、解释器配置与子代理enable_memory、enable_skills、interpreter_config、async_subagents评分上下文goal_criteria_tools、rubric_grader_tools凭据与环境credentials_snapshot、environ。它返回编译图与复合 backend服务器从同一个 backend 派生它的offload 操作offload_operation_from(composite_backend)因此图和 offload 共享资源所有权——图与 offload HTTP 路由解析到同一个 agent、backend 和压缩策略server_graph.py。评分上下文的只读工具规则criteria 创建与 rubric 评分获得内置的外部上下文工具以及注解被显式且一致地声明为只读的 MCP 工具_criteria_context_tools_mcp_tool_is_explicitly_read_only见 server_graph.py。MCPToolAnnotations.readOnlyHint被适配器序列化为 camel-case 的readOnlyHint元数据键实现要求字面量布尔True并拒绝矛盾的破坏性 hint——缺失、畸形、矛盾或可变的注解一律失败关闭fail closed。make_graph 的选择规则make_graph有两条明确的选择规则见 server_graph.py 与 code-agent.md带执行上下文校验持久化线程绑定获得以该绑定持久化资源键为 key 的运行时_workspace_runtime→_resolve_bound_workspace_config→_make_graphs不带执行上下文使用配置的 launch workspace若存在否则使用锁保护的进程级运行时get_server_runtime→_get_runtime。进程级运行时缓存是承重的进程运行时缓存是承重load-bearing的而非单纯的优化server_graph.py它防止重复的 MCP 发现、沙箱创建和atexit清理注册——每请求重建会重复发现 MCP 服务器、泄漏沙箱会话、堆叠重复的atexit处理器。两个消费者交互图和 offload HTTP 路由共享这个缓存。工作区运行时存放在共享锁 LRU 缓存中上限32 项_MAX_WORKSPACE_RUNTIMES 32server_graph.py。在构建工作区运行时之前服务器为其绑定 cwd 重建配置并要求其策略与指纹等于持久化绑定_resolve_bound_workspace_config对项目策略漂移和配置指纹漂移分别抛出命名了漂移字段的WorkspaceConflictError见 server_graph.py。配置的沙箱是进程级的只能被一个工作区认领第二个工作区会被拒绝而不是共享_claim_sandbox_workspace。失败处理与清理启动屏障与 DEEPAGENTS_STARTUP_ERROR 标记运行时构造是一道启动屏障startup barrier构造失败会发出DEEPAGENTS_STARTUP_ERROR:标记并以退出码 1 退出emit_startup_failuresys.exit(1)见 server_graph.py 与 _startup_error.py。父进程从子进程输出中抓取该标记而不是把失败降级为就绪超时——这让失败原因如Sandbox provider X is not installed能精确传回用户界面。server_manager在以下任一失败时会停掉它拥有的服务器启动失败、图就绪失败、远程客户端创建失败、工作区设置失败。其finally清理是取消安全的asyncio.CancelledError是BaseExceptionfinally而非except Exception才能保证取消时也清理见 server_manager.py。会话拆除与 POSIX 进程组正常会话拆除时server_session的finally停止拥有的服务器并发出为 debug 保留日志排队的通知server_session。在 POSIX 上子进程拥有专用进程组优雅发信号、等待和硬杀升级hard-kill escalation都包含后代进程。Windows 升级只能硬杀根进程句柄因此存活的子孙进程可能成为孤儿——这是跨平台清理行为的一个已知不对称点见 code-agent.md 的 Failure handling and teardown。ACP 集成冒烟测试ACP 集成冒烟测试test_acp_mode.py启动deepagents --acp --no-mcp执行协议初始化和new_session并断言返回的会话有 ID。这保护 ACP 的启动与会话创建路径而不经过普通回环路径——两条路径由此获得独立的回归保护。ACP stdio 生命周期--acp 在启动进程内运行--acp在启动进程中调用_run_acp_cli_asyncmain.py它解析初始模型create_model失败写 stderr 并返回退出码 1持久化解析出的模型到[models].recent尽力而为失败不拖垮运行中的会话加载工具与 MCP 配置fetch_url、get_current_thread_id有 Tavily 时加web_searchMCP 经resolve_and_load_mcp_tools在服务生命周期内保持 dcode checkpointer 打开。其build_agent(context)回调使用 ACP 会话选择的模型或解析出的默认和 cwd 构造ProjectContext然后调用create_cli_agent并传入共享的 checkpointer见 code-agent.md 的 ACP stdio lifecycle。ACP 图是会话局部的session-local而不是普通工作区运行时缓存中的条目——这正是不启动 langgraph dev、不使用 RemoteAgent的直接体现没有回环服务器、没有 HTTP/SSE、没有/dcode/threads/...绑定路由。Auto 模式下的 AgentServerACP在 Auto 模式下dcode 使用AgentServerACPacp.py它包装本地图流式输出以写入受信任的 Auto 审批状态、附加 prompt 元数据并提供 CLI 上下文。_AutoGraph.astream在每次运行前把ApprovalMode.AUTO写入 storeapproval_mode_payload并在最后一个消息上附加USER_PROMPT_METADATA_KEY元数据含turn_id然后以CLIContextSchema(approval_modeAUTO, auto_approveTrue, ...)运行图acp.py。两个使用约束见 code-agent.mdYOLO 需要事先确认prior acknowledgement--auto-classifier-model仅在解析出的审批模式是 Auto 时被 ACP 接受。ACP 失败写入 stderr 并返回非零状态码不使用普通子进程的启动标记服务结束后finally块清理 MCP 会话管理器。扩展与运维指引组合点composition points技能与子代理、内置与 MCP 工具、沙箱提供方、hooks 与 commands、以及经授权的 Python 扩展都是组合点ARCHITECTURE.md项目可以提供共享默认与集成每个用户在顶层叠加个人配置。在普通服务器模式下影响资源的设置属于工作区策略/指纹的一部分一个已绑定的线程不能被热重配置为不同的资源策略见 code-agent.md 的 Extension and operations guidance。preserve_bound_extension_trust还保留既有线程的扩展信任当线程绑定时策略为False而新授予为True时新授予被推迟给新线程撤销则始终可见以便绑定与运行时校验拒绝_server_config.py。调试时的归属判断由于存在客户端/服务器边界调试时的第一件事是判断失败属于哪一侧ARCHITECTURE.md呈现与输入通常属于客户端模型执行、工具、内存和图启动通常属于服务器。小结dcode 的架构价值在于把呈现/审批与图执行之间的边界做成进程级所有权边界并用一套机制让这条边界既清晰又可审计ServerConfig.to_env()/from_env()保证客户端与服务器子进程对配置的理解永远一致持久化工作区绑定SQLite SHA-256 指纹 不可变冲突拒绝让哪个目录、什么策略、哪个运行时成为服务器权威客户端无法越权声明项目策略进程运行时缓存与共享锁 LRU上限 32保证 MCP 发现、沙箱创建、atexit注册恰好一次启动失败用DEEPAGENTS_STARTUP_ERROR:标记回传精确原因避免退化为无意义的超时--acp则完全绕过回环服务器用进程内会话图 stdio 提供一条独立、可测试的集成路径。想要深入体验可以阅读 运行 dcode 会话指南、运行时行为、配置分层 与 ACP 集成需要本地构建与调试时可参考 DEVELOPMENT.md 与 COMMANDS.md。【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表