15  第 13 章 Socket API

15.1 概述

CLI 是人类与 Herdr 交互的主要方式,但当你需要从外部程序(如 Python 脚本、Node.js 服务)控制 Herdr 时,频繁调用 CLI 会有以下问题:

  • 每次调用都要启动新进程,开销大
  • 输出需要文本解析,容易出错
  • 无法实时接收事件通知
  • 难以管理多个并发操作

Socket API 解决了这些问题。它提供了基于 Unix Socket 的 JSON-RPC 接口,让你可以直接与 Herdr Server 通信,获取完整的结构化数据和实时事件流。

读完本章,你将能够:

  • 理解 Socket API 与 CLI 的关系和取舍
  • 使用原始 JSON-RPC 方法控制 Herdr
  • 订阅事件流并实现实时监控
  • 用 Python 编写完整的 Herdr 自动化脚本

15.2 何时用 Socket API vs CLI

特性 CLI Socket API
使用门槛 低(直接输入命令) 中(需要写代码)
性能 每次调用有进程启动开销 持久连接,无额外开销
输出格式 文本(可指定 JSON) 原生 JSON-RPC
事件订阅 不支持(需轮询) 原生支持
并发 每次调用独立 单连接多请求
适用场景 日常操作、简单脚本 自动化系统、监控面板、IDE 集成
Tip

经验法则: - 用 CLI:当你在 Shell 中手动操作,或写简单的 Bash 脚本 - 用 Socket API:当你构建自动化系统、需要事件订阅、或从非 Shell 语言(Python、TypeScript)控制 Herdr


15.3 Schema 获取

Herdr 的 API Schema 是自描述的——你不需要记忆所有方法名,可以随时查询。

15.3.1 获取完整 Schema

# 人类可读格式
herdr api schema

# JSON 格式(推荐用于程序化处理)
herdr api schema --json > herdr-api-schema.json

15.3.2 Schema 结构

{
  "version": "1.2.3",
  "methods": {
    "server.status": {
      "params": {},
      "returns": { "running": "boolean", "version": "string" }
    },
    "pane.read": {
      "params": { "paneId": "string", "source": "string?", "lines": "int?" },
      "returns": { "content": "string" }
    }
  },
  "events": {
    "agent.stateChanged": { "fields": { "agentName": "string", "newState": "string" } }
  }
}
Note

Schema 版本化:Schema 中的 version 字段对应 Herdr 版本。不同版本的可用方法可能不同。始终检查 Schema 以确认方法是否可用。


15.4 Socket 路径与传输

15.4.1 Socket 路径

Herdr Server 启动后,会在以下位置创建 Unix Socket:

$TMPDIR/herdr-<uid>/herdr.sock

或(如果 TMPDIR 未设置):

/tmp/herdr-<uid>/herdr.sock

你可以通过以下方式获取实际路径:

# 方法 1:CLI 查询
herdr api socket-path
# /var/folders/xx/herdr-501/herdr.sock

# 方法 2:环境变量
echo "$HERDR_SOCKET"

# 方法 3:status 命令
herdr status --json | jq -r '.socket_path'

15.4.2 传输协议

Socket API 使用 JSON-RPC 2.0 协议:

sequenceDiagram
    participant C as Client
    participant S as Herdr Server
    
    C->>S: {"jsonrpc":"2.0","method":"server.status","id":1}
    S->>C: {"jsonrpc":"2.0","result":{...},"id":1}
    
    C->>S: {"jsonrpc":"2.0","method":"events.subscribe","id":2,"params":{"event":"agent.*"}}
    S->>C: {"jsonrpc":"2.0","result":{"subscriptionId":"sub_1"},"id":2}
    
    Note over S: Agent 状态变化
    S->>C: {"jsonrpc":"2.0","method":"event","params":{"subscriptionId":"sub_1","data":{...}}}

15.4.3 手动测试连接

# 用 socat 连接并手动发送请求
echo '{"jsonrpc":"2.0","method":"server.status","id":1}' | \
    socat - UNIX-CONNECT:$(herdr api socket-path)

# 用 curl(如果支持 Unix Socket)
curl --unix-socket $(herdr api socket-path) \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"jsonrpc":"2.0","method":"server.status","id":1}' \
    http://localhost/

15.5 原始方法名参考

以下按功能区域列出所有 Socket API 方法。

15.5.1 Server / 通知 / 客户端

