# ReachAI Physical Split Route Ownership > Date: 2026-06-29 > Scope: first physical split with one shared MySQL database ## Principles Public route lifecycle classes and frontend-banned aliases are summarized in `docs/architecture/public-route-contracts.md`; this document keeps the detailed owner map. - `reachai-control-service` is the only public API/BFF entry in the first phase. - Frontend, embed integrations, and SDK registration clients keep their current public paths. - `reachai-runtime-service` and `reachai-capability-service` expose internal routes for service-to-service calls. - Keeping one MySQL database does not mean shared write ownership. Each table family has one owning service. - Temporary same-database reads must be documented before use and removed before a later database split. ## Public Routes Kept By Control | Public route family | Public owner | Internal owner after extraction | Notes | | --- | --- | --- | --- | | `/api/registry/projects/{projectCode}/agent-graphs/sync` | `reachai-control-service` | `reachai-runtime-service` | SDK Agent Graph sync writes Runtime-owned `ai_workflow` | | `/api/registry/projects/{projectCode}/pages/register` | `reachai-control-service` | `reachai-control-service` | SDK page/action catalog registration writes Control-owned embed catalog tables | | `/api/registry/**` | `reachai-control-service` | `reachai-capability-service` | SDK register, heartbeat/offline, instance governance, capability sync, diff, review/apply; excludes Agent Graph sync and registry page catalog | | `/api/capabilities/**` | `reachai-control-service` | `reachai-capability-service` | Capability asset catalog | | `/api/tools/**` | `reachai-control-service` | `reachai-capability-service` | Tool catalog and definitions | | `/api/api-assets/**` | `reachai-control-service` | `reachai-capability-service` | API asset catalog | | `/api/api-graph/**` | `reachai-control-service` | `reachai-capability-service` | SDK/API graph | | `/api/tool-retrieval/**` | `reachai-control-service` | `reachai-capability-service` | Tool retrieval settings | | `/api/scan-projects/**` | `reachai-control-service` | `reachai-capability-service` | Scan project catalog | | `/api/skill-mining/**` and `/api/capability-mining/**` | `reachai-control-service` | `reachai-capability-service` | Historical public route names stay compatible; Capability now owns precheck, draft generation/list/status/publish, trace/canvas extraction, and demo trace helpers locally | | `/api/runtime/agents/**`, `/api/runtime/evals/**`, `/api/runtime/interactions/**`, and `/api/workflows/credentials/**` | `reachai-control-service` | `reachai-runtime-service` | Runtime-facing public semantics for Agent execution, evaluation, human approval, and Workflow credential routes. Historical `/api/agent/**` aliases stay compatible but are not the frontend main path. | | `/api/chat/**` | `reachai-control-service` | `reachai-runtime-service` | Lightweight runtime chat | | `/api/agents/**` | `reachai-control-service` | `reachai-runtime-service` | Agent entries and workflow bindings | | `/api/workflows/**` | `reachai-control-service` | `reachai-runtime-service` | Workflow Studio, versions, AI coding, debug | | `/api/runtime/**` and `/api/runtimes/**` | `reachai-control-service` | `reachai-runtime-service` | Runtime registry and debug sessions | | `/api/traces/**` | `reachai-control-service` | `reachai-runtime-service` | Trace detail and node views | | `/api/runops/**` | `reachai-control-service` | `reachai-runtime-service` | Runtime operations views | | `/api/embed/**` and `/embed/**` | `reachai-control-service` | `reachai-control-service` | Browser and business-system integration surface; token exchange, session create, JSON/SSE messages, and page-action pending/result are implemented in Control; undefined Embed root/wildcard paths are no longer kept behind a Platform retired-route fallback | | `/api/mcp/**` and `/mcp/**` | `reachai-control-service` | `reachai-control-service` | MCP control-plane and endpoint routes; `/mcp/manifest` and `/mcp/jsonrpc` now serve manifest, `tools/list`, and Runtime-backed `tools/call` locally | | `/api/admin/a2a/**` and `/a2a/**` | `reachai-control-service` | `reachai-control-service` | A2A admin plus external AgentCard/JSON-RPC endpoint routes; AgentCard, `message/send`, `tasks/get`, and `tasks/cancel` are now implemented locally in Control | | `/gateway/catalog` | `reachai-control-service` | `reachai-runtime-service` | Public AI Gateway catalog; Control keeps the old `agents/capabilities` response shape and currently derives agent entries from Runtime | | `/gateway/agents/{key}/chat` | `reachai-control-service` | `reachai-runtime-service` | Public AI Gateway agent chat, backed by Runtime Agent execution | | `/gateway` | `reachai-control-service` | `reachai-control-service` | No first-phase public root implementation; use `/gateway/catalog` or `/gateway/agents/{key}/chat`; the old Platform retired-route fallback has been removed | | `/api/context/**` | `reachai-control-service` | `reachai-control-service` / `reachai-runtime-service` by subdomain | Context governance public routes stay behind Control; runtime package/query slices must delegate to Runtime when moved | | `/api/market/**` | `reachai-control-service` | `reachai-control-service` | Market item list/detail, Agent/Skill submit, approval, dependency-check, and export; Control owns `market_item` and resolves Agent/Skill snapshots through Runtime/Capability APIs | ## Current First-Phase Migration Status Capability Catalog route families are now routed Control -> Capability first. The generic Control -> legacy catch-all has been retired, and the Platform Control retired-route fallback has also been removed. Route-contract checks now fail if the generic fallback is reintroduced. Public route families that remain in the product must have an explicit Control, Runtime, or Capability implementation; undefined Platform root/wildcard shapes such as `/mcp`, `/a2a`, `/embed`, or `/gateway` are no longer preserved only to return `LEGACY_AGENT_SERVICE_DISABLED`. Implemented Platform routes rely on their real Control/Runtime implementations. Implemented public compatibility routes in the extracted service shells: `scripts/check-physical-service-route-contracts.mjs` now guards against reintroducing Runtime legacy proxy gateway usage. Routes that have already moved to real Runtime implementations, such as lightweight chat and embedded dispatch, cannot silently reintroduce `ai-agent-service` forwarding. The same route contract check now requires migrated Capability routes, such as Capability asset kernel APIs, domain catalog APIs, API asset list projection, Capability-owned registry operations, Tool catalog management, Composition catalog management, semantic document reads/generation/edit, scan module management, API graph snapshot, regenerate, infer, param-hints, and edge/layout operations plus Capability Mining routes, to have a real Capability implementation instead of being covered only by a retired route surface. Remaining Runtime retired-route backlog: none. Runtime public compatibility controllers now either delegate to Runtime-owned implementations or are guarded against reintroducing the legacy proxy gateway. | Public route | Control behavior | Runtime/Capability behavior | Status | | --- | --- | --- | --- | | `/api/registry/projects/{projectCode}/agent-graphs/sync` | Delegates to Runtime | Writes Runtime-owned `ai_workflow`; reads project identity through Capability internal API | Real implementation | | `POST /api/registry/projects/{projectCode}/pages/register` | Handled locally by Control | Registers SDK page metadata and declared page actions into Control-owned `eaf_page_registry` and `eaf_page_action_registry` while preserving the SDK public route shape | Real implementation | | `/api/registry/projects/register`, `/api/registry/projects/{projectCode}/capability-description-settings`, `/instances/**`, `/capabilities/**`, `/capability-snapshots/**`, and `/capability-diff-items/**` | Delegates to Capability | Handles SDK project registration, SDK description-source settings, Runtime instance heartbeat/offline/status/governance cleanup, and Capability snapshot/diff/review flows locally in Capability-owned tables | Real implementation | | `GET /api/workflows` | Delegates to Runtime | Lists Runtime-owned `ai_workflow` rows with project/type/status filters and deletion eligibility | Real implementation | | `POST /api/workflows` | Delegates to Runtime | Creates Runtime-owned `ai_workflow` rows while preserving current public JSON fields | Real implementation | | `GET /api/workflows/{id}` | Delegates to Runtime | Reads Runtime-owned `ai_workflow` by id | Real implementation | | `GET /api/workflows/graph-node-types` | Delegates to Runtime | Returns Runtime GraphSpec node type catalog without DB access | Real implementation | | `POST /api/workflows/runtime-validation` | Delegates to Runtime | Validates GraphSpec runtime semantics; PAGE_ACTION catalog checks call Control internal page-action lookup instead of reading Control-owned tables directly | Real implementation | | `GET /api/workflows/{id}/studio` | Delegates to Runtime | Reads Runtime-owned `ai_workflow` Studio state | Real implementation | | `PUT /api/workflows/{id}/studio` | Delegates to Runtime | Validates GraphSpec/canvas/extra JSON and saves Runtime-owned workflow draft fields | Real implementation | | `/api/workflows/studio/debug-node` and `/api/workflows/studio/debug-run` | Delegates to Runtime | Runtime-owned Workflow Studio debug now resolves direct `graphSpecJson` or `workflowId`, executes the `GraphSpec` locally through `RuntimeGraphSpecExecutor`, and returns the existing debug result shape without forwarding to the retired agent service | Real implementation | | `/api/workflows/studio/generate-draft` | Delegates to Runtime | Runtime-owned AI draft generation calls Model Gateway through the Runtime service client, builds canvas plus `GraphSpec`, and preserves the public Workflow Studio response shape | Real implementation | | `/api/workflows/studio/edit-draft` | Delegates to Runtime | Runtime-owned AI draft edit applies model-generated canvas patch locally and returns updated canvas plus GraphSpec; calls Model Gateway through Runtime service client | Real implementation | | `/api/capabilities` and `/api/capabilities/{code}/**` | Delegates to Capability | Manages Capability-owned module, tool asset, composition, and interaction definition rows locally | Real implementation | | `/api/domains` and `/api/domains/**` | Delegates to Capability | Manages Capability-owned domain definitions, domain assignments, keyword classification, and coverage views locally | Real implementation | | `GET /api/api-assets` | Delegates to Capability | Builds a read-only API asset list from Capability-owned scan project, scan module, scan project tool, and global tool definition rows | Real implementation | | `GET /api/tools`, `POST /api/tools`, `GET /api/tools/{name}`, `PUT /api/tools/{name}`, `DELETE /api/tools/{name}`, `PUT /api/tools/{name}/toggle`, and `POST /api/tools/{name}/test` | Delegates to Capability | Manages Capability-owned `tool_definition` catalog rows locally while preserving public Tool DTO shape; Tool test now invokes Capability's local HTTP Tool executor and returns the frontend `ToolTestResult` shape instead of the retired-route disabled response | Real implementation | | `POST /api/tool-retrieval/search`, `POST /api/tool-retrieval/rebuild`, `GET /api/tool-retrieval/rebuild/status`, and `GET /api/tool-retrieval/health` | Delegates to Capability | Capability now serves the Tool retrieval management routes locally from Capability-owned `tool_definition` and `tool_retrieval_setting`. The first physical split implementation keeps the public route/DTO contract and provides keyword-based local recall plus rebuild task status without depending on the retired `ai-agent-service`; vector/Milvus-backed recall can be reattached later behind the same Capability owner boundary. | Real implementation | | `/api/skill-mining/**` and `/api/capability-mining/**` | Delegates to Capability | Capability now serves the historical Capability Mining public routes locally. It reads Runtime trace data for precheck, n-gram chain mining, trace/canvas extraction, and demo trace helpers through Runtime internal tool-call-log APIs, stores review drafts in `skill_draft`, and publishes approved drafts through the Capability Composition catalog into `tool_definition(kind=SKILL)` without returning the retired-route disabled response. | Real implementation | | `GET /api/compositions`, `POST /api/compositions`, `GET /api/compositions/{name}`, `PUT /api/compositions/{name}`, `DELETE /api/compositions/{name}`, `PUT /api/compositions/{name}/toggle`, `POST /api/compositions/{name}/test`, `POST /api/compositions/{name}/test/resume`, `GET /api/compositions/{name}/metrics`, `GET /api/compositions/pending-interactions/admin-test`, `DELETE /api/compositions/pending-interactions/admin-test/{interactionId}`, and `POST /api/compositions/pending-interactions/admin-test/cancel-all` | Delegates to Capability | Manages Capability-owned `tool_definition` rows where `kind=SKILL` locally while preserving public Composition DTO shape and `/api/skills` alias on the Capability service. Interactive-form Composition test invokes the target Tool through Capability's local Tool executor; SubAgent Composition test delegates to Runtime composition execution through `services.runtime-service.url` while preserving the public `CompositionTestResult` shape; admin-test resume and pending cleanup call Runtime internal interaction APIs; metrics read Runtime tool-call-log data through Runtime internal trace APIs. | Real implementation | | `GET /api/scan-projects`, `POST /api/scan-projects`, `GET /api/scan-projects/{id}`, `PUT /api/scan-projects/{id}`, `PATCH /api/scan-projects/{id}/auth-settings`, `PATCH /api/scan-projects/{id}/registry-credential`, `POST /api/scan-projects/{id}/sdk-access-check`, `PATCH /api/scan-projects/{id}/scan-settings`, `DELETE /api/scan-projects/{id}`, `POST /api/scan-projects/{id}/scan`, `POST /api/scan-projects/{id}/rescan`, `POST /api/scan-projects/{id}/sensitive-data/scan`, `GET /api/scan-projects/{id}/sensitive-data/status`, `GET /api/scan-projects/{id}/tools`, `POST /api/scan-projects/{projectId}/tools/reconcile`, `GET /api/scan-projects/{projectId}/scan-tools/{scanToolId}`, `POST /api/scan-projects/{projectId}/scan-tools/{scanToolId}/rescan-from-source`, `PUT /api/scan-projects/{projectId}/scan-tools/{scanToolId}`, `PUT /api/scan-projects/{projectId}/scan-tools/{scanToolId}/toggle`, `POST /api/scan-projects/{projectId}/scan-tools/{scanToolId}/test`, `POST /api/scan-projects/{projectId}/scan-tools/{scanToolId}/promote-to-tool`, `POST /api/scan-projects/{projectId}/scan-tools/{scanToolId}/unpromote-from-global`, `POST /api/scan-projects/{projectId}/scan-tools/{scanToolId}/push-to-global-tool`, `POST /api/scan-projects/{projectId}/scan-tools/promote-by-module`, `GET /api/scan-projects/{id}/diff-summary`, `GET /api/scan-projects/{id}/operation-blockers`, `GET /api/semantic-docs`, `PUT /api/semantic-docs/{id}`, `GET /api/scan-projects/{id}/semantic-docs`, `POST /api/scan-projects/{id}/semantic/generate`, `GET /api/scan-projects/{id}/semantic/status`, `POST /api/scan-projects/{id}/semantic/generate-project`, `GET /api/scan-projects/{id}/modules`, `PUT /api/scan-modules/{id}`, `POST /api/scan-modules/{id}/semantic/generate`, `POST /api/scan-modules/merge`, `POST /api/tools/{name}/semantic/generate`, and `POST /api/scan-projects/{projectId}/scan-tools/{scanToolId}/semantic/generate` | Delegates to Capability | Capability now owns scan project collection list/create/detail/update/delete, auth and scan settings, registry credential update, SDK access check, scan/rescan and single scan-tool refresh via Knowledge scanner, sensitive-data scan/status via Model Gateway, scan tool list/detail/update/toggle/test, promote/unpromote/push/batch promote DTOs, scan tool reconcile summary, scan tool diff-summary aggregation, and operation blocker checks. The blocker check uses Runtime internal `/internal/runtime/agent-tool-references` instead of direct Runtime table access. Capability also reads, generates, and edits `semantic_doc` rows, manages `scan_module` grouping locally, calls Model Gateway for semantic generation, and updates generated Tool / scan-tool descriptions without returning the retired-route disabled response | Real implementation | | `GET /api/api-graph/projects/{projectId}/snapshot` | Delegates to Capability | Reads Capability-owned API graph node, edge, and layout rows from the shared DB while preserving the public snapshot response shape | Real implementation | | `POST /api/api-graph/projects/{projectId}/rebuild` | Delegates to Capability | Non-destructively reprojects API graph nodes from Capability scan module/tool metadata, upserts generated nodes/edges, cleans stale nodes, preserves layout rows, regenerates MODEL_REF edges, and returns the rebuilt snapshot | Real implementation | | `POST /api/api-graph/projects/{projectId}/regenerate` | Delegates to Capability | Clears the project's API graph node/edge/layout rows, rebuilds graph nodes from Capability scan module/tool metadata, regenerates BELONGS_TO and MODEL_REF edges, then returns the rebuilt snapshot | Real implementation | | `POST /api/api-graph/projects/{projectId}/infer` and `POST /infer/request-response` | Delegates to Capability | Runs Capability-owned API graph model-reference and request/response candidate inference locally over API graph node/edge rows | Real implementation | | `GET /api/api-graph/projects/{projectId}/tools/{toolName}/param-hints` | Delegates to Capability | Builds parameter source hints locally from Capability-owned tool definitions plus API graph node/edge rows | Real implementation | | `GET /api/api-graph/projects/{projectId}/candidates`, `POST /candidates/{edgeId}/confirm`, `POST /candidates/{edgeId}/reject`, `POST /edges`, `DELETE /edges/{edgeId}`, and `PUT /layout` | Delegates to Capability | Reads and writes Capability-owned API graph edge/layout rows locally, preserving candidate filtering, manual edge upsert, delete, and layout save behavior | Real implementation | | `/api/workflows/ai-coding/workflows` and `/api/workflows/{workflowId}/ai-coding/**` | Delegates to Runtime | Creates, reads, validates, patches, runs, lists versions/runs, publishes, and serves Page Assistant AI Coding helper routes through Runtime-owned Workflow, debug, version, and RunOps services without forwarding to the retired agent service | Real implementation | | `PUT /api/workflows/{id}` | Delegates to Runtime | Updates Runtime-owned `ai_workflow` rows while preserving current public JSON fields | Real implementation | | `DELETE /api/workflows/{id}` | Delegates to Runtime | Deletes draft `ai_workflow` rows only when no `ai_agent_workflow_binding` exists; removes Runtime-owned workflow versions first | Real implementation | | `GET /api/workflows/{workflowId}/versions` | Delegates to Runtime | Lists Runtime-owned `ai_workflow_version` rows | Real implementation | | `POST /api/workflows/{workflowId}/versions` | Delegates to Runtime | Publishes a validated Runtime workflow version snapshot | Real implementation | | `POST /api/workflows/{workflowId}/versions/publish` | Delegates to Runtime | Compatibility alias for Workflow version publishing | Real implementation | | `POST /api/workflows/{workflowId}/versions/validate` | Delegates to Runtime | Runs Runtime release validation before publish | Real implementation | | `POST /api/workflows/{workflowId}/versions/{versionId}/rollback` | Delegates to Runtime | Retires active Runtime workflow versions, reactivates the selected version, and restores workflow draft snapshots | Real implementation | | `POST /api/workflows/{id}/page-assistant/bind` | Delegates to Runtime | Binds a PAGE_ASSISTANT workflow to Runtime-owned `ai_agent_workflow_binding`, provisions Runtime-owned page copilot agents when needed, and resolves project identity through Capability internal API by `projectId` or `projectCode` | Real implementation | | `/api/traces/{traceId}` | Delegates to Runtime | Reads same-DB Runtime-owned `tool_call_log` and `agent_trace_span`, returns merged node view | Real implementation | | `/api/traces/recent` | Delegates to Runtime | Reads same-DB Runtime-owned `tool_call_log`, returns grouped recent trace summaries | Real implementation | | `/api/runtime/agents/route-evaluation` with `/api/agent/route-evaluation` compatibility alias | Delegates to Runtime | Reads same-DB Runtime-owned `tool_call_log`, returns route-readiness statistics | Real implementation | | `/api/runops/traces/{traceId}` | Delegates to Runtime | Reads same-DB `tool_call_log`, `agent_trace_span`, and `guard_decision_log`; `guard_decision_log` is a temporary first-phase read aggregation | Real implementation | | `/api/runops/traces/recent` | Delegates to Runtime | Reads same-DB Runtime-owned `tool_call_log`, returns RunOps summaries | Real implementation | | `/api/runops/diagnostics` | Delegates to Runtime | Reads recent RunOps trace details and returns failure clusters plus version comparisons; same read ownership limits as RunOps detail | Real implementation | | `/api/runops/traces/{traceId}/compare/{candidateTraceId}` | Delegates to Runtime | Reads two RunOps trace detail views and returns summary/span/tool/guard diffs; same read ownership limits as RunOps detail | Real implementation | | `/api/runops/traces/{traceId}/replay` | Delegates to Runtime | Runtime-owned replay restores message/session/user context from RunOps trace detail or `messageOverride`, builds replay metadata, and re-enters Runtime Agent execution without forwarding to the retired agent service | Real implementation | | `/api/chat`, `/api/chat/stream`, and `/api/chat/session/{sessionId}` | Delegates to Runtime | Runtime-owned lightweight chat now calls Model Gateway directly, keeps Runtime-local session memory, and preserves `text/event-stream` on the stream route; lightweight Tool Calling remains outside this first moved slice | Real implementation | | `/api/v1/agents/{key}/chat` | Delegates to Runtime | Preserves the public Agent Gateway chat path on Control, copies the request body, injects `{key}` as `agentDefinitionId` with `AGENT_GATEWAY_CHAT` intent, and forwards to Runtime Agent execution routing instead of falling through the retired Platform Control proxy | Real implementation | | `/gateway/catalog` | Delegates to Runtime | Builds the public AI Gateway catalog from Runtime-owned Agent entries, filters disabled and private agents, preserves the old `agents/capabilities` response shape, and no longer falls through to the Platform retired-route surface. Capability catalog aggregation remains a later owner-boundary follow-up. | Real implementation | | `/gateway/agents/{key}/chat` | Delegates to Runtime | Uses the same Runtime-backed Agent Gateway execution path as `/api/v1/agents/{key}/chat`; `/gateway` root is not kept as a retired-route fallback | Real implementation | | `POST /api/embed/token/exchange` | Handled locally by Control, verifies through Capability and Runtime | Preserves the public Embed token exchange contract and `ApiResult.data.token/expiresIn/sessionHint` response. Control normalizes `X-ReachAI-*` / `X-EAF-*` signature headers, asks Capability internal `/internal/capability/embed/token/exchange/verify` to validate registry credential, origin, and embed agent policy, checks Runtime agent availability through Runtime agent catalog, then signs the short-lived `embedToken`. | Real implementation | | `POST /api/embed/chat/sessions` | Handled locally by Control | Verifies the short-lived `embedToken`, validates page context against token claims, creates Control-owned `eaf_embed_session`, and returns the public Embed Chat session DTO without falling through the Platform retired-route surface. | Real implementation | | `POST /api/embed/chat/sessions/{sessionId}/messages` | Handled locally by Control, executes through Runtime | Verifies the Bearer `embedToken`, requires the active Control-owned `eaf_embed_session`, records user and assistant rows in `eaf_embed_chat_event`, calls Runtime `/api/agent/execute` with `EMBED_CHAT` intent and page/session metadata, and returns the public `ApiResult.data.answer/sessionId/metadata/uiRequest` shape. | Real implementation | | `POST /api/embed/chat/sessions/{sessionId}/messages/stream` | Handled locally by Control, executes through Runtime | Verifies the Bearer `embedToken`, requires the active Control-owned session, reuses the Runtime-backed Embed message execution path, and emits the frontend SDK's SSE events (`message.delta`, optional `ui.requested`, and `message.completed`) without falling through the retired Platform route. | Real implementation | | `GET /api/embed/chat/sessions/{sessionId}/page-actions/pending` and `POST /api/embed/chat/sessions/{sessionId}/page-actions/{requestId}/result` | Handled locally by Control | Verifies the Bearer `embedToken`, requires the active Control-owned session, reads pending `REQUESTED` rows from Control-owned `eaf_page_action_event`, and records browser-side page action result status/result payload back into the same table. | Real implementation | | `GET /mcp/manifest` and `POST /mcp/jsonrpc` | Handled locally by Control | Serves the remote MCP HTTP manifest and authenticates `Authorization: Bearer ` against Control-owned `mcp_client`. The local endpoint supports `tools/list` from `mcp_visibility` plus client `toolWhitelistJson`, supports `tools/call` by validating visibility then calling Runtime-backed `/api/runtime/tools/{qualifiedName}/execute`, and records `mcp_call_log`. | Real implementation | | `GET /a2a/{agentKey}/.well-known/agent.json` and `POST /a2a/{agentKey}/jsonrpc` | Handled locally by Control | Serves AgentCard from Control-owned `a2a_endpoint`, executes `message/send` through Runtime Agent execution, persists task output in Control-owned `a2a_task`, supports `tasks/get` and `tasks/cancel`, and records external protocol calls in `a2a_call_log`. | Real implementation | | `/api/market/items`, `/api/market/agents/{agentId}/submit`, `/api/market/skills/submit`, `/api/market/items/{id}/approve`, `/api/market/items/{id}/dependency-check`, and `/api/market/items/{id}/export` | Handled locally by Control | Manages Control-owned `market_item`; Agent submissions resolve Runtime agent snapshots, Skill submissions resolve Capability internal Tool definitions, approval blocks listing when dependency checks find missing Capability references. | Real implementation | | `/api/workflows/credentials` and `/api/workflows/credentials/{id}` with `/api/agent/workflow-credentials/**` compatibility aliases | Delegates to Runtime | Manages Runtime-owned `agent_workflow_credential` rows, encrypts secrets, masks response previews, and disables rows on delete | Real implementation | | `/api/runtime/evals/**` with `/api/agent/evals/**` compatibility aliases | Delegates to Runtime | Manages Runtime-owned `agent_eval_dataset`, `agent_eval_case`, `agent_eval_run`, and `agent_eval_case_result` rows. The first moved slice preserves dataset/case/run/result contracts and records deterministic `EVAL_RUNTIME_NOT_ATTACHED` results until the real GraphSpec eval executor is connected. | Real implementation | | `/api/context/namespaces` and `/api/context/namespaces/{id}` | Handled locally by Control | Manages Control-owned `context_namespace` rows for context governance scopes; create generates a stable namespace key when the client omits one and delete soft-deletes the namespace | Real implementation | | `/api/context/runtime-user-mappings` and `/api/context/runtime-user-mappings/{id}` | Handled locally by Control | Manages Control-owned `context_runtime_user_mapping` rows for platform-to-runtime-user delegated review identity mapping; create resolves `runtimeUserId` from explicit runtime/global/external user id and delete soft-deletes the mapping | Real implementation | | `/api/context/items/**` | Handled locally by Control | Manages Control-owned `context_item`, `context_evidence`, and `context_binding` rows for governance workbench item CRUD, evidence capture, binding reads, verify/revoke/stale/delete transitions, and scoped list queries. Empty project namespace scope returns an empty list instead of widening to all items. | Real implementation | | `/api/context/audit`, `/api/context/ops/summary`, `/api/context/lifecycle/run`, `/api/context/query`, and `/api/context/package` | Handled locally by Control | Reads and updates Control-owned context governance tables for audit listing, operational counts, lifecycle dry-run/run, ACTIVE item keyword retrieval, and management context package assembly. | Real implementation | | `/api/context/memory/candidates/**` | Handled locally by Control | Manages Control-owned `context_memory_candidate` review buffer routes for list/create/update, approve/reject, and batch approve/reject. Approve writes an ACTIVE `context_item` in the candidate namespace and records Control-owned audit events. | Real implementation | | `/api/agents` and `/api/agents/{id}` | Delegates to Runtime | Manages Runtime-owned `ai_agent` entry CRUD while preserving public request/response fields | Real implementation | | `/api/agents/{agentId}/workflow-bindings/**` | Delegates to Runtime | Manages Runtime-owned `ai_agent_workflow_binding` CRUD and resolve-preview ranking | Real implementation | | `/api/runtimes` | Delegates to Runtime | Aggregates the local platform runtime registry with Capability internal runtime instance lookup; Runtime does not directly read Capability-owned `ai_project_instance` rows | Real implementation | | `/api/runtimes/embedded/dispatch` | Delegates to Runtime | Runtime-owned dispatch resolves the target Runtime instance through Capability internal instance metadata, validates status/governance/capability-host role, and calls the business-system Embedded Runtime endpoint `/eaf/runtime/embedded/execute` | Real implementation | | `/api/runtime/tools/{qualifiedName}/execute`, `/api/runtime/compositions/{qualifiedName}/execute`, and `/api/runtime/interactions/{sessionId}/resume` | Delegates to Runtime | Tool execution keeps the public route shape and delegates through Runtime to Capability's internal HTTP Tool executor. Composition execution loads Composition GraphSpec through Capability internal APIs and executes it in Runtime. Interaction resume reads Runtime-owned session state, stores submitted payload/events, and continues the GraphSpec from the suspended node. | Real implementation | | `/api/runtime/debug-sessions/**` | Delegates to Runtime | Runtime-owned executable debug session lifecycle stores `executable_debug_session`, runs draft GraphSpec through Runtime debug, and continues from the suspended node on submit | Real implementation | | `/api/runtime/interactions/human-approvals/**` with `/api/agent/interactions/human-approvals/**` compatibility aliases | Delegates to Runtime | Runtime-owned human approval facade reads pending `skill_interaction` approval rows, maps `UiRequest` payloads for the front end, and records submit/cancel decisions locally | Real implementation | | `/api/runtime/agents/execute` and `/api/runtime/agents/execute/detailed` with `/api/agent/execute/**` compatibility aliases | Delegates to Runtime | Runtime resolves Agent id/keySlug, Agent workflow binding, and Runtime-owned Workflow, then executes the minimal Runtime GraphSpec path. The executable subset supports linear `USER_INPUT -> LLM -> ANSWER` and `USER_INPUT -> TOOL/CAPABILITY -> ANSWER` style graphs, local `ANSWER` rendering, `LLM` calls through `reachai-model-service`, and Tool/Capability calls through `reachai-capability-service`. Unsupported executable node types return Runtime-owned unsupported-node responses instead of proxying to the retired agent service. | Runtime-owned execution routing | ## Internal Routes | Internal route | Owner | Caller | | --- | --- | --- | | `/internal/runtime/health` | `reachai-runtime-service` | `reachai-control-service` | | `/internal/capability/health` | `reachai-capability-service` | `reachai-control-service` | | `/internal/capability/tools/{qualifiedName}` | `reachai-capability-service` | `reachai-runtime-service` | | `/internal/capability/projects/{projectCode}` | `reachai-capability-service` | `reachai-runtime-service` | | `/internal/capability/projects/by-id/{projectId}` | `reachai-capability-service` | `reachai-runtime-service` | | `/internal/capability/runtime-instances` | `reachai-capability-service` | `reachai-runtime-service` | | `/api/internal-services/health` | `reachai-control-service` | Operators and internal diagnostics | ## Non-Goals - Do not split the physical MySQL database in this phase. - Do not rename SQL tables or `skill_*` compatibility-sensitive storage names. - Do not make the frontend call `reachai-runtime-service` or `reachai-capability-service` directly. - Do not change public request or response JSON during route ownership migration.