跳到主要内容

服务模式(ante serve)

服务模式(Server mode)将 Ante 作为长寿命守护进程运行,外部客户端可通过结构化的消息协议对其进行驱动。非常适合用于构建编辑器插件、Web UI 界面或任何需要长期以编程方式控制 Ante 的自动化工作流。

基础用法​

ante serve

该命令将启动守护进程,并通过 stdin/stdout 桥接 JSONL 协议。进程会持续运行,直到客户端发送 Shutdown 操作指令或关闭 stdin。

Stdio 标准输入输出传输(默认)​

ante serve --stdio

--stdio 参数为可选 —— stdio 是默认传输方式。守护进程从 stdin 逐行读取 OpMsg JSON 对象,并将 EventMsg JSON 对象逐行写入 stdout。

Unix 套接字传输​

ante serve --sock # ~/.ante/run/serve.sock
ante serve --sock /tmp/ante.sock

--sock 将协议托管在 Unix 域套接字上,因此生命周期长于单次连接的客户端可以直接连入宿主,而无需每次都拉起一个新进程。未指定路径时,套接字位于 Ante 主目录下的 run/serve.sock。

每个连接驱动各自的会话。某个客户端的 Shutdown 只结束该客户端的连接,宿主继续监听;宿主进程在收到 SIGINT 或 SIGTERM 时退出。

备注

同一时刻只有一个宿主拥有某个套接字路径。所有权由套接字旁 .lock 文件上的排他锁表示:同一路径上的第二个 ante serve --sock 会拒绝启动,而不是抢占该路径,因此正在运行的宿主不会被从其客户端下方抽走。崩溃遗留的套接字文件不持有锁,会在下次启动时被替换,无需手动清理。

WebSocket 传输​

ANTE_SERVE_TOKEN="your-secret-token" ante serve --ws 127.0.0.1:8080

--ws 参数在指定地址上启动 WebSocket 服务端。ante serve --ws 强制要求通过 ANTE_SERVE_TOKEN 环境变量传入 Bearer Token,未配置则拒绝启动。客户端必须在升级握手时提供 Authorization: Bearer <token> 请求头;缺失或错误的 Token 会被返回 HTTP 401 拒绝,握手设有 10 秒超时。每个客户端在共享主机上拥有独立连接与会话。服务端会持续接受连接,直到宿主收到 SIGINT 或 SIGTERM;某个客户端的 Shutdown 只关闭该连接。

备注

传输方式参数互斥 —— 只能在 --stdio、--sock、--ws 中选择其一。

警告