方法 说明 对应 CLI
server.status 获取 Server 状态 herdr status
server.stop 停止 Server herdr server stop
server.reloadConfig 重新加载配置 herdr server reload-config
notification.list 列出通知 herdr notification show
client.identify 标识客户端连接

15.5.2 Session

方法 说明 对应 CLI
session.list 列出所有会话 herdr session list
session.get 获取会话详情 herdr session attach
session.stop 停止会话 herdr session stop
session.delete 删除会话 herdr session delete

15.5.3 Workspace / Worktree

方法 说明 对应 CLI
workspace.create 创建工作空间 herdr workspace create
workspace.list 列出工作空间 herdr workspace list
workspace.get 获取工作空间详情 herdr workspace get
workspace.focus 切换工作空间 herdr workspace focus
workspace.rename 重命名 herdr workspace rename
workspace.close 关闭 herdr workspace close
worktree.create 创建 worktree herdr worktree create
worktree.list 列出 worktree herdr worktree list
worktree.open 打开 worktree herdr worktree open
worktree.remove 移除 worktree herdr worktree remove

15.5.4 Tab

方法 说明 对应 CLI
tab.create 创建 Tab herdr tab create
tab.list 列出 Tab herdr tab list
tab.get 获取 Tab 详情 herdr tab get
tab.focus 切换 Tab herdr tab focus
tab.rename 重命名 Tab herdr tab rename
tab.close 关闭 Tab herdr tab close

15.5.5 Pane

方法 说明 对应 CLI
pane.split 分割窗格 herdr pane split
pane.swap 交换窗格 herdr pane swap
pane.move 移动窗格 herdr pane move
pane.close 关闭窗格 herdr pane close
pane.read 读取内容 herdr pane read
pane.sendText 发送文本 herdr pane send-text
pane.sendKeys 发送按键 herdr pane send-keys
pane.run 执行命令 herdr pane run
pane.waitOutput 等待输出 herdr pane wait-output
pane.reportAgent 报告 Agent 状态 herdr pane report-agent
pane.reportAgentSession 报告 Agent 会话
pane.releaseAgent 释放 Agent
pane.focus 聚焦窗格 herdr pane focus
pane.resize 调整大小 herdr pane resize
pane.zoom 放大/恢复 herdr pane zoom
pane.rename 重命名 herdr pane rename
pane.layout 应用布局 herdr pane layout
pane.processInfo 进程信息 herdr pane process-info
pane.neighbor 查询邻居 herdr pane neighbor
pane.edges 查询边界 herdr pane edges

15.5.6 Agent

方法 说明 对应 CLI
agent.start 启动 Agent herdr agent start
agent.prompt 发送提示 herdr agent prompt
agent.wait 等待状态 herdr agent wait
agent.read 读取输出 herdr agent read
agent.get 获取信息 herdr agent get
agent.list 列出所有 Agent herdr agent list
agent.explain 解释行为 herdr agent explain
agent.sendKeys 发送按键 herdr agent send-keys
agent.rename 重命名 herdr agent rename
agent.focus 聚焦 herdr agent focus

15.5.7 Events

方法 说明
events.subscribe 订阅事件
events.unsubscribe 取消订阅
events.wait 阻塞等待事件(长轮询)
events.list 列出当前订阅

15.5.8 Integrations / Plugins

方法 说明 对应 CLI
integration.install 安装集成 herdr integration install
integration.uninstall 卸载集成 herdr integration uninstall
integration.status 集成状态 herdr integration status
plugin.install 安装插件 herdr plugin install
plugin.uninstall 卸载插件 herdr plugin uninstall
plugin.list 列出插件 herdr plugin list
plugin.action.list 列出 Action herdr plugin action.list
plugin.action.invoke 调用 Action herdr plugin action.invoke

15.6 请求/响应格式

15.6.1 标准请求

所有请求遵循 JSON-RPC 2.0 格式:

{
  "jsonrpc": "2.0",
  "method": "pane.read",
  "params": {
    "paneId": "p1",
    "source": "recent",
    "lines": 50
  },
  "id": 1
}

15.6.2 标准响应

{
  "jsonrpc": "2.0",
  "result": {
    "content": "file.rs\nfn main() { ... }",
    "paneId": "p1",
    "timestamp": "2026-08-01T15:52:00Z"
  },
  "id": 1
}

15.6.3 错误响应

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": {
      "field": "paneId",
      "detail": "Pane 'p99' does not exist"
    }
  },
  "id": 1
}

15.6.4 错误码参考

