ARTICLE DETAIL

资讯详情

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

HumanLayer HLD 守护进程协议全解:基于 Unix Socket 的 JSON-RPC 2.0 通信规范

HumanLayer HLD 守护进程协议全解:基于 Unix Socket 的 JSON-RPC 2.0 通信规范 HumanLayer HLD 守护进程协议全解基于 Unix Socket 的 JSON-RPC 2.0 通信规范【免费下载链接】humanlayerThe best way to get AI coding agents to solve hard problems in complex codebases.项目地址: https://gitcode.com/GitHub_Trending/hu/humanlayerHumanLayer DaemonHLD是 hld/ 目录下用 Go 实现的本地守护进程它把 Claude Code 的会话启动、运行监控、审批流转与事件订阅统一封装成一套基于Unix domain socket JSON-RPC 2.0的行分隔 JSON 协议供本地 CLI如 hlyr与桌面界面humanlayer-wui调用。本文以 hld/PROTOCOL.md 为骨架结合 hld/rpc/server.go、hld/rpc/handlers.go、hld/daemon/daemon.go 等源码实现完整讲解协议的消息格式、全部 API 方法、订阅机制与安全模型读完即可直接用nc或任意语言客户端对接 HLD。协议概览与架构定位HLD 采用Unix domain socket JSON-RPC 2.0 行分隔 JSON三要素组合传输层Unix domain socket本机进程间通信拒绝跨网络访问语义层JSON-RPC 2.0 规范定义请求 / 响应 / 错误结构帧协议每条消息以\n结尾line-delimited JSON方便逐行读取解析。从源码看这一协议由 hld/rpc/server.go 中的Server实现ServeConn使用bufio.Scanner逐行读取连接解析失败返回-32700 Parse error普通请求经handleRequest分发到注册的 handlerSubscribe方法则被单独识别并转交subscriptionMgr.SubscribeConn进入长连接逻辑hld/rpc/server.go。守护进程在 hld/daemon/daemon.go 中创建 socket、设置权限并启动acceptConnections循环为每个客户端连接启动独立 goroutine 处理。传输层设计项目说明协议Unix domain socketAF_UNIXSocket 路径可通过环境变量HUMANLAYER_DAEMON_SOCKET配置默认路径~/.humanlayer/daemon.sock权限0600仅属主可读写消息格式行分隔 JSON每条 JSON-RPC 消息后跟换行符Socket 缓冲区1MB文档约定实际 Scanner 缓冲上限 10MB见下文说明并发模型每个客户端连接独立 goroutine 处理支持并发连接关于默认路径与权限可分别在 hld/config/config.goDefaultSocketPath ~/.humanlayer/daemon.sock与 hld/daemon/daemon.goSocketPermissions 0600创建后调用os.Chmod找到对应实现。守护进程启动时若发现 socket 文件已存在会先尝试连接探测是否存活存活则报ErrDaemonAlreadyRunning否则清理残留的 stale socket 后继续启动hld/daemon/daemon.go。补充一个协议文档未展开的实现细节hld/rpc/server.go 中 Scanner 的单行缓冲区上限为10*1024*102410MB注释明确to match claudecode-go即与 claudecode-go 客户端保持一致的读取能力——读取行超过上限时会直接报错因此单条消息体不应超过该限制。JSON-RPC 2.0 消息格式请求格式{ jsonrpc: 2.0, method: methodName, params: { ... }, id: 1 }响应格式{ jsonrpc: 2.0, result: { ... }, id: 1 }错误响应格式{ jsonrpc: 2.0, error: { code: -32600, message: Error description, data: { ... } }, id: 1 }对应的 Go 结构体定义在 hld/rpc/server.goRequest中params为json.RawMessage延迟解析id为interface{}Response的result与error二选一omitemptyError含code、message与可选的data。从源码看服务端对jsonrpc字段有显式校验req.JSONRPC ! 2.0时返回-32600 Invalid request: must be JSON-RPC 2.0hld/rpc/server.go。标准错误码协议文档列出以下标准 JSON-RPC 2.0 错误码与 hld/rpc/server.go 中的常量一一对应错误码常量名含义-32700ParseError解析错误JSON 无法解析-32600InvalidRequest无效请求如 jsonrpc 版本不符-32601MethodNotFound方法不存在-32602InvalidParams参数无效-32603InternalError内部错误处理链路上JSON 解析失败与版本校验失败会立即构造错误响应方法未注册时返回-32601Method not found: methodhandler 执行返回 error 时统一包装为-32603hld/rpc/server.go。业务层的参数校验错误如query is required也经由 handler 的 error 返回最终以-32603呈现。API 方法总览协议文档定义了核心方法hld/rpc/handlers.go 的SessionHandlers.Register与 hld/rpc/approval_handlers.go 展示了实际注册的全部方法完整清单如下分类方法说明健康检查health返回守护进程状态与版本会话管理launchSession启动一个新 Claude Code 会话会话管理listSessions列出全部会话会话管理getSessionLeaves获取会话树的叶子会话支持 normal/archived/draft 过滤会话管理getSessionState获取会话当前状态与统计会话管理continueSession在既有会话基础上继续生成子会话会话管理interruptSession中断运行中的会话会话管理getSessionSnapshots获取会话期间的文件快照会话管理updateSessionSettings更新会话设置如自动接受编辑、跳过权限会话管理updateSessionTitle更新会话标题会话管理getRecentPaths获取最近使用的目录会话管理archiveSession/bulkArchiveSessions归档 / 批量归档会话会话历史getConversation获取会话完整事件历史审批管理createApproval创建本地审批供 Agent/MCP 调用审批管理fetchApprovals获取某会话待审批列表审批管理getApproval查询单个审批详情审批管理sendDecision提交审批决定approve/deny事件订阅Subscribe长连接订阅事件流下面按协议文档的章节逐一详解并补充源码中的扩展方法。健康检查healthMethodhealth请求参数无响应{ status: ok, version: 0.1.0 }实现位于 hld/rpc/server.go 的handleHealthCheck返回ok与version.GetVersion()的版本号可通过HUMANLAYER_DAEMON_VERSION_OVERRIDE环境变量或NewServerWithVersionOverride覆盖版本字符串便于区分开发/生产实例。注意health是registerBuiltinHandlers中唯一的内置方法与业务 handler 解耦。会话管理 APIlaunchSession启动会话MethodlaunchSession请求参数{ query: string (required), model: string (optional: opus or sonnet), mcp_config: { // MCPConfig object (optional) }, permission_prompt_tool: string (optional), working_dir: string (optional), max_turns: number (optional), system_prompt: string (optional), append_system_prompt: string (optional), allowed_tools: [string array (optional)], disallowed_tools: [string array (optional)], custom_instructions: string (optional), verbose: boolean (optional) }响应{ session_id: string, run_id: string }结合 hld/rpc/handlers.go 的HandleLaunchSession实现可补充以下几点关键行为query 必填query为空时直接报错query is required模型映射源码实际支持三种取值——opus→claudecode.ModelOpus、sonnet→claudecode.ModelSonnet、haiku→claudecode.ModelHaiku传入其他值或留空则交由 Claude 决定默认模型hld/rpc/handlers.go输出格式强制 JSONhandler 固定设置OutputFormat: claudecode.OutputStreamJSON保证守护进程以流式 JSON 事件监控会话MCP 注入无论调用方是否提供mcp_confighld/session/manager.go 都会自动注入名为codelayer的 MCP server命令为hlyr mcp claude_approvals并通过环境变量注入HUMANLAYER_SESSION_ID、HUMANLAYER_RUN_ID、HUMANLAYER_DAEMON_SOCKETHTTP 类型的 MCP server 则注入X-Session-ID请求头。这正是审批能力与permission_prompt_tool自动回退默认为mcp__codelayer__request_permission的底层机制请求中还支持协议文档未列出的扩展字段title、additional_directories、dangerously_skip_permissions、dangerously_skip_permissions_timeout见LaunchSessionRequest定义。listSessions列出会话MethodlistSessions请求参数None 或空对象响应{ sessions: [ { id: string, run_id: string, claude_session_id: string (optional), parent_session_id: string (optional), status: starting|running|completed|failed, start_time: ISO 8601 timestamp, end_time: ISO 8601 timestamp (optional), last_activity_at: ISO 8601 timestamp, error: string (optional), query: string, model: string (optional), working_dir: string (optional), result: { // Claude Code Result object (optional) } } ] }实现上HandleListSessions直接透传h.manager.ListSessions()返回的[]session.Infohld/rpc/handlers.go目前请求体仅预留过滤器位置。getSessionState获取会话状态MethodgetSessionState请求参数{ session_id: string (required) }响应{ session: { id: string, run_id: string, claude_session_id: string (optional), parent_session_id: string (optional), status: starting|running|completed|failed|waiting_input, query: string, model: string (optional), working_dir: string (optional), created_at: ISO 8601 timestamp, last_activity_at: ISO 8601 timestamp, completed_at: ISO 8601 timestamp (optional), error_message: string (optional), cost_usd: number (optional), total_tokens: number (optional), duration_ms: number (optional) } }从 hld/rpc/types.go 的SessionState结构可见真实响应字段远比协议文档示例丰富还包括summary、title、model_id、input_tokens、output_tokens、cache_creation_input_tokens、cache_read_input_tokens、effective_context_tokens、context_limit、auto_accept_edits、dangerously_skip_permissions、dangerously_skip_permissions_expires_at、archived等。其中context_limit由 handler 依据模型计算得出hld/rpc/handlers.go 调用GetModelContextLimit其余 token 统计由 Claude Code 结果回填。continueSession继续会话MethodcontinueSession请求参数{ session_id: string (required), query: string (required), system_prompt: string (optional), append_system_prompt: string (optional), mcp_config: string (JSON string of MCP config, optional), permission_prompt_tool: string (optional), allowed_tools: [string array (optional)], disallowed_tools: [string array (optional)], custom_instructions: string (optional), max_turns: number (optional) }响应{ session_id: string, run_id: string, claude_session_id: string, parent_session_id: string }两个关键实现细节hld/rpc/handlers.go父子会话模型continueSession不是追加到原会话而是创建一个以session_id为parent_session_id的新会话/新 run形成会话树。这也是 getSessionLeaves 存在的前提mcp_config 传字符串与launchSession直接传对象不同continueSession的mcp_config是 MCP 配置的JSON 字符串源码注释明确to avoid import cyclehandler 内部json.Unmarshal后转为claudecode.MCPConfig解析失败返回invalid mcp_config JSON扩展字段additional_directories、proxy_enabled、proxy_base_url、proxy_model_override、proxy_api_key用于代理模型场景见ContinueSessionRequest。会话树扩展方法源码补充协议文档未展开、但已在 hld/rpc/handlers.go 注册的方法服务于 humanlayer-wui 的会话树/管理功能getSessionLeaves入参{filter: normal|archived|draft}基于parent_session_id构建父子映射只返回没有子会话的叶子节点并按last_activity_at倒序排列。测试用例覆盖线性链、fork、深树等场景hld/rpc/handlers_test.gointerruptSession仅允许中断running状态的会话返回{success: true, status: interrupting}hld/rpc/handlers_test.go 验证了非 running 不可中断的约束getSessionSnapshots入参{session_id}返回该会话期间的文件快照列表tool_id、file_path、content、created_at供前端展示 Diff 场景使用updateSessionSettings支持auto_accept_edits、dangerously_skip_permissions可带dangerously_skip_permissions_timeout_ms。开启跳过权限时handler 会自动批准该会话所有待审批项best-effort失败仅记日志并发布settings_updated事件hld/rpc/handlers.goupdateSessionTitle / getRecentPaths / archiveSession / bulkArchiveSessions分别为会话改名、查询最近工作目录默认 limit 20、归档与批量归档failed_sessions列出失败项。会话历史getConversationMethodgetConversation请求参数{ session_id: string (optional), claude_session_id: string (optional) }注意session_id与claude_session_id至少提供一个二者都为空时返回错误either session_id or claude_session_id is required。响应{ events: [ { id: number, session_id: string, claude_session_id: string, sequence: number, event_type: message|tool_call|tool_result|system, created_at: ISO 8601 timestamp, role: user|assistant|system (optional), content: string (optional), tool_id: string (optional), tool_name: string (optional), tool_input_json: string (optional), tool_result_for_id: string (optional), tool_result_content: string (optional), is_completed: boolean, approval_status: string (optional: NULL|pending|approved|denied), approval_id: string (optional) } ] }实现要点hld/rpc/handlers.go按claude_session_id查询时走store.GetConversation单次会话按session_id查询时走store.GetSessionConversation始终返回包含父会话在内的完整历史事件结构体 hld/rpc/types.go 额外定义了parent_tool_use_id字段工具调用嵌套关系created_at统一格式化为 RFC3339ISO 8601时间戳approval_status取值为NULL | pending | approved | deniedNULL表示无需审批approval_id关联审批记录测试用例覆盖按两种 ID 查询、缺失 ID 报错、非法 JSON 报错等场景hld/rpc/handlers_test.go。审批管理 API审批是 HLD 的核心能力Agent 执行工具调用前可经由codelayerMCP server 创建审批由外部界面humanlayer-wui或脚本拉取并决策。fetchApprovals拉取待审批项MethodfetchApprovals请求参数{ session_id: string (optional) }响应{ approvals: [ { id: local-xxx, session_id: session-xxx, tool_name: bash, tool_input: {command: ls -la}, status: pending, created_at: 2025-07-15T12:00:00Z } ] }实现细节hld/rpc/approval_handlers.go未提供session_id时返回空列表[]而非 null提供时调用approvals.GetPendingApprovals返回待审批项。sendDecision提交审批决定MethodsendDecision请求参数{ approval_id: string (required), decision: approve|deny (required), comment: string (optional/required for deny) }决策规则approve批准该工具调用deny拒绝该工具调用必须提供 comment响应{ success: boolean, error: string (optional) }从 hld/rpc/approval_handlers.go 的实现看校验顺序为approval_id必填 →decision必填 → 按 decision 分发approve调用ApproveToolCall(ctx, id, comment)deny时 comment 为空直接报错comment is required for denial非法 decision 报invalid decision: d (must be approve or deny)。业务失败如审批不存在会以{success: false, error: ...}返回而不是 RPC 错误。源码补充的审批方法createApproval入参{run_id, tool_name, tool_input, tool_use_id?}由 Agent 侧MCP/hlyr调用创建本地审批有tool_use_id时走CreateApprovalWithToolUseID支持对具体工具调用二次确认否则走兼容旧路径的CreateApprovalhld/rpc/approval_handlers.gogetApproval入参{approval_id}返回单个审批的完整详情。事件订阅SubscribeMethodSubscribe请求参数{ event_types: [string array (optional)], session_id: string (optional), run_id: string (optional) }事件类型new_approval收到新的审批approval_resolved审批已解决approved/denied/respondedsession_status_changed会话状态变更初始响应{ subscription_id: string, message: Subscription established. Waiting for events... }事件通知流式推送{ event: { type: event_type, timestamp: ISO 8601 timestamp, data: { // Event-specific data } } }心跳每 30 秒{ type: heartbeat, message: Connection alive }注意Subscribe采用长轮询long-polling连接会一直保持直到客户端或服务端主动关闭。订阅机制的源码实现Subscribe是协议中唯一需要直连读写的方法hld/rpc/server.go 会拦截该方法并直接转交SubscriptionHandlers.SubscribeConn其完整流程hld/rpc/subscription_handlers.go参数校验event_types、session_id、run_id均为可选过滤器全部拼装为bus.EventFilter订阅事件总线调用h.eventBus.Subscribe(ctx, filter)获取带唯一subscription_id的订阅通道事件缓冲 100 条见 hld/bus/events.go并defer保证断开时注销发送初始响应先回{subscription_id: ..., message: Subscription established. Waiting for events...}连接监控后台 goroutine 每 100ms 尝试读 1 字节仅当遇到非超时错误连接关闭时取消上下文、结束订阅——这正是客户端断开即自动退订的机制事件循环select三路——上下文取消即退出事件到达则包装为{event: {...}}推送事件类型为空时丢弃并告警30 秒无事件则发送心跳保持连接存活。事件过滤规则事件总线在 hld/bus/events.go 的matchesFilter中实现过滤event_types非空时事件类型必须命中其中一项session_id过滤要求事件data.session_id与过滤器一致run_id过滤要求事件data.run_id与过滤器一致三种条件同时满足才推送慢消费者通道写满会直接丢弃事件并打dropping event for slow subscriber警告因此订阅端应尽快消费。连接管理每个客户端连接独立处理独立 goroutine见 hld/daemon/daemon.go连接可随时关闭服务端通过读取超时监控自动清理订阅守护进程支持并发连接Socket 缓冲区 1MB协议文档约定RPC 读取缓冲上限 10MB实现值。数据类型与状态机会话状态值Session Status值含义starting会话初始化中running会话处理中completed会话成功完成failed会话出错waiting_input会话等待用户输入如等待审批额外的状态流转细节守护进程重启时会将上一轮遗留的running、waiting_input、starting会话标记为failederror_message: daemon restarted while session was active而interrupting、interrupted、completed、failed状态保持不变以支持重启后继续已中断的会话hld/daemon/daemon.go。审批状态值Approval Status值含义NULL无需审批pending等待审批决定approved已批准denied已拒绝resolved已通用解决外部渠道解决事件类型Event Types值含义message聊天消息user/assistant/systemtool_call工具调用tool_result工具执行结果system系统事件端到端实战示例1. 连接守护进程并做健康检查# 使用 netcat仅用于测试 nc -U ~/.humanlayer/daemon.sock # 发送健康检查 {jsonrpc:2.0,method:health,id:1}预期响应一行 JSON{jsonrpc:2.0,result:{status:ok,version:0.1.0},id:1}若守护进程尚未启动可用go run ./hld/cmd/hld启动socket 路径可通过HUMANLAYER_DAEMON_SOCKET覆盖。2. 启动一个会话{ jsonrpc: 2.0, method: launchSession, params: { query: Help me write a Python script, model: opus, working_dir: /path/to/project }, id: 2 }预期响应{jsonrpc:2.0,result:{session_id:uuid,run_id:uuid},id:2}拿到session_id后即可轮询getSessionState观察状态或用getConversation拉取对话事件。3. 订阅事件流{ jsonrpc: 2.0, method: Subscribe, params: { event_types: [new_approval, session_status_changed], session_id: session-123 }, id: 3 }连接建立后先收到订阅确认随后每 30 秒收到一次心跳无事件时事件产生时收到{event: {...}}通知。4. 审批处理闭环典型工作流Agent 调用工具前经codelayerMCP 触发审批会话状态进入waiting_input客户端收到new_approval事件或主动调用fetchApprovals拉取展示tool_name与tool_input如{command: ls -la}给人确认调用sendDecision提交approve或带 comment 的deny审批解决后收到approval_resolved事件会话继续运行。5. 继续会话分叉新 run{ jsonrpc: 2.0, method: continueSession, params: { session_id: session-xxx, query: Now fix the bug you found }, id: 4 }响应中的parent_session_id指向原会话新会话成为会话树的一个新分支。安全设计守护进程仅接受 Unix domain socket 连接不监听任何网络端口用于 RPCHTTP 服务仅绑定127.0.0.1见 hld/config/config.go 的http_host默认值Socket 权限为0600仅属主可读写由守护进程启动时强制os.Chmod设置不内置认证安全由文件系统权限保证——只有与守护进程同用户的进程才能访问该 socket守护进程以启动它的用户同等权限运行因此任何能连上 socket 的本地进程都拥有全部操作能力切勿将 socket 路径暴露给不可信进程socket 目录以0700权限创建且启动时会清理残留的 stale socket 文件hld/daemon/daemon.go。参考源码索引协议文档hld/PROTOCOL.mdRPC 服务器与消息结构hld/rpc/server.go请求/响应类型定义hld/rpc/types.go会话 handler 实现hld/rpc/handlers.go审批 handler 实现hld/rpc/approval_handlers.go订阅 handler 实现hld/rpc/subscription_handlers.go守护进程主逻辑socket 生命周期hld/daemon/daemon.go事件总线与过滤hld/bus/events.go配置加载与默认值hld/config/config.go会话管理与 MCP 注入hld/session/manager.go协议测试用例hld/rpc/handlers_test.go客户端 Go SDKclaudecode-go/README.md配套 CLIhlyrhlyr/README.md桌面界面消费该协议的 UIhumanlayer-wui/README.md【免费下载链接】humanlayerThe best way to get AI coding agents to solve hard problems in complex codebases.项目地址: https://gitcode.com/GitHub_Trending/hu/humanlayer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表