All notable changes to cmdc_gateway are documented in this file.
[Unreleased]
[0.6.0] - 2026-06-01
Minor release — Core 0.6 gateway protocol upgrade, AgentOps event surface and release hardening.
Published to hex.pm and hexdocs.pm, checksum
8674905211ab7612d388dbc2ee7fd034bffc9acc8b67db545c2b8eaa6f273e60.
Added
- Core 0.6 session/control surface:
POST /v1/sessionsnow accepts a safe whitelist of v0.6 fields includinggroupId,hibernateAfterMs,eventBufferSize,memory,subagents,interruptImmuneToolsandresponseFormatwith camelCase/snake_case compatibility.POST /v1/sessionsalso accepts bounded safemessagesJSON import foruser/assistant/tool_resulthistory continuation and rejects public JSONskillSelectormodule injection.GET /v1/sessions/:id/eventssupports session replay viasince,typesandLast-Event-ID; status/stats exposelastEventIndexandeventBufferCount.GET /v1/groups/:group_id/eventsstreams group-level SSE events viaCMDC.EventBus.subscribe_group/1, addingsessionIdto each event data payload.POST /v1/sessions/:id/tools/batchexposes allowlisted atomic attach/detach/replace for core batch tool APIs and surfacestools_updatedto SSE/WS clients.PATCH /v1/sessions/:id/plugins/:plugin/optscallsCMDC.update_plugin_opts/3behind:plugin_opts_allowlistand translatesplugin_opts_updated.POST /v1/sessions/:id/checkpointsandPOST /v1/sessions/resumeexpose checkpoint/resume without accepting client-supplied checkpoint backend modules.- Admin-only
/v1/provider_profilesendpoints and startup:provider_profilesconfig register Provider Registry profiles without accepting JSONresolverFn; responses expose option keys only.
- EventTranslator v0.6 event surface:
- Current core shapes for
model_switchedandtool_call_unknownare now first-class while legacy shapes remain accepted. - Control/runtime events now include model switch failures, batch tool updates, tool metrics/blocks, stream errors, context overflow, prompt queue/drop/reject, agent resume, abort tool kills, compaction and subagent events.
- Persistence/memory events now include
auto_checkpoint_savedand episodic memory plugin events. - SSE supports
?mode=audit, projecting covered core events throughCMDC.AuditEventintoaudit_eventpayloads while skipping noisy token delta events.
- Current core shapes for
- Workflow / AgentOps event adapter:
CMDCGateway.WorkflowEventAdaptertranslatescmdc_orchestrator 0.6RunEvent/human_task ledger shapes from plain maps, tuples or structs without depending onCMDCOrchestratorat compile time.- Standard workflow events now cover run/node lifecycle, fork/join node lifecycle, signal edges and human_task create/progress/decision/ complete/timeout/fail events.
GET /v1/workflows/runs/:run_id/eventsprovides read-only paginated replay from a server-configured:workflow_event_source; without a source it returnsworkflow_event_source_not_configured.
Changed
- Phase 20 upgrade path targets
cmdc_gateway 0.6.0directly. The A2A terminal/webhook fixes are folded into the minor release; publish a0.5.1hotfix only if an existing production deployment needs the A2A fix before the full core 0.6 surface is ready. - Hex dependency baseline moves to
cmdc ~> 0.6;:telemetryis now declared directly because gateway emits webhook dead-letter telemetry itself. - Agent Card now advertises core 0.6 group events, plugin opts update, checkpoint/resume, Provider Registry control-plane endpoints and audit projection plus A2A JSON-RPC, webhook, task polling, workflow replay, session replay, batch tool control and safe message import capabilities.
- Session/status/stats JSON includes group/workspace metadata and core
token_usage/cost_usdsummaries while preserving existing dashboard fields. - REST/WS control calls now preserve explicit
autoResume: false; model switch accepts strictproviderOpts; abort accepts snake_casekill_toolsandclear_queue. - README/API docs now document the
cmdc ~> 0.6install baseline, 0.6 session options, SSE replay, group SSE, workflow replay, plugin opts, checkpoint/ resume, Provider Registry, A2A/webhook endpoints and SDK compatibility notes.
Compatibility
- Existing REST/SSE/WebSocket clients remain compatible with 0.5-era fields and status codes; 0.6 additions are new fields or new endpoints.
/v1/sessions/:id/toolsremains callback tool registration. Core Tool batch attach/detach/replace lives at/v1/sessions/:id/tools/batch.- Public JSON still rejects module/resolver/backend injection paths; SDKs should move those concerns to server-side Elixir configuration.
Security
- Session creation now validates
workingDiragainst a server-sideCMDCGateway.WorkingDirPolicyroot before starting an Agent. The gateway rejects..,~, filesystem-root escape, non-directory targets and symlink path segments, socmdc 0.6Sandbox.Localvirtual mode cannot be bypassed by choosing an unsafe sandbox root. - Batch tool control is guarded by
:tool_module_allowlist; attach/replace do not accept unknown modules or arbitrary JSON-created atoms. - Gateway deliberately does not expose public JSON for
skill_selector, global telemetry audit streams, group replay, orCMDC.monitor/1process monitors.
Fixed
- A2A
translate_event/2now handles the currentEventTranslator.translate/1return shape ({:ok, event_type, data}) and maps terminal{:agent_end, messages, usage}events correctly forsendSubscribe/ webhook completion. - REST and WebSocket
respondnow callCMDC.user_respond/3, preserving the coreagent_resumedevent instead of broadcasting:user_respondedby hand. - Router JSON field lookup now preserves explicit
falsevalues instead of treating them as missing.
[0.5.0] - 2026-05-31
Minor release — Phase 18F RAG / GraphRAG AgentOps trace sync。
已发布到 hex.pm + hexdocs,checksum
e67f19ad3a68454057fe7798d3779735ae947493902fc7ed9a96664a7810bef2。
Added
CMDCGateway.EventTranslator支持cmdc_rag_arcanaPhase 18 三元 plugin events,并映射为标准 SSE/WebSocket event:rag_acl_blocked、rag_retrieved、rag_answered、rag_citation_used、rag_pipeline_step、rag_ingestion_progress、rag_reembed_progress、rag_graph_progress、rag_graph_audit、rag_eval_progress。- RAG tool 成功结束时,
tool_execution_end继续保留兼容字段result, 同时新增rag结构化摘要,覆盖 citation、grounding、 pipelineRunSummary、graphEvidence、graphStatus 与 ingestStatus。
Security / Privacy
- RAG trace payload 默认移除
text/chunk_text/content/prompt/chunks/raw_results/results等正文或 chunk 字段,只保留 provenance、计数、状态与治理摘要。
Changed
- Hex 依赖基线升级为
cmdc ~> 0.5。
[0.4.2] - 2026-05-18
Patch release — repository URL normalization + documentation cleanup. No code changes, no behavior changes.
- Repository URL →
https://github.com/tupleyun/cmdc_gateway - Module moduledoc + inline comments rewritten to neutral technical descriptions (removed internal task numbering)
[0.4.1] - 2026-05-16
Patch release — 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 兜底查询
补全 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 持久化
把 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 客户端示例
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 | v0.4.0 | 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 模式落地,
补齐 sync / SSE / webhook 三大长任务交互入口;
依赖升级到 cmdc ~> 0.4,自动获得核心库 v0.4 全部能力(Checkpoint /
Backend / Skill v2 / 3 新内置 Plugin / Telemetry)。No breaking changes
against v0.3.x。
Added — A2A Webhook 异步交互模式
A2A 协议 4 种交互机制中,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
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
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
CMDCGateway.AgentCard— 生成 A2A 兼容的 Agent Card JSON(capabilities + endpoints)GET /.well-known/agent.json— 免认证暴露 Agent Card,供其他 A2A Agent 发现
Added — Guardrails & Safety Control Plane
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— 中段注入指令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 透传
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 个单元测试 + 集成测试,全部通过