错误码 含义
-32700 解析错误(无效 JSON)
-32600 无效请求
-32601 方法不存在
-32602 参数无效
-32603 内部错误
-32000 Agent 超时
-32001 Agent stalled
-32002 Agent blocked
-32003 资源不存在

15.6.5 批量请求

Socket API 支持批量请求,一次发送多个调用:

[
  {"jsonrpc":"2.0","method":"agent.list","id":1},
  {"jsonrpc":"2.0","method":"server.status","id":2},
  {"jsonrpc":"2.0","method":"workspace.list","id":3}
]

响应也以批量方式返回:

[
  {"jsonrpc":"2.0","result":{"agents":[...]},"id":1},
  {"jsonrpc":"2.0","result":{"running":true},"id":2},
  {"jsonrpc":"2.0","result":{"workspaces":[...]},"id":3}
]
Tip

批量请求的性能优势:当你需要同时获取多个独立信息时,批量请求可以显著减少往返延迟。例如,初始化监控面板时,可以用一个批量请求获取所有 Agent 的状态、工作空间列表和通知。


15.7 事件订阅机制

事件订阅是 Socket API 相对于 CLI 的最大优势。你可以实时接收 Herdr 内部发生的变化,而无需轮询。

15.7.1 events.subscribe

{
  "jsonrpc": "2.0",
  "method": "events.subscribe",
  "params": {
    "event": "agent.stateChanged",
    "filter": {
      "agentName": "my-helper"
    }
  },
  "id": 1
}

响应:

{
  "jsonrpc": "2.0",
  "result": {
    "subscriptionId": "sub_a1b2c3"
  },
  "id": 1
}

15.7.1.1 通配符订阅

// 订阅所有 Agent 相关事件
{"event": "agent.*"}

// 订阅所有事件
{"event": "*"}

15.7.1.2 可订阅事件列表

事件 说明 字段
agent.stateChanged Agent 状态变化 agentName, oldState, newState
agent.started Agent 启动 agentName, kind, paneId
agent.stopped Agent 停止 agentName, reason
agent.output Agent 产生输出 agentName, content
pane.created 窗格创建 paneId, tabId
pane.closed 窗格关闭 paneId
pane.output 窗格产生输出 paneId, content
workspace.activated 工作空间切换 workspaceName
notification.created 新通知 type, message

15.7.2 events.wait

events.wait 是一个便捷方法,阻塞直到匹配的事件发生(超时返回)。

{
  "jsonrpc": "2.0",
  "method": "events.wait",
  "params": {
    "event": "agent.stateChanged",
    "filter": {
      "agentName": "my-helper",
      "newState": "done"
    },
    "timeout": 300
  },
  "id": 2
}
Note

events.wait vs events.subscribe: - subscribe:注册长期订阅,持续接收事件。适合监控面板。 - wait:一次性等待,超时即返回。适合编排脚本中的「等待某个条件满足」。

15.7.3 事件消息格式

当订阅的事件发生时,Server 会推送通知:

{
  "jsonrpc": "2.0",
  "method": "event",
  "params": {
    "subscriptionId": "sub_a1b2c3",
    "event": "agent.stateChanged",
    "data": {
      "agentName": "my-helper",
      "oldState": "working",
      "newState": "idle",
      "timestamp": "2026-08-01T15:52:00Z"
    }
  }
}

15.8 Agent 状态报告

Socket API 提供了比 CLI 更细致的 Agent 状态控制。

15.8.1 pane.report-agent

主动报告窗格中 Agent 的状态:

{
  "jsonrpc": "2.0",
  "method": "pane.report-agent",
  "params": {
    "paneId": "p2",
    "state": "working",
    "detail": "正在分析代码..."
  },
  "id": 3
}

15.8.2 pane.report-agent-session

报告 Agent 会话信息(更详细):

{
  "jsonrpc": "2.0",
  "method": "pane.report-agent-session",
  "params": {
    "paneId": "p2",
    "sessionId": "session-abc",
    "model": "claude-sonnet-4",
    "tokenCount": 15234
  },
  "id": 4
}

15.8.3 pane.release-agent

释放窗格的 Agent 关联(Agent 停止但进程可能继续):

{
  "jsonrpc": "2.0",
  "method": "pane.release-agent",
  "params": {
    "paneId": "p2",
    "reason": "task completed"
  },
  "id": 5
}

15.9 读取窗格输出

// 请求
{
  "jsonrpc": "2.0",
  "method": "pane.read",
  "params": {
    "paneId": "p1",
    "source": "recent",
    "lines": 100
  },
  "id": 6
}

