Skip to content

Latest commit

 

History

History
427 lines (332 loc) · 11 KB

File metadata and controls

427 lines (332 loc) · 11 KB
title AEP v1 协议参考
weight 1
description Agent Event Protocol v1 完整参考:事件类型、Envelope 格式、背压机制与错误码

AEP v1 协议参考

Agent Event Protocol v1 完整参考文档——事件类型、Envelope 格式、背压机制、错误码

协议概述

AEP v1(Agent Event Protocol)是 HotPlex Gateway 的 WebSocket 通信协议:

  • 传输层:WebSocket,NDJSON(Newline-Delimited JSON)编码
  • 通信模式:全双工(Full-Duplex),Client 和 Server 可同时发送消息
  • 设计理念:Streaming-first、统一 Envelope、结构化用户交互
  • 版本标识aep/v1

Envelope 格式

所有消息共用统一的 Envelope 结构:

{
  "version": "aep/v1",
  "id": "evt_<uuid>",
  "seq": 42,
  "priority": "data",
  "session_id": "sess_<uuid>",
  "timestamp": 1710000000123,
  "event": {
    "type": "message.delta",
    "data": {}
  }
}
字段 类型 必选 说明
version string 固定 aep/v1
id string 事件唯一标识,UUID v4(evt_ 前缀)
seq int64 单调递增序列号,从 1 开始,per-session 独立空间
priority string "control""data"(默认)
session_id string Session 标识(sess_ 前缀)
timestamp int64 Unix 毫秒时间戳
event.type string 事件类型
event.data object 事件载荷

