HTTP + SSE + WebSocket 协议网关,让任何语言的外部系统接入 CMDC Agent 能力。

安装

# mix.exs
def deps do
  [{:cmdc_gateway, "~> 0.6"}]
end

快速开始

1. 配置

# config/config.exs
config :cmdc_gateway, CMDCGateway.Plugs.Auth,
  api_keys: %{
    "my-api-key" => "default-tenant"
  }

# 可选:限流配置
config :cmdc_gateway, CMDCGateway.RateLimiter,
  rpm: 60,          # 每分钟最大请求数
  enabled: true

2. 启动服务器

# 在你的 Application 中添加 Cowboy
children = [
  {Plug.Cowboy, scheme: :http, plug: CMDCGateway.Router, options: [port: 4000]}
]

3. 调用 API

# 创建 Session
curl -X POST http://localhost:4000/v1/sessions \
  -H "X-API-Key: my-api-key" \
  -H "Content-Type: application/json" \
  -d '{"model": "deepseek:deepseek-chat", "systemPrompt": "你是助手"}'

# 发送 Prompt(异步返回 202)
curl -X POST http://localhost:4000/v1/sessions/{session_id}/prompt \
  -H "X-API-Key: my-api-key" \
  -H "Content-Type: application/json" \
  -d '{"text": "你好"}'

# 订阅 SSE 事件流(实时接收 Agent 回复)
curl -N http://localhost:4000/v1/sessions/{session_id}/events \
  -H "X-API-Key: my-api-key"

架构

外部系统 (Python / Node.js / Go / 浏览器)
    HTTP + SSE / WebSocket
  
CMDCGateway.Router
   Auth Plug          API Key  tenant_id
   RateLimiter Plug   令牌桶限流
   SessionStore       ETS session_id  Agent pid
   EventTranslator    内部事件  对外 JSON + RAG/GraphRAG trace events
   SSEHandler         chunked SSE 推送 + 心跳
   WSHandler          双向 WebSocket
   A2A                JSON-RPC task + webhook lifecycle
   WorkflowReplay     只读 AgentOps run event replay
   Meter              per-key 用量计量
   CallbackTool       HTTP 回调工具代理
  
    Elixir in-process 调用
  
CMDC 核心库 (EventBus 驱动)

端点概览

方法路径说明
GET/healthz健康检查(无需认证)
GET/.well-known/agent.jsonAgent Card / A2A 能力发现(无需认证)
POST/v1/a2a/tasks/sendA2A JSON-RPC 同步 task
POST/v1/a2a/tasks/sendSubscribeA2A JSON-RPC SSE task
POST/v1/a2a/tasks/sendWithWebhookA2A JSON-RPC webhook task
GET/v1/a2a/tasks/:task_idA2A task 短期状态兜底查询
POST/v1/sessions创建 Session
GET/v1/sessions/:id查询 Session 状态
GET/v1/sessions/:id/status完整状态:队列、审批、event cursor
DELETE/v1/sessions/:id删除 Session
POST/v1/sessions/:id/prompt发送 prompt(异步 202)
GET/v1/sessions/:id/eventsSSE 事件流,支持 since/types session replay
GET/v1/groups/:group_id/eventsgroup SSE live stream
GET/v1/workflows/runs/:run_id/eventsAgentOps workflow event replay
WS/v1/sessions/:id/wsWebSocket 双向通信
POST/v1/sessions/:id/approve审批通过
POST/v1/sessions/:id/reject审批拒绝
POST/v1/sessions/:id/respond回答 Agent 提问
POST/v1/sessions/:id/switch_model异步切换模型,支持严格 providerOpts
POST/v1/sessions/:id/tools/batch批量 attach/detach/replace allowlisted Tool
PATCH/v1/sessions/:id/plugins/:plugin/optsallowlisted Plugin opts 热更新
POST/v1/sessions/:id/steer中段注入 steering
POST/v1/sessions/:id/abort异步中止,可选 kill tools / clear queue
POST/v1/sessions/:id/checkpoints保存 checkpoint
POST/v1/sessions/resume从 checkpoint 恢复
GET/v1/provider_profilesadmin-only Provider Profile 列表
POST/v1/provider_profilesadmin-only Provider Profile 注册
DELETE/v1/provider_profiles/:nameadmin-only Provider Profile 删除
GET/v1/sessions/:id/stats用量统计
GET/v1/sessions/:id/messages对话历史
POST/v1/sessions/:id/tools注册回调工具

完整 API 文档(每个端点的详细输入/输出/字段说明/示例)见 API.md

0.6 边界

  • POST /v1/sessions 支持 core 0.6 安全白名单字段:groupIdeventBufferSizemaxSteeringQueuehibernateAfterMsmessages 等。
  • messages 历史导入只接受 user / assistant / tool_result JSON,禁止 system__struct__ 和任意 module 字段。
  • skillSelector、checkpoint backend、provider resolver、plugin module 注入不通过 public JSON;这些必须由宿主 Elixir app 服务端配置。
  • ?mode=audit 只投影当前 EventBus 事件;system-wide telemetry audit 由宿主 app 自行 attach。
  • group SSE 不提供 replay;断线补帧使用 session SSE 的 since/types
  • CMDC.monitor/1 / demonitor/2 是进程内集成能力,不提供 HTTP endpoint。

SDK 兼容

  • cmdc_gateway 0.6 对既有 REST/SSE/WebSocket SDK 是加性升级:旧字段不改名,新字段可忽略。
  • POST /v1/sessions/:id/prompt 仍返回 202,旧客户端继续通过 SSE/WS 读取 agent_end
  • GET /v1/sessions/:id/events 不带 since/types 时仍是实时流;需要断线补帧时启用 eventBufferSize 并保存 lastEventIndex
  • POST /v1/sessions/:id/tools 仍是 HTTP callback tool 注册;core Tool 批量控制使用 /tools/batch
  • workingDirproviderOpts、Plugin opts、Provider Profile opts 都经过服务端边界校验;SDK 不应发送任意模块名、resolver 函数或动态 atom key。

环境变量

变量说明默认值
GATEWAY_PORTHTTP 监听端口4000
GATEWAY_API_KEYS逗号分隔的 API Key 列表

Docker 部署

FROM elixir:1.17-otp-27-alpine AS build
WORKDIR /app
COPY . .
RUN mix deps.get --only prod && MIX_ENV=prod mix release

FROM alpine:3.19
COPY --from=build /app/_build/prod/rel/cmdc_gateway /app
ENV GATEWAY_PORT=4000
EXPOSE 4000
CMD ["/app/bin/cmdc_gateway", "start"]
docker build -t cmdc-gateway .
docker run -p 4000:4000 -e GATEWAY_API_KEYS=my-key cmdc-gateway

许可证

Apache-2.0 + Commons Clause — 详见 LICENSE