4.4 KiB
ADR: Unified Bridge Entry Points for APP Traffic
Status
Accepted
Date
2026-04-11
Last Reviewed
2026-04-13
Context
xworkmate-bridge 代理 app 流量到独立 upstream ACP / gateway 服务,但如果把这些 upstream 直接暴露成 app-facing entrypoint,会带来几个问题:
- app 必须知道 provider-specific 或 gateway-specific hostname
- routing truth 会在 URL 形状与 bridge 逻辑之间分裂
- auth contract 更难保持统一
- upstream implementation detail 会泄漏到 app shell / module 心智
当前 app 主链已经收敛到 assistant + settings 两个 surface,因此 bridge 入口也必须保持同一口径:统一公共入口,bridge 内部负责 provider / gateway 路由细节。
Decision
For APP traffic, the canonical public entry point remains:
https://xworkmate-bridge.svc.plus
Canonical app-facing contract families are:
- ACP control-plane
POST /acp/rpcGET /acp
- Gateway runtime methods
xworkmate.gateway.connectxworkmate.gateway.requestxworkmate.gateway.disconnect
Bridge-owned metadata may still include:
providerCataloggatewayProvidersresolvedExecutionTargetresolvedProviderIdresolvedGatewayProviderId
这些字段属于 bridge 返回给 app 的 routing/capability metadata,不属于 app shell taxonomy。
换句话说:
- app 可以消费这些字段来展示当前可用能力或执行结果
- app 不应该把 provider/gateway 矩阵抬升成新的顶层模块、别名页面、或直接 URL 合同
The APP should not depend on provider-specific public URLs such as:
/codex/acp/rpc/opencode/acp/rpc/gemini/acp/rpc/openclaw/
OpenClaw task submit now uses the same /acp/rpc HTTP surface with explicit
routing metadata. Capabilities, routing, gateway control-plane methods, cancel,
and close remain on /acp or /acp/rpc.
If the bridge reports execution-target metadata such as single-agent
or gateway, the app should treat those values as routing
results, not as shell-level surface categories.
If the bridge reports gateway provider IDs such as openclaw, the
app should treat them as bridge-owned gateway backend identifiers, not as
independent app entrypoints.
APP-facing routing should be modeled in two layers:
executionTargetagentgateway
agentProviderscodexopencodegemini
gatewayProvidersopenclaw
For APP integration, gatewayProviders is the stable gateway-facing concept.
APP and UI code should consume bridge state in two phases:
acp.capabilities- discover
availableExecutionTargets - discover
agentProviders - discover
gatewayProviders
- discover
xworkmate.routing.resolve- determine
resolvedExecutionTarget - determine
resolvedProviderIdorresolvedGatewayProviderId - determine unavailable state
- determine
The APP should treat resolvedProviderId and resolvedGatewayProviderId as
mutually exclusive routing outputs depending on resolvedExecutionTarget.
Gateway access remains bridge-owned via JSON-RPC methods:
xworkmate.gateway.connectxworkmate.gateway.requestxworkmate.gateway.disconnect
Upstream authentication is unified for both ACP and gateway routes:
Authorization: Bearer $INTERNAL_SERVICE_TOKEN
Consequences
Positive
- APP integration stays stable behind one public origin
- provider and gateway topology remain bridge concerns
- auth handling remains consistent across ACP and gateway forwarding
- app architecture docs can stay focused on
assistant + settingsinstead of a fake module matrix
Trade-offs
- docs must clearly separate canonical app contracts from independent upstream services
- bridge metadata must be documented as metadata, not as surface taxonomy
Path Naming Guidance
Use these terms consistently:
canonical app-facing path:/acp/rpcand/acpOpenClaw task submit:/acp/rpcwithrouting.explicitExecutionTarget=gatewayandrouting.preferredGatewayProviderId=openclawgateway runtime method family:xworkmate.gateway.*independent upstream service: provider / gateway runtime behind bridge-owned compatbridge-owned routing: provider / gateway selection performed inside bridgerouting metadata: execution target and resolved provider/gateway identifiers returned to the app
Avoid describing upstream URLs, provider IDs, or gateway mode IDs as if they were independent app modules or alternate primary entrypoints.