// 响应
{
  "jsonrpc": "2.0",
  "result": {
    "content": "$ npm test\n\n> my-app@1.0.0 test\n> jest\n\nPASS  src/index.test.js\nTests: 3 passed",
    "paneId": "p1",
    "rows": 6,
    "timestamp": "2026-08-01T15:52:00Z"
  },
  "id": 6
}

15.10 等待状态变化

结合 events.wait 实现「等待 Agent 完成后读取结果」的模式:

// 步骤 1: 发送提示
{
  "jsonrpc": "2.0",
  "method": "agent.prompt",
  "params": { "name": "my-helper", "message": "修复 bug" },
  "id": 7
}

// 步骤 2: 等待完成
{
  "jsonrpc": "2.0",
  "method": "events.wait",
  "params": {
    "event": "agent.stateChanged",
    "filter": { "agentName": "my-helper", "newState": "idle" },
    "timeout": 600
  },
  "id": 8
}

// 步骤 3: 读取结果
{
  "jsonrpc": "2.0",
  "method": "agent.read",
  "params": { "name": "my-helper", "source": "recent", "lines": 100 },
  "id": 9
}

15.11 布局导入导出

15.11.1 layout.export

// 请求
{
  "jsonrpc": "2.0",
  "method": "layout.export",
  "params": {},
  "id": 10
}

// 响应
{
  "jsonrpc": "2.0",
  "result": {
    "layout": {
      "type": "split",
      "direction": "horizontal",
      "ratio": 0.5,
      "children": [
        { "type": "pane", "id": "p1" },
        {
          "type": "split",
          "direction": "vertical",
          "ratio": 0.6,
          "children": [
            { "type": "pane", "id": "p2" },
            { "type": "pane", "id": "p3" }
          ]
        }
      ]
    }
  },
  "id": 10
}

15.11.2 layout.apply

{
  "jsonrpc": "2.0",
  "method": "layout.apply",
  "params": {
    "layout": {
      "type": "split",
      "direction": "horizontal",
      "ratio": 0.3,
      "children": [
        { "type": "pane" },
        { "type": "pane" },
        { "type": "pane" }
      ]
    }
  },
  "id": 11
}

布局 JSON 的递归结构:

graph LR
    Root["Split (horizontal)"] --> P1["Pane p1"]
    Root --> Right["Split (vertical)"]
    Right --> P2["Pane p2"]
    Right --> P3["Pane p3"]


15.12 实验性功能

以下功能标记为实验性,API 可能在未来版本中变更。

15.12.1 Pane Graphics(Kitty Graphics 协议)

支持在窗格中渲染图像(基于 Kitty Terminal Graphics Protocol):

{
  "jsonrpc": "2.0",
  "method": "pane.renderGraphics",
  "params": {
    "paneId": "p1",
    "image": "<base64-encoded-png>",
    "format": "png",
    "placement": "center"
  },
  "id": 12
}
Warning

兼容性:Pane Graphics 依赖于终端的 Kitty Graphics 协议支持。目前支持的终端:Kitty、WezTerm、Ghostty。iTerm2 使用不同的协议,部分支持。macOS Terminal.app 不支持

15.12.2 Terminal Session Observe / Control

允许第三方程序观察和控制终端会话:

// 开始观察
{
  "jsonrpc": "2.0",
  "method": "terminal.observe",
  "params": { "paneId": "p1" },
  "id": 13
}

// 响应中包含一个 observeId,之后所有 pane 的输出都会推送
// 接管控制
{
  "jsonrpc": "2.0",
  "method": "terminal.control",
  "params": {
    "observeId": "obs_abc",
    "mode": "shared"
  },
  "id": 14
}

适用于构建远程协作工具、录制/回放系统等。


15.13 协议稳定性说明

Herdr 的 Socket API 遵循以下版本化策略:

graph TD
    A[API 版本] --> B[Stable 核心]
    A --> C[Stable 扩展]
    A --> D[Experimental]
    
    B -->|"保证向后兼容"| E["语义化版本控制<br/>major 变更才 break"]
    C -->|"次要版本可扩展"| F["新方法可加入<br/>现有方法不变"]
    D -->|"随时可能变更"| G["可能有 breaking change<br/>使用前检查 Schema"]

分类 说明 稳定性
Stable 核心 Server/Pane/Agent/Workspace/Tab 的基本 CRUD ✅ 向后兼容
Stable 扩展 Events/Layout/Integration ✅ 次要版本只新增
Experimental Graphics/Terminal observe/Plugin actions ⚠️ 可能变更
Tip

