第26篇:API Server——把 Hermes 变成服务
Hermes 功能详解第26篇:API Server。用 HTTP API 调用 Hermes。
第26篇:API Server——把 Hermes 变成服务
嘿,朋友们!今天咱们来玩点刺激的——把 Hermes 从“命令行小助手”升级成“7x24小时在线服务”。没错,就是那个传说中的 API Server,让 Hermes 变成一个 OpenAI 兼容的 HTTP 接口。
为啥要这么干?
想象一下:你辛辛苦苦调教好的 Hermes,带着全套工具(终端、文件操作、网页搜索、记忆、技能),现在能直接接入 Open WebUI、LobeChat、LibreChat、NextChat、ChatBox 等几百种前端。这些前端只要会说 OpenAI 的“方言”,就能把 Hermes 当后端用,而且工具调用的进度条还能实时显示,酷不酷?
💡 小贴士:Hermes 自己需要配置好模型提供商和工具后端才能干活。如果你有 Nous Portal 订阅,跑一次
hermes setup --portal就全搞定了——300+ 模型加上网页/图片/TTS/浏览器工具,一步到位。
三步起飞
第一步:开启 API Server
打开 ~/.hermes/.env,加上这几行:
API_SERVER_ENABLED=true
API_SERVER_KEY=change-me-local-dev
# 可选:如果浏览器要直接访问 Hermes
# API_SERVER_CORS_ORIGINS=http://localhost:3000
第二步:启动网关
hermes gateway
看到这行就说明成功了:
[API Server] API server listening on http://127.0.0.1:8642
第三步:连接前端
把任何 OpenAI 兼容的客户端指向 http://localhost:8642/v1 就行。先用 curl 试试:
curl http://localhost:8642/v1/chat/completions \
-H "Authorization: Bearer change-me-local-dev" \
-H "Content-Type: application/json" \
-d '{"model": "hermes-agent", "messages": [{"role": "user", "content": "Hello!"}]}'
两个核心接口
1. POST /v1/chat/completions —— 标准 OpenAI 聊天格式,无状态,每次请求都带上完整对话历史:
{
"model": "hermes-agent",
"messages": [
{"role": "system", "content": "You are a Python expert."},
{"role": "user", "content": "Write a fibonacci function"}
],
"stream": false
}
2. POST /v1/responses —— 新版 Responses 格式,支持服务端记忆!用 previous_response_id 就能串联多轮对话,上下文(包括工具调用)全由服务器管理:
{
"model": "hermes-agent",
"input": "What files are in my project?",
"store": true
}
下一轮直接带上 "previous_response_id": "resp_abc123" 就行,省心!
另外,如果你不想自己追踪 response ID,还可以用 conversation 参数给对话起个名字,服务器会自动接到该对话里最新的那条 response 上。/v1/runs 和 /v1/responses 还会保留 X-Hermes-Session-Key 请求头声明的对话;显式的 session 或 response 链优先,且不会把它的对话身份转移到别的请求头上:
{"input": "Hello", "conversation": "my-project"}
{"input": "What's in src/?", "conversation": "my-project"}
{"input": "Run the tests", "conversation": "my-project"}
幂等键:重试不重复干活
POST /v1/chat/completions 和 POST /v1/responses 都接受 Idempotency-Key 请求头。在网关运行会话权威的规范模式下,这个键就是持久的准入身份:第一次带它的请求被准入并只执行一次,之后这个键就归属那次准入。键按已认证的 API profile 和凭据隔离,换个 profile 或轮换了 API_SERVER_KEY 再用同一个客户端键,会被当成新请求。
重试只有在键相同、身份字段相同、目标也相同时才算“精确重试”。改了身份字段,或把键发到另一个会话,就是冲突:请求被拒(admission_conflict),什么都不会执行。Responses(JSON 或流式)和非流式 Chat Completions 返回 HTTP 409 加错误码 admission_conflict;流式 Chat Completions 因为流已经以 HTTP 200 打开,拒绝会作为最后一个 chunk 出现,带 finish_reason: "error" 和 error.message 为 "admission_conflict",随后是 data: [DONE]——要看这个 chunk,而不是状态码。
身份字段按端点不同:Responses 是 input、instructions、previous_response_id、conversation、conversation_history、model、provider、model_options 和 tools,发送时还包括 truncation;Chat Completions 是最后一条用户消息、之前的消息(除非发了 X-Hermes-Session-Id,此时历史来自会话)、系统提示词,以及请求的模型、提供商和 model_options 等轮次设置。tools 和 tool_choice 不算在内:只改这两项的重试会重放原答案,而不是冲突。两个端点的身份都不包含投递方式,所以重试可以在 JSON 和 stream: true 之间切换,拿到同样答案的对应形式。
图片输入?没问题!
两种接口都支持图片。用户消息里用数组传 text 和 image_url 部分,远程 URL 和 base64 的 data:image/... 都行:
{
"model": "hermes-agent",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "What is in this image?"},
{"type": "image_url", "image_url": {"url": "https://example.com/cat.png", "detail": "high"}}
]
}
]
}
注意:上传文件(file / file_id)和非图片的 data: URL 会返回 400 unsupported_content_type。另外,结构化图片内容在执行过程中会保持结构化,不会被当成网关的斜杠命令来解析。
流式输出 & 工具进度
设置 "stream": true 就能开启 SSE 流式响应。Chat Completions 用标准的 chat.completion.chunk 事件,外加 Hermes 自定义的 hermes.tool.progress 事件——前端能实时显示“Agent 正在调用终端工具…”的进度,体验拉满!
Responses 接口则用 OpenAI 原生事件类型(response.created、response.output_text.delta 等),工具调用会以 function_call 和 function_call_output 形式出现在流里,结构化展示工具 UI 毫无压力。
终态语义也统一了:runs 轮询和 SSE 对 cancelled 或 failed 的判断一致;Responses 用同样的终态和 response.cancelled / response.failed 事件(即使带有诊断文本也一样);Chat Completions 对被中断的轮次报 finish_reason: "cancelled",失败报 "error",而不是成功的 "stop"。另外,用光迭代预算(agent.max_turns)的轮次仍会返回 agent 对已发现内容的收尾总结:Chat Completions 用 finish_reason: "length" 和 hermes.error_code: "iteration_budget_exhausted" 交付这段文本,Responses 则报 status: "incomplete"。把它当成一个中途停下但可用的答案,而不是取消。会话聊天回复会带上 status,其流也会报告匹配的终态 run 事件——assistant 的收尾帧本身并不代表执行成功。
顺便说一句,所有 SSE 流(Chat Completions、Responses、/api/sessions/{id}/chat/stream、/v1/runs/{id}/events)在 10 秒没事件时都会发一行 : keepalive 注释,防止长时间工具调用把客户端“晾”到超时。标准 SSE 客户端会自动忽略注释行,自己写解析器的话记得跳过以 : 开头的行。
模型思考过程也能流出来
如果模型本身会输出推理内容,而且配置允许,那思考过程也会一并返回:
- Chat Completions:思考内容走
choices[0].delta.reasoning_content,正文还是delta.content。Open WebUI、opencode、Vercel AI SDK 这些前端会把它渲染成“思考块”。 - Responses:每段思考是一个原生的
reasoningoutput item,在下一个 message 或function_call之前闭合,response.completed里也会带上。 - 非流式:
/v1/chat/completions在choices[0].message.reasoning_content返回;/v1/responses则在 message 之前返回reasoningitem,GET /v1/responses/{id}回放时也一样。 - 想关掉的话,输入端设
model_options.reasoning.enabled: false就行。能力开关在GET /v1/capabilities里看features.reasoning_streaming。
另外,Responses 流式模式下,模型在工具调用旁边写的“中途解说”(比如 openai-codex 后端的 phase="commentary" 前言)会作为独立的 message item 返回,带 "phase": "commentary",不会混进最终答案里。不想要的话,display.interim_assistant_messages: false 可以关掉。
还有几个实用接口
除了上面两个核心接口,API Server 还提供了一些辅助端点:
- GET /v1/models —— 列出可用的模型名(默认就是 profile 名,默认 profile 下是
hermes-agent),大多数前端靠它做模型发现。注意它只是 OpenAI 兼容的“轻量版”,不会枚举所有可路由的提供商/模型组合,也不带价格和能力信息。 - GET /api/model/options —— Hermes 感知的客户端可以用它拿到和 Dashboard、TUI 一样的精选模型清单,包含提供商、模型能力提示和价格元数据。默认只探测当前选中的自定义端点,加
?refresh=1才会全量探测并刷新缓存。 - GET /v1/capabilities —— 返回一份机器可读的能力描述,告诉外部 UI 当前 Hermes 版本是否支持 runs、流式、取消、会话连续性等,方便做集成时自动发现。
- GET /api/sessions/{id}/messages —— 拉取某个会话的消息历史。默认只返回“活的”对话记录;加上
include_compacted=true,被上下文压缩归档掉的那些轮次也会一并返回,方便你回看完整来龙去脉。另外,如果客户端是走网络读取、不想被大图拖慢,可以加inline_images=false,这样图片附件会渲染成[image]占位符,而不是内联的 data URI——整个对话记录只有几 KB,传输飞快。
已经退休的老接口:浏览器扩展控制
早期版本有一组给浏览器扩展用的控制协议——POST /v1/browser-control/register、GET /v1/browser-control/ws,以及 /v1/artifacts/* 路由、面板里的 browser.controller.* RPC 和 browser.extension_control 配置项。这些已经整块移除了,因为它们驱动的老工具(browser_navigate / browser_click 那一套)本身也不存在了:现在浏览器自动化统一走 browser_exec(over CDP)。
想让 Hermes 驱动你已经在跑的浏览器,把 config.yaml 的 browser.cdp_url 指向它的 DevTools 端点,或者用 /browser connect。升级时会自动清掉 config.yaml 里残留的 browser.extension_control 段,不用你手动删。
最后说两句
API Server 让 Hermes 从“单机工具”变成了“服务基础设施”。前端随便换,后端不用动。而且工具调用已经在服务器端执行完毕,返回的结果都是 "status": "completed",客户端只管展示,不用操心执行逻辑。
赶紧试试吧!把 Hermes 变成你的私人 AI 后端,配上 Open WebUI 之类的漂亮前端,那感觉,真香!
📖 官方文档
本文根据 Hermes Agent 官方文档编写,原文见:官方文档 › user-guide/features/api-server