监听地址必须为本地回环地址(127.0.0.0/8 或 ::1)。Ante 拒绝绑定任何其他地址 —— 传入 0.0.0.0:8080 会在绑定前直接报错退出。跨机器访问守护进程时,请通过 SSH 隧道或带身份验证与 TLS 加密(wss://)的反向代理转发。

查看服务端记录​

v0.2.8 的 --sock 与 --ws 会向 stdout 打印可读记录,包含连接、会话开始、消息、工具调用与轮次状态。每条记录带有服务端或客户端标签,便于区分并发连接。可重定向 stdout 保存本地记录:

NO_COLOR=1 ante serve --sock > serve-transcript.log

仅在终端中启用样式,任意非空 NO_COLOR 都会禁用样式。该记录按尽力而为方式输出:输出管道过慢时可能丢弃部分记录,而不会阻塞协议通信。需要完整事件的客户端应读取协议。--stdio 的 stdout 专用于 JSONL,不打印此记录。

工作原理​

  1. 主机启动并等待所选传输方式上的操作指令
  2. 发送 StartSession 操作,使用所选模型和提供商初始化会话
  3. 发送 UserInput 操作提交提示词
  4. 在同一连接上接收流式事件 —— 思考增量、消息增量、工具调用、审批请求
  5. 对 TurnPause 中的 Approval 使用 ApprovalResponse,对 Question 使用 QuestionResponse;无法提供交互界面的客户端应在启动会话时设置 unattended: true
  6. 发送 Shutdown(或断开连接)以优雅关闭连接。stdio 模式下这也会结束单连接进程;Unix 套接字与 WebSocket 宿主则继续服务其他客户端,直到收到信号

完整消息目录与报文格式请参阅通信协议参考手册。

协议输入与事件输出相互独立读取,因此即使对端停止消费事件,Interrupt 与 Shutdown 仍能及时响应。每次事件写入的期限为 30 秒;持续阻塞或用响应淹没队列的对端会被断开,而不会拖住宿主。

调用会话示例​

将以下代码保存为 client.cjs,并运行 node client.cjs(需在 PATH 上安装 Ante,且已配置 Anthropic 凭证)。示例保持 stdin 开启,等待 SessionStart 后提交提示词,并在轮次结束或发生错误时发送 Shutdown。unattended: true 会立即拒绝需要审批的调用,并跳过结构化提问,以便此无交互示例顺利结束。

const { spawn } = require("node:child_process");
const { createInterface } = require("node:readline");

const ante = spawn("ante", ["serve", "--stdio"], {
stdio: ["pipe", "pipe", "inherit"]
});
const lines = createInterface({ input: ante.stdout, crlfDelay: Infinity });
let sequence = 0;
let stopping = false;
const send = (op) => ante.stdin.write(
JSON.stringify({ op, id: `op_${++sequence}` }) + "\n"
);

const fail = (error) => {
console.error(error.message);
process.exitCode = 1;
};
ante.on("error", fail);
ante.stdin.on("error", fail);
ante.on("exit", (code) => {
if (code) process.exitCode = code;
});

lines.on("line", (line) => {
if (!line.trim()) return;
const { event } = JSON.parse(line);
console.log("Event:", event);
if (stopping) return;
if (event.SessionStart) {
send({ UserInput: "explain what this project does" });
} else if (event.TurnEnd || Object.hasOwn(event, "Error")) {
if (event.TurnEnd?.status !== "Completed") process.exitCode = 1;
stopping = true;
send("Shutdown");
ante.stdin.end();
}
});

send({ StartSession: {
model: "claude-sonnet-5-5",
provider: "anthropic",
unattended: true
} });

Rust SDK​

ante-sdk 是面向外部程序的 Ante 客户端,因此 Rust 集成无需自行处理 JSONL 分帧或管理宿主进程。connect 会返回一个 Client —— 即一个 op 发送端与一个事件接收端 —— 适用于任意传输方式:

use ante_sdk::{ConnectOptions, connect, protocol::{Evt, Op, SessionRequest}};

let mut client = connect("stdio".parse()?, ConnectOptions::default()).await?;

client.send(Op::StartSession(SessionRequest {
model: Some("claude-sonnet-5-5".into()),
provider: Some("anthropic".into()),
unattended: Some(true),
..Default::default()
})).await?;

client.send(Op::UserInput("explain what this project does".into())).await?;

while let Some(event) = client.next_event().await {
println!("{event:?}");
if matches!(event.event, Evt::TurnEnd { .. } | Evt::Error(_)) {
break;
}
}
client.close().await;

Endpoint 描述的是宿主在哪里可达 —— 而非某个会话。连接驱动哪个会话,由其上发送的 op(StartSession、ResumeSession)决定:

Endpoint客户端行为宿主生命周期
stdio将 ante serve --stdio 作为自身子进程拉起随连接结束 —— 丢弃 op 发送端即关闭子进程的 stdin
unix:<path>连接某个 ante serve --sock 宿主的套接字文件属于他人;宿主的生命周期长于该连接
ws://<addr>, wss://<addr>连接 ante serve --ws 宿主,附带 ConnectOptions::token 作为 Bearer 认证属于他人;宿主的生命周期长于该连接

原生 ws:// 仅允许连接本地回环地址;跨网络远程连接必须使用 wss://(在启用可选 wss 特性时提供),确保 Bearer Token 绝不明文传输。

每种方式都产出同一个 Client;自身托管会话的进程也直接从其宿主获得同一类型 —— 进程内通道传递的正是远程编解码器所序列化的协议类型,因此客户端所能观察到的一切并无差别。

ConnectOptions 全部字段可选:executable(默认为 PATH 上的 ante)、追加在 serve --stdio 之后的 args、cwd、额外的 env,以及连接 ws:///wss:// 时的 token(Bearer 认证 Token)。连接成功仅代表传输层成功 —— 管道已打开,或套接字已连上。协议没有握手问候,因此第一个 op 的回复才是存活性检查。

// 连接他人正在运行的宿主
let client = connect("unix:/tmp/ante.sock".parse()?, ConnectOptions::default()).await?;

完整客户端示例可参考 examples/mini-tui:一个单文件的交互式 Chat TUI,展示了如何流式接收 MessageDelta、通过 y/n 响应 TurnPause 审批,以及按 Esc 发送 Interrupt。在该目录下运行 cargo run 即可体验。

SDK 0.2.2 已移除 ante_sdk::claude 和旧版子进程 stdio API。Ante 宿主的 stdio 连接仍通过 connect(Endpoint::Stdio, options) 支持,如上例所示。

服务模式与无头模式的区别​

无头模式(Headless)服务模式(Server)
生命周期执行单次提示词后退出长寿命常驻,支持多轮持续交互
输入方式CLI 参数或 stdin 管道结构化 JSONL 操作指令
输出形式格式化文本(minimal/human/json)原始协议事件流(JSONL)
传输层无Stdio(默认)、Unix 套接字 (--sock) 或 WebSocket (--ws)
会话管理隐式创建 —— 单次调用对应单会话显式声明 —— 客户端发送 StartSession
工具审批默认为 yolo;显式 strict/auto 会拒绝原本需要提示的调用客户端必须响应 TurnPause,或将会话声明为 unattended 以自动拒绝

命令行参数参考​

参数标识说明
--stdio通过 stdin/stdout 提供 JSONL 协议服务(默认)
--sock [PATH]通过 Unix 域套接字提供协议服务(默认为 Ante 主目录下的 run/serve.sock)
--ws <ADDR>在本地回环地址上通过 WebSocket 提供协议服务
--offline-model [MODEL]加载本地或验证模型,启动共享的 llama serve 路由器并注册 local 提供商。接受路径、已发现的文件名或验证模型名称/URL;省略值则使用 ante offline use 保存的默认模型
备注

--prompt 参数不能与 ante serve 同时使用。请通过 UserInput 操作指令传递提示词。