生产环境建议: 1. 在程序启动时调用 api schema 检查方法是否可用 2. 对实验性方法做降级处理(graceful degradation) 3. 订阅 server.apiChanged 事件,在 API 变更时收到通知


15.14 实战示例:Python Herdr 监控脚本

以下是一个完整的 Python 脚本,展示如何通过 Socket API 实现多 Agent 监控。

#!/usr/bin/env python3
"""
Herdr 多 Agent 监控面板
通过 Socket API 实时监控所有 Agent 的状态变化。
"""

import json
import socket
import sys
import time
from dataclasses import dataclass, field
from typing import Optional


# ──────────────────────────────────────────────
# Herdr Client
# ──────────────────────────────────────────────

class HerdrClient:
    """Herdr Socket API 客户端"""

    def __init__(self, socket_path: Optional[str] = None):
        self.socket_path = socket_path or self._discover_socket()
        self.sock: Optional[socket.socket] = None
        self._id = 0

    def _discover_socket(self) -> str:
        """自动发现 Socket 路径"""
        import subprocess
        result = subprocess.run(
            ["herdr", "api", "socket-path"],
            capture_output=True, text=True
        )
        path = result.stdout.strip()
        if not path:
            raise RuntimeError("无法发现 Herdr Socket 路径")
        return path

    def connect(self):
        """连接到 Herdr Server"""
        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        self.sock.connect(self.socket_path)
        self.sock.settimeout(300)  # 5 分钟超时
        print(f"✅ 已连接: {self.socket_path}")

    def close(self):
        """关闭连接"""
        if self.sock:
            self.sock.close()
            self.sock = None

    def call(self, method: str, **params) -> dict:
        """发送 JSON-RPC 请求"""
        self._id += 1
        request = {
            "jsonrpc": "2.0",
            "method": method,
            "id": self._id
        }
        if params:
            request["params"] = params

        data = json.dumps(request) + "\n"
        self.sock.sendall(data.encode())

        # 读取响应
        buffer = b""
        while True:
            chunk = self.sock.recv(4096)
            if not chunk:
                break
            buffer += chunk
            if b"\n" in buffer:
                break

        response = json.loads(buffer.decode().strip())
        if "error" in response:
            raise Exception(
                f"API Error {response['error']['code']}: "
                f"{response['error']['message']}"
            )
        return response.get("result", {})

    def recv_event(self, timeout: float = 300) -> Optional[dict]:
        """接收一个事件(阻塞)"""
        self.sock.settimeout(timeout)
        try:
            buffer = b""
            while True:
                chunk = self.sock.recv(4096)
                if not chunk:
                    break
                buffer += chunk
                if b"\n" in buffer:
                    break
            msg = json.loads(buffer.decode().strip())
            if msg.get("method") == "event":
                return msg["params"]
        except socket.timeout:
            return None
        return None


# ──────────────────────────────────────────────
# Agent 监控器
# ──────────────────────────────────────────────

@dataclass
class AgentInfo:
    name: str
    kind: str
    state: str
    pane_id: str
    last_change: float = field(default_factory=time.time)


class AgentMonitor:
    """多 Agent 状态监控器"""

    def __init__(self, client: HerdrClient):
        self.client = client
        self.agents: dict[str, AgentInfo] = {}

    def refresh(self):
        """刷新所有 Agent 状态"""
        result = self.client.call("agent.list")
        agents = result.get("agents", [])

        self.agents.clear()
        for a in agents:
            info = AgentInfo(
                name=a["name"],
                kind=a.get("kind", "unknown"),
                state=a.get("state", "unknown"),
                pane_id=a.get("paneId", "?")
            )
            self.agents[info.name] = info
        self._render()

    def subscribe(self):
        """订阅 Agent 状态变化事件"""
        self.client.call("events.subscribe", event="agent.*")
        print("📡 已订阅 Agent 事件\n")

    def listen(self):
        """监听事件并更新状态"""
        while True:
            event = self.client.recv_event(timeout=600)
            if event is None:
                continue

            event_type = event.get("event")
            data = event.get("data", {})
            name = data.get("agentName", "?")

            if event_type == "agent.stateChanged":
                old = data.get("oldState", "?")
                new = data.get("newState", "?")
                if name in self.agents:
                    self.agents[name].state = new
                    self.agents[name].last_change = time.time()
                print(f"🔄 [{name}] {old}{new}")

            elif event_type == "agent.started":
                kind = data.get("kind", "?")
                pane = data.get("paneId", "?")
                self.agents[name] = AgentInfo(
                    name=name, kind=kind, state="idle", pane_id=pane
                )
                print(f"🚀 [{name}] 启动 (kind={kind}, pane={pane})")

            elif event_type == "agent.stopped":
                reason = data.get("reason", "?")
                self.agents.pop(name, None)
                print(f"🛑 [{name}] 停止 (reason={reason})")

            self._render()

    def _render(self):
        """渲染状态表格"""
        print("\n" + "=" * 60)
        print(f"{'Agent':<20} {'Kind':<10} {'State':<12} {'Pane':<6}")
        print("-" * 60)

        state_emoji = {
            "idle": "🟢",
            "working": "🔵",
            "blocked": "🟡",
            "done": "✅",
            "error": "🔴"
        }

        for name, info in sorted(self.agents.items()):
            emoji = state_emoji.get(info.state, "⚪")
            print(
                f"{name:<20} {info.kind:<10} "
                f"{emoji} {info.state:<8} {info.pane_id:<6}"
            )
        print("=" * 60 + "\n")