Priority 语义

  • control:跳过背压队列,优先发送(如 control.reconnecterrordone
  • data:正常排队,受背压控制(如 message.deltatool_call

Seq 规则

  • 仅实际发送的事件消耗 seq(被丢弃的 delta 不递增 seq)
  • ping/pong 的 seq 为 0(不参与序号分配)
  • Client 不应通过 seq gap 检测丢包——gap 不会出现

Client → Server 事件

init(连接握手)

WebSocket 连接建立后的第一帧必须是 init,30 秒超时。

{
  "type": "init",
  "data": {
    "version": "aep/v1",
    "worker_type": "claude_code",
    "session_id": "sess_xxx",
    "auth": { "token": "<jwt>" },
    "config": {
      "model": "claude-sonnet-4-6",
      "allowed_tools": ["read_file", "write_file"],
      "max_turns": 0,
      "work_dir": "/app"
    },
    "client_caps": {
      "supports_delta": true,
      "supports_tool_call": true,
      "supported_kinds": ["message.delta", "tool_call"]
    }
  }
}

session_id 非空时为 Resume 模式,空时创建新 Session。

input(用户输入)

{
  "type": "input",
  "data": {
    "content": "请帮我重构 login 函数",
    "metadata": {}
  }
}

Session 处于 RUNNING 时发送 input 会被拒绝(SESSION_BUSY)。

permission_response(权限响应)

{
  "type": "permission_response",
  "data": {
    "id": "perm_123",
    "allowed": true,
    "reason": "approved by user"
  }
}

question_response(用户回答)

{
  "type": "question_response",
  "data": {
    "id": "q_<uuid>",
    "answers": { "问题文本": "选项标签" }
  }
}

elicitation_response(MCP 输入响应)

{
  "type": "elicitation_response",
  "data": {
    "id": "el_<uuid>",
    "action": "accept",
    "content": { "token": "ghp_xxx" }
  }
}

action 取值:"accept" | "decline" | "cancel"

worker_command(Worker 命令)

通过 Worker stdio 发送的控制命令,用于在 Agent Turn 过程中查询状态或修改运行时行为。

{
  "type": "worker_command",
  "data": {
    "command": "context_usage",
    "args": "",
    "extra": {}
  }
}

WorkerStdioCommand 支持以下命令:

Command 说明
context_usage 查询当前 context window 使用情况
mcp_status 查询 MCP 服务器连接状态
set_model 切换 LLM 模型
set_permission 修改工具权限策略
skills 列出可用 Skills
compact 压缩上下文历史
clear 清空上下文
model 查询当前模型信息
effort 调整推理努力级别
rewind 回退到指定对话快照
commit 触发代码提交

ping(心跳)

{ "type": "ping", "data": {} }

Server → Client 事件

init_ack(握手确认)

{
  "type": "init_ack",
  "data": {
    "session_id": "sess_xxx",
    "state": "created",
    "server_caps": {
      "protocol_version": "aep/v1",
      "supports_resume": true,
      "supports_delta": true,
      "max_frame_size": 32768
    }
  }
}

错误时 state"deleted",附带 error + code 字段。

message.start / message.delta / message.end(流式输出)

三段式流式消息生命周期:

message.start → message.delta* → message.end
  • message.start:消息元数据(ID、role、content_type)
  • message.delta:增量文本(可被背压丢弃,dropped 标记)
  • message.end:消息结束标记

message(完整消息)

非流式场景的完整消息,向后兼容。流式场景推荐使用三段式。

tool_call / tool_result(工具调用通知)

{ "type": "tool_call", "data": { "id": "call_123", "name": "read_file", "input": {"path": "/app/main.py"} } }
{ "type": "tool_result", "data": { "id": "call_123", "output": "file content...", "error": "" } }

Autonomous 模式下为通知性质,Worker 内部执行,Client 无需回传结果。

state(状态变更)

{ "type": "state", "data": { "state": "running", "message": "context_reset" } }

状态集合:created | running | idle | terminated

done(执行完成)

{
  "type": "done",
  "data": {
    "success": true,
    "stats": {
      "duration_ms": 5200,
      "tool_calls": 3,
      "input_tokens": 1000,
      "output_tokens": 500,
      "total_tokens": 1700,
      "model": "claude-sonnet-4-6",
      "context_used_percent": 45.2
    },
    "dropped": false
  }
}

dropped: true 表示本轮有 message.delta 被丢弃,Client 应以最终完整载荷覆盖渲染。

注意stats 字段类型为 map[string]any,无固定 schema。上表列出的是常见字段,实际返回的字段取决于 Worker 类型和执行结果,可能包含 cost_usdcache_read_tokens 等额外信息。

permission_request / question_request / elicitation_request(用户交互)

Worker 请求人类介入的结构化交互事件。默认 5 分钟超时自动拒绝(auto-deny)。

reasoning / step / raw(辅助事件)

  • reasoning:Agent 思维过程(thinking)
  • step:执行阶段标记(plan/execute/verify)
  • raw:Worker 原始事件透传

context_usage(Context 用量报告)

{
  "type": "context_usage",
  "data": {
    "total_tokens": 62000,
    "max_tokens": 200000,
    "percentage": 31,
    "categories": [{"name": "system_prompt", "tokens": 4500}]
  }
}

mcp_status(MCP 服务状态)

{
  "type": "mcp_status",
  "data": {
    "servers": [{"name": "github-mcp", "status": "connected"}]
  }
}

pong(心跳响应)

{ "type": "pong", "data": { "state": "idle" } }

双向事件

control(控制命令)

Client → Server

Action 说明
terminate 终止 Worker,Session → TERMINATED
delete 删除 Session + 清理 runtime
reset 清空上下文,Session 保持 RUNNING
gc 归档会话:终止 Worker,保留历史,可 Resume
cd 切换工作目录(创建新 Session 继承原 Session 上下文)

Server → Clientpriority: "control"):

Action 说明
reconnect 强制重连(服务器维护、版本升级)
session_invalid Session 失效通知
throttle 降级通知(速率限制建议)

error(错误通知)

{ "type": "error", "data": { "code": "WORKER_CRASH", "message": "exit code 139" } }

error 后必须跟随 done

错误码参考

Worker 类

Code 说明
WORKER_START_FAILED Worker 启动失败
WORKER_CRASH 进程崩溃(SIGSEGV 等)
WORKER_TIMEOUT 执行超时
WORKER_OOM 内存溢出(exit code 137)
PROCESS_SIGKILL 被强制终止
WORKER_OUTPUT_LIMIT 单行输出超限(10MB)

Session 类

Code 说明
SESSION_NOT_FOUND Session 不存在
SESSION_EXPIRED Session 已过期
SESSION_BUSY 正在执行,拒绝新 input
SESSION_TERMINATED Session 已终止
SESSION_INVALIDATED Session 被失效

Protocol 类

Code 说明
INVALID_MESSAGE 消息格式无效
PROTOCOL_VIOLATION 协议违规
VERSION_MISMATCH 版本不兼容
CONFIG_INVALID 配置校验失败

Auth / Gateway 类

Code 说明
UNAUTHORIZED 认证失败
AUTH_REQUIRED 认证缺失
INTERNAL_ERROR 内部错误
GATEWAY_OVERLOAD 过载
RATE_LIMITED 速率限制
EXECUTION_TIMEOUT Worker 僵死超时
RECONNECT_REQUIRED 服务端要求客户端重连
RESUME_RETRY Session resume 失败,建议重试
NOT_SUPPORTED 操作不支持
TURN_TIMEOUT Turn 执行超时

背压机制

Worker 产出过快时,Gateway 使用 bounded channel(默认容量 256)缓冲消息:

事件类型 背压行为
message.delta / raw 可丢弃(非阻塞 select)
message / done / error / control 不可丢弃(阻塞发送)
priority: "control" 跳过背压队列,直接发送

丢弃的 delta 不消耗 seq,通过 done.dropped 标记通知 Client。

Init 握手流程

Client                          Server
  |                               |
  |--- init(version, caps) ------>|
  |                               |--- 创建/恢复 Session
  |<-- init_ack(session_id) ------|
  |                               |
  |--- input(content) ----------->|--- state(running)
  |                               |--- message.start
  |<-- message.delta * ------------|--- message.delta
  |<-- message.end ---------------|
  |<-- done(success) -------------|--- state(idle)
  |                               |

全双工通信流

Client ←→ Server

Input Flow:     input → [state(running)] → [tool_call → tool_result]* → [message.delta*] → done
Control Flow:   control(action) → state(new_state) / error
Interactive:    permission_request ←→ permission_response
                question_request ←→ question_response
                elicitation_request ←→ elicitation_response
Heartbeat:      ping ←→ pong

最小合规要求

必须支持initinputcontrolpinginit_ackmessage.deltastateerrordonepong

可选扩展message.start/endmessagetool_call/resultreasoningsteprawpermission_*question_*elicitation_*context_usagemcp_statusworker_command