All notable changes to cmdc_gateway are documented in this file.
[0.4.1] - 2026-05-16
Patch release — Phase 12M v0.4.1 webhook 可靠性闭环 + A2A 协议 补全。纯加性变更,与 v0.4.0 完全向后兼容。
主库
cmdc在 v0.4.1 不变(保持 0.4.0 为最新),本 patch 仅升级 Gateway。{:cmdc_gateway, "~> 0.4"}自动拉到 0.4.1。
Added — A2A tasks/get 兜底查询 (Phase 12M / 12M.4)
补全 v0.4 留尾的「webhook 派发失败 / 客户端漏接收时无法查询 task 状态」 痛点:
GET /v1/a2a/tasks/:task_id新端点:返回 task 当前 status / last_event / payload / updated_at / ttl_untilCMDCGateway.TaskStore新模块:ETS-backed 短期缓存(默认 TTL 10 分钟),由CMDCGateway.A2A在每次 webhook 派发时同步刷新put/4、get/1、delete/1、list_recent/1、gc_now/0公共 API- 后台 GenServer 每 60s GC 过期条目
- 不持久化(重启即清,仅做"短期兜底",与 12M.1 dead-letter 职责正交)
- A2A
dispatch_webhook/5内部每次派发同步TaskStore.put,让 GET 端点能立即拿到 accepted / status_update / artifact_update / completed / failed 5 类状态
Added — Webhook Dead-Letter 持久化 (Phase 12M / 12M.1)
把 v0.4.0 「webhook 派发失败仅 log」升级为「失败 → 持久化 → BEAM 重启后自动重试」的可靠性闭环:
CMDCGateway.Webhook.DeadLetterbehaviour — 4 callback:init/1/save_failed/2/list_pending/1/delete/2/mark_retried/3。任意 backend 实现统一接口CMDCGateway.Webhook.DeadLetter.DETS—— 默认 backend:DETS 文件 持久化,BEAM 重启后自动 reload;零外部依赖;auto_save: 5_000ms保护CMDCGateway.Webhook.Dispatcher—— 调度器 GenServer:- 启动时按
enabled?opt 决定是否开始调度(默认 true,可通过WEBHOOK_DLQ_ENABLED=false关闭) - 每
tick_interval_ms(默认 30s)扫一遍 pending → 到时间的条目重 新调Webhook.dispatch - 派发成功 →
DeadLetter.delete清除 - 派发失败 →
DeadLetter.mark_retried推后下一次重试(指数退避, base 30s / cap 1h / 默认 max 10 retries) - 达到 max_retries → 永久放弃 +
Logger.error+ emit telemetry[:cmdc_gateway, :webhook, :dead_letter, :permanent_failure] - 公共 API:
enqueue/4、tick_now/0、stats/0(含 pending_count / total_retries / total_succeeded / total_permanent_failures)
- 启动时按
A2A.dispatch_webhook/5自动入队:3 次同步重试失败后 → 调Dispatcher.enqueue入 dead-letter。Dispatcher 未启动 / 不可用时 退化为原始 error tuple(无 regression)
Added — Webhook Receiver 客户端示例 (Phase 12M / 12M.2 + 12M.3)
cmdc_gateway/examples/a2a/ 新增两个开箱即用的 webhook 接收端示例,
含 HMAC-SHA256 验签与 5 类 event payload 解析:
webhook_receiver.exs—— Elixir Plug.Cowboy 实现- 自包含
Mix.install([{:plug_cowboy, ~> 2.7}, {:jason, ~> 1.4}]), 单文件即可跑 - 自定义
body_reader缓存 raw bytes 给签名校验用 :crypto.hash_equals/2常数时间比较(OTP 25+),老 OTP 自动降级
- 自包含
webhook_receiver.mjs—— Node.js Express 实现crypto.timingSafeEqual防 timing attack- JSDoc 类型定义覆盖 5 类 payload
--self-test内置签名算法验证
examples/a2a/README.md—— 协议演进时间线表 + 各 receiver 运行 命令 + 端到端测试 curl 示例
Changed — examples/a2a/README.md 协议速查表
| 端点 | 阶段 | 说明 |
|---|---|---|
POST /v1/a2a/tasks/send | 11C | JSON-RPC 同步 |
POST /v1/a2a/tasks/sendSubscribe | 11C | JSON-RPC + SSE 流式 |
POST /v1/a2a/tasks/sendWithWebhook | 12L NEW.5 | JSON-RPC + webhook 异步 |
GET /v1/a2a/tasks/:task_id | 12M v0.4.1 | 兜底查询(ETS 10min) |
配置参考
# config/runtime.exs(推荐)
config :cmdc_gateway, CMDCGateway.Webhook.Dispatcher,
enabled?: true,
backend: CMDCGateway.Webhook.DeadLetter.DETS,
backend_opts: [file: ~c"/var/cmdc/webhook_dlq.dets"],
tick_interval_ms: 30_000,
max_retries: 10环境变量快速配置:
WEBHOOK_DLQ_ENABLED=false— 关闭 dead-letter 调度WEBHOOK_DLQ_FILE=/path/to/dlq.dets— DETS 文件路径- 默认值:
enabled?=true,文件位置System.tmp_dir!()/cmdc_gateway_webhook_dlq.dets
Tests
test/cmdc_gateway/task_store_test.exs— 14 测试(put/get/TTL/GC/ delete/list_recent + event → status 推导)test/cmdc_gateway/webhook/dead_letter_test.exs— 5 测试 (build_entry + next_retry 指数退避)test/cmdc_gateway/webhook/dead_letter_dets_test.exs— 8 测试 (DETS round-trip + 持久化 reload + 幂等删除)test/cmdc_gateway/webhook/dispatcher_test.exs— 4 测试(init 降级 + enqueue + stats + tick 未到期跳过)test/cmdc_gateway/a2a_test.exs— +4 新测试(GET tasks/:idTaskStore 命中 / 404 / TTL 过期 / status 推导)- 全量 160 tests / 0 failures(v0.4.0 125 → v0.4.1 160,+35 新增)
mix compile --warnings-as-errors/mix format --check-formatted/mix credo --strict路径全通
留给 v0.4.2 / v0.5
- webhook artifact_update(message_delta)throttle 机制(v0.4 全归并为 status_update 避免风暴;v0.4.2 可选 throttle 后开启 artifact_update)
- A2A 多轮对话
sessionId默认复用(v0.4.0 起步阶段每次 task 是独立 session,v0.5 计划补 sessionId 复用语义) - A2A
Push notifications完整模式(v0.5)
[0.4.0] - 2026-05-16
Minor release — A2A Protocol 第 4 种交互机制 webhook 模式落地
(Phase 12 NEW.5 / 12L),补齐 ADP Ch.15 定义的 sync / SSE / webhook 三大入口;
依赖升级到 cmdc ~> 0.4,自动获得核心库 Phase 12 全部能力(Checkpoint /
Backend / Skill v2 / 3 新内置 Plugin / Telemetry)。No breaking changes
against v0.3.x。
Added — A2A Webhook 异步交互模式(Phase 12 NEW.5 / 12L / ADP Ch.15)
ADP Ch.15 定义的 4 种 A2A 交互机制中,v0.3 已实现 sync (/tasks/send) +
SSE (/tasks/sendSubscribe),唯独缺 webhook。SSE 在家庭路由器 / NAT
环境下普遍被 60 ~ 300 秒空闲超时杀连接,对 deep_research / ralph_mode
这种 >5 分钟的长任务是硬伤。v0.4 补齐:
POST /v1/a2a/tasks/sendWithWebhook— JSON-RPC 2.0 扩展端点:接收callbackUrl(必填)+webhookSecret(可选,用于 HMAC 签名)+id/message/sessionId/timeout_ms;立即返回{taskId, status: "accepted"},Agent 任务在后台Task进程内异步执行CMDCGateway.Webhook新模块:HMAC-SHA256 签名 + 派发 + 指数退避重试sign_payload/2+verify_signature/3—— 用:crypto.hash_equals/2(OTP 25+,常数时间比较防 timing attack;老 OTP 自动降级到 byte_size- 逐字符)
build_payload/3—— 标准 payload schema(event/taskId/timestamp/schemaVersion: 1+ extra)dispatch/3—— 同步 POST + 3 次指数退避(1s / 2s / 4s),失败 log error;HTTP 客户端用 Erlang 内置:httpc(零额外依赖)
CMDCGateway.A2A.start_with_webhook/3—— Webhook lifecycle 编排:- 立即派发
task.acceptedwebhook - subscribe EventBus;翻译 5 类 A2A 生命周期事件回调:
task.accepted—— Task 接受,session 已创建task.statusUpdate—— Agent 状态变化(working / tool_calling等)task.artifactUpdate—— 流式 message_delta(可选)task.completed—— Agent 正常结束 + 完整回复task.failed—— Agent abort / timeout / error
- 派发失败:3 次指数退避后仅写 log(v0.4.0 不持久化重试,留 v0.4.1)
- 立即派发
Signature 验签示例
# 客户端发起
curl -X POST https://your-gateway/v1/a2a/tasks/sendWithWebhook \
-H "X-API-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0", "id": 1, "method": "tasks/sendWithWebhook",
"params": {
"id": "task-abc",
"callbackUrl": "https://my-app.com/webhook",
"webhookSecret": "shared-secret-123",
"message": {"role": "user", "parts": [{"type": "text", "text": "..."}]}
}
}'
# 立即返回
# {"jsonrpc": "2.0", "id": 1, "result": {"taskId": "task-abc", "status": "accepted"}}
# 后台异步派发回调(含 HMAC-SHA256 签名)
# POST https://my-app.com/webhook
# X-CMDC-Signature: sha256=<hex>
# Body: {"event": "task.completed", "taskId": "task-abc", "result": {...},
# "timestamp": "2026-05-16T...", "schemaVersion": 1}
Changed — 依赖升级
{:cmdc, "~> 0.4"}—— 升级到核心库 0.4.0,Gateway 自动获得 cmdc 0.4 全部能力:CMDC.Checkpoint—— 配Backend.DETS可让 Session 在 BEAM 重启 / Gateway 滚动更新后无缝恢复CMDC.Backend.Composite—— prefix 路由后端,Gateway 单 Session 可同时挂Sandbox.Local(默认) +Memory.PG(/memories/*) + ETS (/conversation_history/*)- 3 新内置 Plugin ——
LargeResultOffload(200KB+ tool result 写/large_tool_results/*不污染 message history)、ContentPolicy(LLM-as-Judge 越狱 / 离题拦截)、EpisodicMemory(成功 session 自动转 few-shot 复用) CMDC.Telemetry—— 标准:telemetry事件契约([:cmdc, :llm, :request, :start/:stop]等 6 个事件),无侵入接 Langfuse / LangSmith / TempoCMDC.Skillv2 —— 加license / compatibility / metadataAnthropic spec 字段;Skill 文件 10MB 上限防 DoS
Tests
test/cmdc_gateway/webhook_test.exs—— 12 个新测试:- 签名稳定性 / 篡改检测 / secret 不匹配 / 长度差异(6)
- payload 5 种 event 字符串映射(2)
- dispatch mock 一次性成功 / 重试 3 次后失败 / 第 2 次重试成功 / secret 触发签名 header 注入(4)
- 全量 125 tests / 0 failures(v0.3.0 113 → v0.4.0 125,+12 webhook)
留给 v0.4.1 minor 版本
- webhook 派发失败的持久化 dead-letter queue(v0.4.0 仅写 log)
examples/a2a/webhook_receiver.exs+webhook_receiver.mjs客户端示例 (核心服务已完整,示例补全后即可宣传 12L.3)tasks/getREST 端点 + ETS 缓存最近 10 分钟 task 状态(webhook 派发 失败时给客户端兜底查询)
[0.3.0] - 2026-05-16
Minor release — A2A Protocol Task endpoints + Gateway-level Guardrails
- alignment with cmdc 0.3.0 core. No breaking changes against v0.2.x.
Added — A2A Protocol Task Endpoints (Phase 11C / ADP Ch.15)
Implement A2A (Agent-to-Agent) JSON-RPC 2.0 Task protocol, making CMDC Gateway a first-class A2A-compliant Agent runtime callable from any ADK / LangGraph / CrewAI / external Agent that speaks A2A.
POST /v1/a2a/tasks/send— synchronous JSON-RPC Task invocation; idempotent ontaskId; returns final Task result map; goes through Auth → RateLimit → Guardrails Plug chainPOST /v1/a2a/tasks/sendSubscribe— SSE streaming variant emittingTaskStatusUpdateEvent/TaskArtifactUpdateEventwith heartbeatsCMDCGateway.A2A— new module: JSON-RPC handler + Task lifecycle (handle_send / start_subscribe); maps A2A Task semantics onto existing Session APICMDCGateway.SSEHandler.stream_a2a/3— A2A-flavored SSE stream that translates CMDC events to A2A Task lifecycle event schema
Added — Gateway Guardrails (Phase 11C / ADP Ch.18)
CMDCGateway.Plugs.Guardrails— HTTP-layer input/output filter: denylist keywords, max prompt size, sensitive content rejection; mounted in the Router Plug chain after Auth + RateLimit, before dispatch; pluggable via application config
Added — A2A Client SDK Examples
Three runnable client samples proving external A2A agents can call this gateway end-to-end (discover → send → subscribe):
examples/a2a/curl_examples.sh— raw HTTP / SSE walkthroughexamples/a2a/elixir_send.exs— Mix-runnable Elixir Req clientexamples/a2a/node_send.mjs— Node.js fetch-based clientexamples/a2a/README.md— quickstart with environment setup
Added — Performance Baselines
benchmark/event_translator.exs— Benchee suite forCMDC.Event.t()→ A2ATaskStatusUpdateEventtranslation throughput:benchee ~> 1.3added as:dev / :testdependency
Changed — Dependency Upgrade
{:cmdc, "~> 0.3"}— pick up all 13 RFC items from cmdc 0.3.0 core (most notably::tool_execution_metricsevent,:after_turnPlugin hook, batchattach_tools/2, error-tuple public API #B21)
Quality
mix credo --strict— 0 issues (clean)- All A2A endpoints covered by
test/cmdc_gateway/a2a_test.exs - Existing 107 tests + new A2A coverage all green
[0.2.0] - 2026-04-24
Added — A2A Inter-Agent Communication(ADP Ch15)
CMDCGateway.AgentCard— 生成 A2A 兼容的 Agent Card JSON(capabilities + endpoints)GET /.well-known/agent.json— 免认证暴露 Agent Card,供其他 A2A Agent 发现
Added — Guardrails & Safety Control Plane(ADP Ch18 + CMDC v0.2 RFC)
POST /v1/sessions/:id/switch_model— 运行时切模型(RFC C8,async 202)POST /v1/sessions/:id/attach_tool— 运行时加载工具(RFC C9)DELETE /v1/sessions/:id/tools/:name— 运行时卸载工具(RFC C9)POST /v1/sessions/:id/steer— 中段注入指令(Phase 10A)POST /v1/sessions/:id/abort— 结构化 abort,支持 reason/kill_tools(RFC B6,async 202)GET /v1/sessions/:id/status— 扩展 session status(pending + queue_sizes,RFC C11)POST /v1/sessions新增 userData + promptMode 透传(RFC A1 / Phase 10B)
Fixed — Meter 自动订阅修复(P0)
Meter.init/1启动时EventBus.subscribe_all/0全局订阅- 自动
record_token_usage/2on{:agent_end, _, %CMDC.TokenUsage{}}事件 (支持 cached/reasoning/cost_usd 细粒度字段) - 移除对
{:prompt_received}的订阅,避免与 Router 手动record_prompt/1重复计数
Changed — EventTranslator 白名单扩容
- 新增 7 种事件翻译:
model_switched、tool_attached、tool_detached、tool_call_unknown、memory_flushed、plugin_event、steering
Changed — 依赖与质量
{:cmdc, "~> 0.2"}依赖升级- 新增
excoveralls开发依赖 - Router 的
CMDC.steer/2返回值修正(移除永不匹配的:ok子句) switch_model/abort改为 202 Accepted +async: true(cast 语义)- 代码质量 lift:
mix credo --strict零 issue(修with/else单子句 +try/rescue显式 + cyclomatic complexity + alias 字母序)
Stats
- 107 个单元 + 集成测试,全部通过(其中 13 个 v0.2 新端点测试)
mix compile --warnings-as-errors通过mix credo --strict0 issue
[0.1.0] - 2026-04-08
Added
CMDCGateway.Router— Plug/Cowboy HTTP 路由,13 个 REST 端点CMDCGateway.SessionStore— ETS Session 注册表,含 tenant_id/api_key 多租户字段CMDCGateway.RateLimiter— per-api-key 令牌桶限流CMDCGateway.Plugs.Auth— API Key 认证中间件(X-API-Key / Bearer Token)CMDCGateway.Plugs.RateLimitPlug— 限流 Plug,返回标准 429 + Retry-AfterCMDCGateway.Meter— per-api-key 用量计量(prompt 次数 + token 统计)CMDCGateway.EventTranslator— 内部 CMDC 事件 → 对外 JSON schema(15 种事件)CMDCGateway.SSEHandler— Server-Sent Events 流式推送 + 30 秒心跳CMDCGateway.WSHandler— Cowboy WebSocket 双向通信(事件推送 + 控制消息)CMDCGateway.CallbackTool— HTTP 回调工具动态注册与代理执行GET /healthz健康检查端点(无需认证)- 84 个单元测试 + 集成测试,全部通过