helix发消息的请求

Helix 发送的请求 body 中路由信息是放在 aid_context 嵌套对象里的(body.aid_context[“User-Id”]),而不是 HTTP headers 或 body 顶层字段。

1
2
3
4
5
6
7
8
9
{
"aid_context": {
"User-Id": "user_3c0a8d30ff7d4e9fa497e5c0ef737c59",
"Env-Id": "env_32eb5875894744d39fcd9ff81fedcece",
"Task-Id": "task_cc814a7bace74972b3bb45a06d141f2d",
"Bot-Id": "assistant_b3708f670f3f4e40bb8f98d4d121097f"
},
"content": "你好"
}

目前 MetisV3 monitor.ts 的 extractRoutingFromBody() 新增了对 aid_context 的解析,优先级:

  • body.aid_context 对象(Helix 实际格式)
  • body 顶层字段(兜底)
  • HTTP headers(兜底)

Helix 简化格式(V3 主要格式)

isHelixSimplifiedFormat() (第109-118行) 和 extractRoutingFromBody() (第129-160行) 判断和解析:

请求

1
2
3
4
5
6
7
POST /metis/events HTTP/1.1
Host: <openclaw_ip>:8765
Content-Type: application/json
User-Id: user_3c0a8d30ff7d4e9fa497e5c0ef737c59
Env-Id: test_env_001
Task-Id: test_task_001
Bot-Id: openclaw_bot

Body(三种写法,按优先级排列)

写法 1:aid_context 对象(推荐,优先级最高)

1
2
3
4
5
6
7
8
9
{
"aid_context": {
"User-Id": "user_3c0a8d30ff7d4e9fa497e5c0ef737c59",
"Env-Id": "test_env_001",
"Task-Id": "test_task_001",
"Bot-Id": "openclaw_bot"
},
"content": "你好,请问现在使用的是什么模型?"
}

写法 2:平铺字段(snake_case / camelCase / PascalCase 均可)

1
2
3
4
5
6
{
"content": "你好",
"user_id": "user_xxx",
"env_id": "test_env_001",
"task_id": "test_task_001"
}

写法 3:最简形式(路由信息全靠 HTTP Headers)

1
2
3
{
"content": "你好,请问现在使用的是什么模型?"
}

路由解析优先级

根据第166-208行 convertHelixToMetisEvent() 的逻辑:

1
Body aid_context  >  Body 平铺字段  >  HTTP Headers  >  默认值

默认值:userId → "unknown_user"envId → "default_env"taskId → "task_{timestamp}"


判断依据

代码通过以下条件判断为 Helix 简化格式(第109-118行):

1
2
3
4
typeof obj.content === "string"   // 有 content 字段
&& !obj.event_id // 没有 event_id
&& !obj.sender // 没有 sender
&& !obj.message // 没有 message

即:body 里有 content 字符串,但没有 event_id/sender/message 这些完整 Metis 格式的字段,就走 Helix 简化路径。


响应

无论哪种写法,Helix 收到的响应都是(第342-343行):

1
2
HTTP 200
{ "Code": 200, "Message": "success" }

消息在后台异步处理,处理完后 OpenClaw 通过 send.ts POST 到 callbackUrl 回复。