在 Hermes Agent 上部署 A2A:Docker 网关参考栈
在生产环境中运行 A2A 意味着桥接两个从未被设计为相互通信的协议——并在一个网关后面完成认证、租户隔离和流式传输而不丢失 token。这个参考栈解决了阻止 A2A 部署的三个问题:协议转换(JSON-RPC 2.0 到 OpenAI 兼容的 chat completions)、流式协调(A2A 工件 SSE 到 Hermes 运行事件 SSE)以及多租户安全(每次查询的 PostgreSQL 行级安全)。如果你需要不同框架上的代理相互委托工作,这里的模式就是部署路径。
关键要点
- 3 层架构,1 个 Docker Compose 栈 — SilvaEngine Gateway 负责传输与鉴权,A2A Daemon Engine 负责协议逻辑,HermesAgentHandler 桥接到 Hermes Agent 的 OpenAI 兼容 API。docker-a2a-hermes-agent-gateway 仓库将三者打包在一起。
- 单端口 5 个协议面 — JSON-RPC 2.0、GraphQL、SSE 流、SSE 推送和 Agent Card 发现,全部位于端口 8765 上单个网关之后,采用 JWT 或 AWS Cognito 鉴权。
- PostgreSQL 行级安全强制租户隔离 — 复合键
partition_key = "{endpoint_id}#{Part-Id}"通过四张 A2A 表上的 RLS 策略在数据库层面强制执行,而非仅依赖应用代码。 - A2A SDK v2 的单消息约束塑造了流式架构 — 桥接将 token 分块实时发送到 SSE,并在流完成后将单个累积 Message 发送到 SDK EventQueue,避免
InvalidAgentResponseError。 - 跨 5 个脚本的 15 项端到端测试检查 — 从非流式冒烟测试到完整的 SSE 流式管线并验证 HTTP 回退,全部可用
pip install requests运行。
Agent2Agent Protocol(A2A)定义了 AI 智能体如何通过 JSON-RPC 2.0 互相发现、委派和流式传输任务。Hermes Agent(由 Nous Research 开发)在 /v1/chat/completions 暴露 OpenAI 兼容的 API Server,并在 /v1/runs 和 /v1/runs/{id}/events 提供基于 runs 的 SSE 流式接口。两者并不使用同一种语言。A2A 发送带有结构化 parts 的 message/send;Hermes 接收的是聊天补全负载。A2A 通过 SSE 流式传输任务制品;Hermes 通过 run 事件流式传输 token 增量。
docker-a2a-hermes-agent-gateway 仓库以单一容器镜像和 docker compose 栈弥合了这一鸿沟。它运行 SilvaEngine Gateway,仅注册 a2a_daemon_engine 模块,暴露完整的 A2A 协议面,并通过 HTTP + SSE 将 A2A 任务桥接到一个 Hermes Agent API Server 实例。状态持久化到内置的 PostgreSQL 后端,并通过行级安全实现租户隔离。
本文梳理了三层架构、从 A2A 客户端到 Hermes 再返回的请求生命周期、配置与部署模式,以及在生产环境中于 Hermes Agent 上运行 A2A 的运维关注点。这是一份参考部署指南——通用模式(网关介导的、桥接到任意智能体框架的 A2A)才是主题;Docker 栈是具体的实现范例。
三层架构
该栈将关注点分离为三层,每层由一个独立组件负责:
网关是唯一常驻服务。Hermes 和 PostgreSQL 都是按需启用的兄弟服务——将它们打包即可获得自包含栈,或者关闭这些 profile,将 HERMES_API_URL 和 PG_HOST 指向外部实例。这对生产环境很重要:你可以在自己的 VPC 中运行网关,并将其指向托管的 Postgres(RDS、Cloud SQL)以及运行在别处 GPU 节点上的 Hermes 实例。
第 1 层:SilvaEngine Gateway — 传输与鉴权
SilvaEngine Gateway 是一个 FastAPI 网关,用于对已安装模块进行经过鉴权的进程内访问。它通过可配置的 YAML 路由清单暴露模块的 GraphQL 和 REST 路由——添加新模块只需修改清单,无需编写任何网关 Python 代码。在本栈中,仅注册了 A2A Daemon Engine。
网关负责:
- 鉴权 — 本地 JWT(HS256)或 AWS Cognito(RS256 + JWKS),由
GATEWAY_AUTH_PROVIDER选择 - 路由 — YAML 清单将 URL 路径映射到模块分发函数
- SSE 客户端生命周期 —
sse_manager按模块解析并管理长生命周期客户端连接 - 速率限制 — 基于 IP 的内存速率限制(
GATEWAY_RATE_LIMIT请求 /GATEWAY_RATE_WINDOW秒) - 线程池分发 — 同步模块分发函数在可配置线程池中运行(
GATEWAY_DISPATCH_WORKERS,Docker 镜像默认 32)
网关根据 URL 路径段和 Part-Id 请求头构建 partition_key = "{endpoint_id}#{Part-Id}"。每个租户范围的请求都需要该头。位于 /{ep}/.well-known/agent-card.json 的 Agent Card 端点按 A2A 规范是公开的(无需鉴权),但仍需要 Part-Id,因为卡片是按分区解析的。
第 2 层:A2A Daemon Engine — 协议逻辑
a2a_daemon_engine 不是一个独立服务。它通过 main.py 中的 deploy() 作为已注册的网关模块加载,声明了三个面向网关的入口点:
| 入口点 | 网关路由 | 方法 | 用途 |
|---|---|---|---|
a2a_core_graphql |
POST /{ep}/a2a_core_graphql |
POST | 针对智能体、任务、消息、设置的 GraphQL CRUD |
a2a |
POST /{ep}/a2a |
POST | A2A JSON-RPC 协议(message/send、tasks/get、tasks/cancel、tasks/list) |
sse_message |
POST /{ep}/a2a_sse |
POST | A2A JSON-RPC 消息 + 推送到 SSE 客户端 |
网关额外暴露 GET /{ep}/a2a_sse 用于 SSE 流。在生产环境中,守护进程不监听自己的端口,也不运行自己的 HTTP 服务器。所有传输、鉴权和 SSE 客户端生命周期均由网关负责。
守护进程提供:
- A2A SDK v1.0 — 基于 HTTP 的 JSON-RPC,构建于官方 A2A SDK 服务端模式
- 公开 Agent Card 位于
/.well-known/agent-card.json,支持 ETag 和 Last-Modified - 任务状态机 —
submitted→working→input-required|completed|failed|canceled - 双后端持久化 — DynamoDB(PynamoDB)或 PostgreSQL(SQLAlchemy + Alembic)。Docker 镜像强制使用 PostgreSQL。
- 多租户隔离 — 复合分区键(
{endpoint_id}#{part_id})配合 PostgreSQL 行级安全 - 可插拔 LLM 处理器 — 在智能体注册表中按智能体选择
module_name/class_name
第 3 层:HermesAgentHandler — 桥接
Hermes 桥接处理器(a2a_daemon_engine/handlers/a2a_hermes_handler.py)是唯一框架特定的代码。它实现了 ask_model() 接口:接受 A2A 消息 parts 和上下文,调用 Hermes Agent API Server,将响应转换回 A2A 消息 parts,对于流式情况,将 token 增量转发到 SSE 通道。
该处理器支持两种执行模式:
非流式映射到 Hermes API Server 的 POST /v1/chat/completions — 即 OpenAI 兼容端点。请求将转换后的 A2A 消息 parts 作为聊天补全负载携带。Hermes 处理请求并返回单个响应。处理器将响应转换为带 ROLE_AGENT 的 A2A Message 并发送到 SDK EventQueue。客户端收到一个包含完整智能体文本的 JSON-RPC 响应。
流式映射到 POST /v1/runs 以创建 run,然后打开到 GET /v1/runs/{id}/events 的 SSE 连接。Hermes 在事件发生时流式传输:token 增量(message.delta)、推理元数据(reasoning.available)、工具调用/结果通知、审批请求(approval.required)以及生命周期事件(run.created、run.completed、run.failed)。处理器在后台线程中运行排空循环。每个 message.delta 事件被推送到网关的 SSE 管理器,实时投递给已连接的客户端。当 run.completed 到达时,累积文本作为单个 A2A Message 发送到 SDK EventQueue。
请求生命周期
一个带 stream=true 的 message/send 需经过八个步骤:
1. Client POST /{ep}/a2a {jsonrpc, method:"message/send", params}
Headers: Authorization: Bearer *** Part-Id:
2. Gateway auth (local JWT / Cognito) → route match from routes.yaml
→ partition_key = "{ep}#{Part-Id}"
3. a2a_daemon dispatch_a2a → A2ADaemonExecutor
→ resolve_agent(): agent metadata (DB) > setting dict > Config (env)
4. Handler HermesAgentHandler (A2A_AI_AGENT_MODULE / _CLASS)
5. Hermes POST {HERMES_API_URL}/v1/runs (Bearer HERMES_API_KEY)
GET {HERMES_API_URL}/v1/runs/{id}/events (SSE)
6. Broadcast token chunks → subscribers on GET /{ep}/a2a_sse
7. Persist task + messages written to PostgreSQL (a2a_* tables, RLS-scoped)
8. Response accumulated reply also returned in the HTTP JSON-RPC result 第 8 步很关键:即使在流式情况下,HTTP 响应也携带完整回复。错过 SSE 帧的客户端仍可回退到 HTTP 响应。端到端测试套件(test_hermes_sse_live.py)在其第 06 步中显式验证了这一回退。
智能体解析优先级
配置解析遵循优先级链:智能体元数据(DB)→ setting dict → Config 默认值(环境变量)。按智能体的覆盖优先于全局默认值。两个智能体可以指向不同框架——一个指向 Hermes 处理推理密集型任务,另一个指向不同处理器处理工作流编排任务——而 A2A 协议面对调用方智能体时看起来完全相同。
对于由 Hermes 支持的智能体,存储在 a2a_agents 表中的元数据如下:
{
"module_name": "a2a_daemon_engine.handlers.a2a_hermes_handler",
"class_name": "HermesAgentHandler",
"hermes_api_url": "http://127.0.0.1:8642",
"hermes_api_key": "hermes-local-key",
"hermes_model": "hermes-agent",
"hermes_timeout": 300.0
}环境变量默认值(HERMES_API_URL、HERMES_API_KEY、HERMES_MODEL)让桥接在没有数据库智能体记录时也能到达 Hermes——当不存在智能体记录时,a2a_ai_agent_utility.py 中的 resolve_agent() 函数回退到环境变量。这意味着你可以启动栈并直接发送 message/send 而无需注册任何智能体,它将使用环境默认值路由到 Hermes。
A2A 状态映射
桥接将 Hermes SSE 事件映射到 A2A 任务状态。这张表是桥接的核心——每个框架集成都会产生一张等价表:
| Hermes SSE 事件 | A2A 任务状态 | 桥接动作 |
|---|---|---|
run.created(返回 run_id) |
WORKING |
注册 run_id 以支持取消 |
message.delta |
WORKING |
累积 token;按分块发送到 SSE |
reasoning.available |
WORKING |
推理元数据 — 不发送 token |
tool.call / tool.result |
WORKING |
仅工具执行元数据 |
approval.required |
INPUT_REQUIRED |
发送审批分块;存储 pending_approval |
run.completed |
COMPLETED |
设置流事件;累积最终文本 |
run.failed |
FAILED |
发送错误分块;设置 FAILED 状态 |
POST /v1/runs/{id}/stop |
CANCELED |
通过 tasks/cancel 外部取消 |
POST /v1/runs/{id}/approval |
(继续 run) | 通过 operation="approval_response" 解决 |
a2a_daemon_engine 仓库中的 HERMES_INTEGRATION.md 文档记录了确切的 Hermes 事件格式、配置键和端到端流程细节。
跨智能体边界的人在回路审批
Hermes 支持人在回路审批门控——当智能体需要执行敏感操作的许可时,它会暂停并发出审批请求。桥接将其转换为 A2A INPUT_REQUIRED 状态,向调用方智能体(或人类操作员)发出需要输入的信号。响应通过 POST /v1/runs/{id}/approval 返回,run 随即继续。
这正是桥接模式体现价值之处。A2A 将 INPUT_REQUIRED 定义为一等任务状态。Hermes 有自己的审批机制。桥接将两者映射,而调用方智能体——它本身可能是运行在完全不同框架上的 A2A 客户端——看到的是标准协议状态转换,而非 Hermes 特有的细节。一条智能体委派链可以包含一个需要人工审批的步骤(采购授权、数据访问决策、报价审批),而 A2A 协议会透明地跨越框架边界传递该门控。
A2A SDK v2 约束与双路修复
A2A SDK v2(a2a-sdk==1.0.2)对 on_message_send 路径施加了两项约束,塑造了桥接实现:
- 仅单个 Message。 向 SDK EventQueue 发送多个
Message对象会引发InvalidAgentResponseError: Multiple Message objects received. - 无 TaskStatusUpdateEvent。 状态事件会引发
InvalidAgentResponseError: Received TaskStatusUpdateEvent in message mode.
朴素的桥接会为每个 token 增量发送一个 Message——这是自然的流式模式。SDK 拒绝这样做,并拒绝在 message/send 路径上的状态事件(WORKING、COMPLETED)。
修复方案是双路输出通道:
- SSE(网关管理): Token 分块实时推送到 SSE。已连接的客户端实时看到流式输出。状态事件(WORKING、COMPLETED、FAILED)也仅发送到 SSE。
- SDK EventQueue: 流完成后,将一个包含完整响应文本的累积
Message发送到 SDK EventQueue。这是 JSON-RPCmessage/send响应所返回的内容。
客户端通过 SSE 获得实时流式输出,并通过 SDK 获得干净的单消息 JSON-RPC 响应。两个通道都能工作;都不违反 SDK 约束。
单端口上的协议面
网关在单个端口(默认 8765)上暴露五个协议面:
| 协议 | 路由 | 鉴权 | 用途 |
|---|---|---|---|
| GraphQL | POST /{ep}/a2a_core_graphql |
是 | A2A 核心查询/变更(智能体、任务、消息、设置) |
| JSON-RPC 2.0 | POST /{ep}/a2a |
是 | A2A 协议:message/send、tasks/get、tasks/cancel、tasks/list |
| SSE(流) | GET /{ep}/a2a_sse |
是 | 长生命周期的按分区 A2A 任务事件流 |
| SSE(推送) | POST /{ep}/a2a_sse |
是 | JSON-RPC 消息 + 推送到已连接的 SSE 客户端 |
| Agent Card | GET /{ep}/.well-known/agent-card.json |
公开 | A2A 发现文档(仍需 Part-Id 头) |
测试工具使用的 JSON-RPC message/send 参数结构:
{
"message": {
"role": "ROLE_USER",
"parts": [{ "text": "Say hello from A2A" }]
},
"metadata": {
"operation": "task_execution",
"agent_uuid": "a2a-hermes-agent",
"stream": true,
"task_data": { "task_id": "my-task-001", "task_type": "hermes_test" },
"system_prompt": "You are a concise assistant.",
"conversation_history": []
}
}metadata.operation 字段选择执行路径:task_execution 用于支持流式的智能体 run,message_response 用于非流式聊天。agent_uuid 指向注册表中的特定智能体。stream 标志启用 SSE 广播。task_data.task_id 是调用方提供的 id,用于 tasks/get 和 tasks/cancel。
SSE 是按分区的,而非按任务的。{ep}#{Part-Id} 中的每个任务都广播给该分区的所有订阅者。操作顺序很关键:在发送消息之前先连接 SSE 监听器,否则会错过早期的 token 分块。
持久化与多租户
Docker 镜像强制 db_backend=postgresql — 不支持 DynamoDB。守护进程使用字面、无前缀的表名:
| 表 | 存储 |
|---|---|
a2a_agents |
智能体记录 + 按智能体的处理器/模型元数据 |
a2a_tasks |
任务生命周期 + 状态 |
a2a_messages |
每个任务的消息轮次 |
a2a_settings |
按分区的设置 dict |
由于名称无前缀,请不要将 PG_DB 与使用相同名称的其他模块共享。
租户隔离使用 PostgreSQL 行级安全。会话变量 app.tenant_id 被设置为请求的 partition_key("{endpoint_id}#{Part-Id}"),RLS 策略将每个查询限定到该值。当 initialize_tables=1 时,表和策略在网关启动时自动创建。这意味着应用代码中遗漏的 partition_key 过滤器不会泄漏跨租户行——数据库强制了边界。
RLS 实现位于 a2a_daemon_engine/utils/rls.py(set_rls_context 和 create_rls_policies)以及迁移 0005_enable_rls_policies 中。set_rls_context 函数在连接上运行每请求的 SET app.tenant_id,create_rls_policies 在全部四张 A2A 表上启用并强制 RLS 以及 tenant_isolation 策略。在 DynamoDB 模式下 RLS 不生效。
使用 Docker Compose 部署
该栈有一个常驻服务和两个可选的按需启用兄弟服务:
| 服务 | 容器名 | 是否常驻? | Profile | 用途 |
|---|---|---|---|---|
a2a-gateway |
a2a-hermes-gateway |
是 | — | SilvaEngine Gateway(仅 A2A 路由)+ Hermes 桥接 |
postgres |
a2a-postgres |
可选 | postgres |
内置 PostgreSQL 持久化后端 |
hermes |
container-hermes |
可选 | hermes |
内置 Hermes Agent(OpenAI 兼容 API + 仪表盘) |
COMPOSE_PROFILES 是控制两个兄弟服务的单一开关:
| 值 | 启动的服务 |
|---|---|
| 空 | 仅网关(外部 Postgres + 外部 Hermes) |
postgres |
网关 + 内置 Postgres |
hermes |
网关 + 内置 Hermes(外部 Postgres) |
postgres,hermes |
网关 + 内置 Postgres 和 Hermes(默认) |
当兄弟服务被内置时,将其主机引用指向服务名:PG_HOST=postgres 和 HERMES_API_URL=http://hermes:<API_SERVER_PORT>。当兄弟服务为外部时,将它们指向你自己的实例(例如 PG_HOST=host.docker.internal、HERMES_API_URL=http://host.docker.internal:8642)。
快速开始
cp .env.example .env
# Fill in: JWT_SECRET_KEY, ADMIN_PASSWORD, API_SERVER_KEY,
# HERMES_API_KEY (= API_SERVER_KEY), HERMES_MODEL_PROVIDER + provider key, HERMES_MODEL
mkdir -p www/hermes www/projects
DOCKER_BUILDKIT=1 docker compose build
docker compose up -d # COMPOSE_PROFILES=postgres,hermes is the default
docker compose ps # wait for (healthy)
curl -f http://localhost:8765/health
pip install requests
python test_hermes_hello.py # end-to-end smoke testsilvaengine_gateway 和 a2a_daemon_engine 均通过 pip 从 git 安装到镜像中(不挂载主机源码)。镜像是通用的、完全由环境变量驱动——不内嵌任何密钥。模块通过 git+https 从 ideabosque 下的公开 GitHub 仓库克隆——无需凭据或 SSH 部署密钥。
.env 行内注释陷阱
Docker Compose 的 env_file 解析器不会去除行内注释。像这样一行:
HERMES_API_KEY=hermes-local-key # token for Hermes会将 HERMES_API_KEY 设为字面字符串 hermes-local-key # token for Hermes(注释被包含在内),从而静默破坏鉴权。规则是:在任何 KEY=value 行的值之后不要放任何内容。将说明放在变量上方的独立 # 注释行中。
验证:跨 5 个脚本的 15 项端到端检查
该栈附带独立的 Python 测试工具(唯一依赖:requests)。它们加载 ./.env、解析或铸造网关 JWT,并与运行中的栈通信:
| 脚本 | 类型 | 功能 |
|---|---|---|
test_hermes_hello.py |
冒烟 | 非流式 message/send,打印回复 |
test_hermes_hello_sse.py |
冒烟 | 通过 SSE 流式回传一个提示 |
test_hermes_gateway_live.py |
E2E 套件 | 9 项检查:Hermes 健康、网关健康、agent card、GraphQL ping、message/send、tasks/get、tasks/list、tasks/cancel、失败路径 |
test_hermes_sse_live.py |
E2E 套件 | 6 项检查:健康 ×2、SSE 连接、实时 token 分块、COMPLETED 状态、HTTP 回退 |
test_hermes_chatbot.py |
交互式 | 针对 A2A 界面的 REPL,带实时 SSE 流式 |
所有非交互式脚本按步骤打印 PASS/FAIL 并在失败时以非零退出,因此可用作 CI 门控。单元测试套件(test_hermes_handler.py)通过 httpx.MockTransport 模拟 HTTP 运行 24 项测试——无需任何服务。
运维模式
路由变更无需重新构建
routes.yaml 以只读方式绑定挂载到容器中。编辑主机文件并重启网关进程——无需重新构建:
make restart上游变更之后
由于 silvaengine_gateway 和 a2a_daemon_engine 在构建时通过 pip 从 git 安装,上游变更需要使用 --no-cache 重新构建,以便 git 层重新克隆最新的 @main:
DOCKER_BUILDKIT=1 docker compose build --no-cache
docker compose up -d --force-recreate没有版本固定——@main 是一个移动目标。如需可复现性,请在 requirements-modules.txt 中固定标签或提交。
扩展到超过一个 worker
内存中的任务状态、速率限制计数器和 SSE 客户端注册表都是按进程的。当 GATEWAY_WORKERS > 1 时,切换到共享后端(GATEWAY_TASK_BACKEND=dynamodb、GATEWAY_RATE_LIMIT_BACKEND=dynamodb,外加 region_name 和 aws_* 凭据),并为 SSE 使用粘性会话。默认配置启动一个 Uvicorn 进程。
需要更改的安全默认值
JWT_SECRET_KEY=change-me-in-production— 用openssl rand -hex 32替换ADMIN_PASSWORD=change-me— 替换为真实密码POSTGRES_PASSWORD=silvaengine— 替换为真实密码GATEWAY_CORS_ORIGINS=*允许任意无凭据来源。如需 cookie/凭据,请设置显式列表。- 内置 Hermes 挂载主机 Docker socket(
/var/run/docker.sock)。这对该容器内的任何内容而言实际上等同于主机 root。仅在受你控制的主机上运行hermesprofile,如果智能体不需要启动容器,请移除该挂载。 - Hermes 仪表盘默认在端口 9119 启用,且 basic-auth 凭据为空。在暴露主机之前设置
HERMES_DASHBOARD_BASIC_AUTH_*或将端口绑定到 localhost。 - RLS 是租户边界。能设置任意
Part-Id的调用方可读取该分区数据——在你置于其前的任何前端中,将Part-Id视为与授权相关的输入。
这带来的能力
三层栈赋予你三项难以从零组装的能力:
1. 无需重写 Hermes 即可实现 A2A 协议合规。 任何 A2A 客户端都可以通过其 Agent Card 发现由 Hermes 支持的智能体,通过 message/send 发送任务,通过 SSE 流式接收响应,并通过标准 A2A 状态跟踪任务生命周期。客户端不知道远端智能体运行的是 Hermes——它看到的是一个带 JSON-RPC 接口的 A2A 端点。
2. 单网关多租户智能体服务。 Part-Id 头配合 PostgreSQL RLS 意味着单个网关实例以硬性的数据库级隔离服务多个租户。每个租户拥有自己的智能体注册表、任务历史和消息存储——全部位于相同的四张表中,由 partition_key 限定范围。
3. 跨智能体边界的人在回路审批。 Hermes 审批门控映射到 A2A INPUT_REQUIRED 状态。一条智能体委派链可以包含一个需要人工审批的步骤,而 A2A 协议将这一状态转换回传给发起智能体或操作员——无论链中每个智能体运行在哪个框架上。
该参考实现还支持用于无服务器 A2A 的 AWS Lambda 分发、带双向流式的实验性 gRPC 传输,以及双后端持久化(DynamoDB 或 PostgreSQL)。a2a_daemon_engine 仓库及其 Hermes 集成指南包含完整实现、配置参考和状态映射细节。SilvaEngine Gateway 仓库记录了路由清单系统、鉴权提供者和模块自动初始化。
相关阅读
- MCP + A2A:每个生产级智能体 AI 系统背后的两个协议 — MCP(智能体到工具)与 A2A(智能体到智能体)在双层协议栈中的互补角色
- 将 A2A 与现有智能体框架集成:Hermes Agent 演示 — 通用桥接模式及其如何应用于 OpenClaw 和 Hermes 之外的其他框架
- MCP 模块代码规范 — 生产级智能体模块的结构化模式,同样适用于 A2A 处理器代码
一家中端分销商需要报价智能体与目录智能体对话,目录智能体再与库存智能体对话——每个智能体由不同框架支持,每个智能体由不同团队拥有。A2A 为这些智能体提供了共享协议。桥接层让 Hermes Agent 无需重写内部实现即可参与其中。docker-a2a-hermes-agent-gateway 将该桥接打包为单一容器镜像,具备 PostgreSQL 持久化、RLS 多租户和 15 项端到端测试检查。
申请范围明确的构建
一周的发现阶段。你将获得系统清单、工作流映射和固定范围——无论你是否选择与我们合作构建。
想为您的系统构建这个吗?
这里的每份文档都来自真实的生产工作。如果您有目标系统和工作流想法,我们可以在一周内确定范围。
申请定制开发为期一周的发现阶段。您会拿到系统清单、工作流地图和固定范围——无论您最终是否与我们合作开发。