ARTICLE DETAIL

资讯详情

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

Long Horizon Slash Command 全解析:ADK 长时程 Agent 的 9 个内置斜杠命令与分发机制

Long Horizon Slash Command 全解析:ADK 长时程 Agent 的 9 个内置斜杠命令与分发机制 Long Horizon Slash Command 全解析ADK 长时程 Agent 的 9 个内置斜杠命令与分发机制【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samples导读本文以 commands.md 为核心骨架系统拆解 Long Horizonhorizon包内置的 9 个斜杠命令——从/model切换模型、/grant授予 HITL 绕过、/yolo切换审批模式到/dream-review强制记忆整合。文章不仅逐条说明每个命令的语法与返回结果还会深入 dispatcher.py 的分发源码讲清这些命令如何在before_model_callback中被拦截、为何模型永远看不到/cmd这一轮以及如何注册你自己的斜杠命令。什么是 Long Horizon 的 slash commandLong Horizon 是构建在 ADKAgent Development Kit之上的长时程 Agent 参考实现支持跨会话记忆、每用户沙箱、工具护栏、子 Agent 与自我改进循环。在这套体系里slash command斜杠命令属于用户的操控面user-facing affordance而非模型的能力面换模型、强制记忆整合、授予人工介入HITL绕过、刷新技能目录——这些操作都应当由用户直接发起而不是靠请求模型去做。目录文档开篇即点明机制核心Names come fromhorizon/commands/__init__.pymake_slash_command_dispatcherintercepts before the model runs。所有命令名都注册在 horizon/commands/init.py 的BUILTIN_COMMAND_REGISTRY中而拦截动作由 dispatcher.py 中的make_slash_command_dispatcher()完成。commands.md 是由 generate_commands_catalog.py自动生成的目录文件文件头有 AUTO-GENERATED 标记因此修改命令注册表后需执行make commands-catalog重新生成。分发机制模型永远看不到/cmd这一轮dispatcher.py 的make_slash_command_dispatcher()返回一个挂在before_model回调链上的异步函数其执行逻辑分三种情况非斜杠开头_last_user_text(llm_request)取不到以/开头的文本直接返回None模型照常运行命中内置命令从BUILTIN_COMMAND_REGISTRY查表cmd, _, rest text[1:].partition( )解析出命令名与参数调用对应 handler并把返回字符串包装成LlmResponse直接作为本轮回复——模型完全没有参与这一轮推理命中已绑定技能名/name若匹配bound_skill_names()中的技能则通过_rewrite_last_user_text把用户消息原地改写为Use the cmd skill. rest后放行给模型执行——技能天然需要模型调用load_skill再按 SKILL.md 执行因此走改写放行而不是短路回复。此外还有一层保护handler 抛出的任何异常都会被捕获并转为[/cmd failed; see server logs]的兜底回复避免一条命令打崩整个会话。命令总览9 个命令说明/dream-review强制立即执行一次 dream-review 整合把近期会话中的信息合并进你的结构化档案Structured Profile。/grant为某条 shell 命令授予会话级 HITL 绕过——覆盖 bash、进程 spawn、进程 write 三种形态无参数时列出当前生效的授权。/model显示或切换本会话的根 Agent 模型无参数时列出可用模型。/permissions列出会话级与持久化的权限授权clear清空会话授权。/reload重新加载技能目录并使本会话缓存的 secrets 失效。/routines列出已排程的定时例程remove id取消其中一条。/sandbox-upgrade将沙箱升级到当前运行时镜像并迁移工作区。/workspace显示、设置或清除本会话的工作区焦点目录。/yolo切换 YOLO 审批模式自动批准危险命令数据外泄与灾难性操作拦截仍然生效。下面逐条结合源码展开。/model查看与切换会话模型无参数时/model通过horizon.models.selector._resolve读取当前生效的模型并列出MODEL_REGISTRY中所有可用模型current: gemini-3.7-flash available: gemini-3.1-pro-preview, gemini-3.7-flash带参数时校验模型名是否在注册表中合法则写入会话状态state[SELECTED_MODEL_STATE_KEY]key 为selected_model实现仅对本会话生效的模型切换。从源码看registry.py 中的_MODELS是模型的单一事实来源每条ModelDescriptor描述构建方式、输入窗口与能力媒体限制等MODEL_REGISTRY是懒加载的_LazyModelRegistry首次访问才构建后端因此import horizon不需要 GCP 凭据。而 selector.py 中的select_model_callback是before_model链上的第一个回调负责把会话选择的模型盖到llm_request.model上。其优先级为session.state[selected_model]由/model写入LHA_ROOT_MODEL环境变量 硬编码DEFAULT_MODEL_NAMEgemini-3.7-flash。值得注意的是未知模型名不会硬失败——选择器会告警并静默回退到默认模型聊天可用性优先于硬报错。/grant授予会话级 HITL 绕过/grant是护栏体系的一部分。当policies_guard拦截了一个工具调用比如一条有风险命令用户明确同意放行后可以用/grant command为这条命令授予本会话的豁免。源码揭示了一个容易忽略的细节一条 shell 命令在护栏链上会以三种形态出现——bash(command...)、process(actionspawn, command...)、process(actionwrite, data...)。而grant_matches要求(tool_name, signature)精确匹配所以只对bash授权会让另外两种形态仍然被拦截。因此_grant的实现会一次写入三条授权记录policy_grant(actiongrant, tool_namenames.BASH, signature{command: command}, tool_context...) policy_grant(actiongrant, tool_namenames.PROCESS, signature{command: command}, tool_context...) policy_grant(actiongrant, tool_namenames.PROCESS, signature{data: command}, tool_context...)无参数时/grant列出当前会话生效的授权列表含序号与签名重复授权同一命令会返回grant for command... already active。授权记录存放在session.state[_policy_grants]中见 policy_grants.py这意味着它们随会话持久通过与会话状态相同的机制跨插件重启存活会话结束即回收不会跨会话泄漏严格限定作用域签名采用子集匹配模型——授权{command: rm -rf build/}不会放行rm -rf /。授权在policies_guard评估规则之前被查询命中即短路放行。/permissions查看与会话授权管理/permissions汇总展示两层面的权限状态会话授权session grants即/grant写入的规则存储在session.state[permission_grants]持久化规则persisted rules从工作区.lha/permissions.jsonl读取的覆盖规则overlay。/permissions clear调用write_session_grants(state, [])清空全部会话授权持久化文件不受影响。从 permission_rules.py 可以看清权限体系的层级内置默认规则 →.lha/permissions.jsonl持久化覆盖 → 会话授权解析策略为deny 优先否则最后匹配者胜默认兜底是ask_user。该文件还定义了APPROVAL_MODE_STATE_KEY approval_mode/yolo依赖以及PERMISSION_GRANTS_STATE_KEY permission_grants。/yolo切换 YOLO 审批模式/yolo读写session.state[APPROVAL_MODE_STATE_KEY]approval_mode在default与yolo两个模式间切换yolo模式本会话内危险命令自动批准但返回信息明确提示Catastrophic and secret-exfil blocks still apply——灾难性操作与秘密外泄拦截不受影响default模式危险命令需要交互式人工审批。read_approval_mode只接受{default, yolo}两个合法值其余一律回落为default。它是典型的会话级开关所有状态都落在 ADK 会话状态上不触碰全局配置。/workspace设置会话工作区焦点/workspace控制每会话的工作区窗口workspace window——即默认作用域而非安全边界无参数显示当前焦点目录workspace focus: ...未设置时为(whole workspace)/workspace subdir把窗口锚定到某个工作区相对子目录如/workspace src/之后路径类工具解析默认值.与相对路径时优先落在窗口内/workspace /或/workspace --all清空窗口恢复整个工作区范围。实现细节见 workspace_window.py目录校验通过path_under_root完成设置结果写入session.state[workspace_window]。该文件的 docstring 特别强调窗口收窄的是默认绝不是访问权限——真正的信任闸门是path_under_root它会在每次路径解析的最后执行任何在根目录内的路径包括/前缀或指向其他子目录的路径仍可触达整个工作区窗口只是让默认值聚焦避免模型在共享工作区里迷路。/reload刷新技能目录与 secrets 缓存/reload是唯一一个与模型侧工具共享同一代码路径的命令。在 commands/init.py 中模块级函数reload()同时被注册为模型工具reload和斜杠命令/reload——手打/reload与请求模型执行 reload走完全相同的逻辑这是该命令在源码注释中明确的设计意图。它的职责有两层使 secrets 缓存失效调用get_secret_store().invalidate(user_id)让用户下次注入时从 Secret Manager 重新拉取重新镜像并重扫技能目录调用resync_and_refresh()skill_reload.py。该方法先通过环境接口把用户在沙箱内编辑的技能workspace/.agents/skills/重新镜像到宿主机缓存再重走技能目录原地替换SkillToolset._skills最后把新目录写入session.state[bound_skills]。返回格式展示了刷新差异reloaded · skills: total · loaded · -removed其中 loaded/removed 是本次刷新新增/移除的技能名列表。这正是 README 中drop a SKILL.md or a scripts/ .py in the workspace and/reloadpicks it up mid-session. No fork, no redeploy的实现基础——ADK 的SkillToolset._skills可变且关闭了调用缓存目的就是允许会话中途变更目录。/routines管理定时例程/routines与调度器子系统对接无参数或list通过get_routine_store().list_for_user(user_id)列出当前用户的例程每行包含- id (schedule) next: next_fire_atremove id调用store.cancel(id, user_id)取消指定例程成功返回Removed routine id.否则No such routine.。用户身份通过horizon.auth.identity.get_user_id_from_context()解析例程数据存储在例程存储中生产环境为 Cloud SQL见 routine_postgres_store.py。定时例程是真实持久化的聊天在 Web UI 的 Scheduled 文件夹中可见、可回放——由 Cloud Scheduler 驱动的例行聊天与普通会话走同一条 A2A 处理路径。/sandbox-upgrade升级沙箱运行时/sandbox-upgrade调用horizon.conversation.session_start.upgrade_user_sandbox(user_id)返回状态分三种状态含义upgraded沙箱已升级到新版本工作区已迁移sandbox upgraded to version · /workspace migratedalready_current已在最新版本无需升级no_sandbox尚无沙箱——下个会话会自动创建这与每用户沙箱的跨会话存活机制配套沙箱在轮次之间保持温热并在下一条消息时重挂快照存活为可选开启当部署镜像滚动更新后用户可通过该命令热升级自己的沙箱运行时而不必等待重建。/dream-review强制记忆整合/dream-review把本应夜间定时执行的做梦过程dream review提前触发调用horizon.memory.dream_review._run_dream_review_for_user()读取近期会话把分散的记忆合并进用户的结构化档案Structured Profile。成功后返回dream-review done — profile consolidated from N session(s)若跳过则返回dream-review skipped: reason。这对应 Long Horizon 的自我改进循环单次会话看不到全局而 dream review 恰恰把周一提到的事在周五浮现这类跨会话洞察显式化。正常运行时它由 Cloud Scheduler 定时驱动见 dream_review_endpoint.py/dream-review让用户可以在任意时刻手工触发同一流程。如何注册你自己的斜杠命令commands.md 指出命令名来自 horizon/commands/init.py 的注册表新增命令的方式就是向该注册表注册一个 handlerfrom horizon.commands import register register(my-command) async def _my_command(args: str, callback_context: Any) - str: # args: 命令名之后的所有文本如 /my-command foo bar 的 foo bar # callback_context: ADK 回调上下文可访问 session state 等 return my-command executed注册表BUILTIN_COMMAND_REGISTRY: dict[str, SlashHandler]以register(name)装饰器收集 handler签名统一为Callable[[str, Any], Awaitable[str]]参数 回调上下文 → 返回字符串。handler 返回的字符串会被 dispatcher.py 包装成LlmResponse直接回复用户。几个扩展要点读写会话状态通过getattr(callback_context, state, None)获取 ADK 会话状态 dict写入自定义 key如/model写selected_model、/workspace写workspace_window访问调用上下文callback_context._invocation_context携带user_id、app_name、memory_service、session_service等运行时依赖/dream-review、/reload、/sandbox-upgrade均依赖它命令名与技能名冲突内置命令优先于技能只有未命中内置注册表的/name才会被改写为技能调用重新生成目录改动注册表后执行make commands-catalog让 commands.md 与代码保持同步该文件由 generate_commands_catalog.py 自动生成不建议手改。在回调链中的位置与设计意图从 architecture.md 的执行流程看_slash_command_dispatcher位于before_model回调链中部select_model_callback盖模型→prune_tool_outputs_callback→redact_artifact_urls_callback→_slash_command_dispatcher→system_prompt_assembly_callback→reminder_injection_callback→subagent_description_callback这个位置有明确考量分发器在系统提示词组装之前短路本轮因此模型既看不到/cmd原文也拿不到针对该轮组装的提示词——命令是纯粹的用户侧操作。这与这些能力属于用户的操控面而非模型的能力面的模块 docstring 完全一致。下一步阅读docs/configuration.md —— 环境变量与依赖 extras 全集AGENTS.md —— 架构、子系统与贡献规则含回调顺序、状态键、环境变量的完整内部文档docs/architecture.md —— 系统级架构图与各子系统入口文件docs/security-model.md —— 护栏分层exfil 层 A / policies 层 C / permission 层 D与权限模型docs/routines.md —— 定时例程的隔离沙箱与运行上下文docs/memory.md —— 记忆、自我改进与 dream-review 循环。【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表