# ──────────────────────────────────────────────
# 主程序
# ──────────────────────────────────────────────

def main():
    # 连接 Herdr
    client = HerdrClient()
    client.connect()

    monitor = AgentMonitor(client)

    # 初始刷新
    monitor.refresh()

    # 订阅事件
    monitor.subscribe()

    # 持续监听
    print("🎧 监听中... (Ctrl+C 退出)\n")
    try:
        monitor.listen()
    except KeyboardInterrupt:
        print("\n👋 退出监控")
    finally:
        client.close()


if __name__ == "__main__":
    main()

15.14.1 运行效果

$ python3 monitor.py
 已连接: /var/folders/xx/herdr-501/herdr.sock

============================================================
Agent                Kind       State        Pane
------------------------------------------------------------
code-reviewer        claude     🟢 idle      p2
fixer                codex      🔵 working   p3
orchestrator         claude     🟡 blocked   p1
============================================================

📡 已订阅 Agent 事件

🎧 监听中... (Ctrl+C 退出)

🔄 [fixer] working → done
🔄 [fixer] done → idle
🛑 [orchestrator] 停止 (reason=timeout)
🚀 [test-runner] 启动 (kind=claude, pane=p4)

============================================================
Agent                Kind       State        Pane
------------------------------------------------------------
code-reviewer        claude     🟢 idle      p2
fixer                codex      🟢 idle      p3
test-runner          claude     🟢 idle      p4
============================================================

15.14.2 扩展:自动分配任务

基于监控框架,你可以进一步实现自动任务分配:

def auto_dispatch(client: HerdrClient, monitor: AgentMonitor):
    """当有 idle Agent 时,自动从任务队列分配任务"""
    task_queue = ["写单元测试", "更新文档", "修复 lint 错误"]

    for name, info in monitor.agents.items():
        if info.state == "idle" and task_queue:
            task = task_queue.pop(0)
            print(f"📤 分配任务给 [{name}]: {task}")
            client.call(
                "agent.prompt",
                name=name,
                message=task
            )
            # 异步等待完成
            client.call(
                "events.wait",
                event="agent.stateChanged",
                filter={"agentName": name, "newState": "idle"},
                timeout=600
            )
            # 读取结果
            result = client.call(
                "agent.read",
                name=name,
                source="recent",
                lines=50
            )
            print(f"✅ [{name}] 完成: {result.get('content', '')[:200]}")
Tip

进阶方向: 1. Web 仪表盘:用 Flask/FastAPI 包装 Socket API,提供浏览器可访问的监控面板 2. Slack/飞书通知:Agent 完成任务后自动发送消息通知 3. 自动扩缩容:根据任务队列长度自动启动/停止 Agent 4. 日志聚合:收集所有 Agent 的输出,统一搜索和分析


15.15 小结

本章深入探讨了 Herdr 的 Socket API——从底层协议到实战应用。

特性 CLI Socket API
日常操作 ✅ 首选 过重
自动化脚本 ✅ 简单可用 ✅ 更强大
实时监控 ❌ 需轮询 ✅ 事件驱动
IDE 集成 ⚠️ 可用 ✅ 推荐
批量操作 ⚠️ 多次调用 ✅ 批量请求

下一章我们将进入进阶篇,讨论 Herdr 的深度配置、性能调优和高级部署模式。