166 lines
5.9 KiB
Markdown
166 lines
5.9 KiB
Markdown
# NODE.DC AI Workspace Assistant
|
|
|
|
Platform-owned shared state service for the cross-surface AI Workspace assistant.
|
|
|
|
It owns:
|
|
|
|
- user AI Workspace executors/devices and selected executor;
|
|
- assistant conversation/thread metadata;
|
|
- surface context and enabled tool packs;
|
|
- linked artifacts between Engine, Ops and future platform surfaces.
|
|
|
|
It does not replace the AI Workspace Hub. The Hub remains the thin transport/rendezvous layer for remote Codex workers.
|
|
|
|
It does not replace the legacy Ops MCP config flow:
|
|
|
|
```text
|
|
external Codex client -> ~/.codex/config.toml -> nodedc-ops-agent MCP -> Ops Agent Gateway
|
|
```
|
|
|
|
That flow remains a separate product path.
|
|
|
|
## API
|
|
|
|
All endpoints require the shared internal token. App BFFs pass the resolved platform subject through:
|
|
|
|
```text
|
|
X-NODEDC-User-Id
|
|
X-NODEDC-User-Email
|
|
X-NODEDC-User-Role
|
|
X-NODEDC-User-Groups
|
|
```
|
|
|
|
`Role` and `Groups` are identity inputs for entitlement adapters. App backends still own object-level ACL enforcement.
|
|
|
|
Executor registry:
|
|
|
|
```text
|
|
GET /api/ai-workspace/assistant/v1/executors
|
|
POST /api/ai-workspace/assistant/v1/executors
|
|
PATCH /api/ai-workspace/assistant/v1/executors/:executorId
|
|
DELETE /api/ai-workspace/assistant/v1/executors/:executorId
|
|
POST /api/ai-workspace/assistant/v1/executors/:executorId/select
|
|
```
|
|
|
|
Conversations:
|
|
|
|
```text
|
|
GET /api/ai-workspace/assistant/v1/threads
|
|
POST /api/ai-workspace/assistant/v1/threads
|
|
GET /api/ai-workspace/assistant/v1/threads/:threadId
|
|
PATCH /api/ai-workspace/assistant/v1/threads/:threadId
|
|
POST /api/ai-workspace/assistant/v1/threads/:threadId/messages
|
|
GET /api/ai-workspace/assistant/v1/threads/:threadId/messages
|
|
```
|
|
|
|
Assistant actions:
|
|
|
|
```text
|
|
POST /api/ai-workspace/assistant/v1/actions
|
|
```
|
|
|
|
This is the platform entrypoint for ontology-backed assistant tool calls. Natural-language chat dispatch still goes through the selected assistant model/executor first; `ontology-core` is the deterministic policy/action layer the assistant calls after it has interpreted the user's intent.
|
|
|
|
Request shape:
|
|
|
|
```json
|
|
{
|
|
"phase": "preview",
|
|
"input": {
|
|
"actionId": "hub.user.block",
|
|
"targetUserId": "user_123",
|
|
"confirmed": true,
|
|
"idempotencyKey": "hub.user.block:user_admin:user_123"
|
|
}
|
|
}
|
|
```
|
|
|
|
For write execution, first call `phase=preview`, show the returned `action.confirmation` to the user, then call `phase=execute` with `confirmationToken`. The final mutation still goes through the app-owned Launcher admin API guards; this service only routes the registered action.
|
|
|
|
Launcher action gateway configuration:
|
|
|
|
```text
|
|
NDC_ONTOLOGY_LAUNCHER_BASE_URL=http://launcher.local.nodedc
|
|
NDC_LAUNCHER_INTERNAL_ACCESS_TOKEN=...
|
|
```
|
|
|
|
If `NDC_LAUNCHER_INTERNAL_ACCESS_TOKEN` is not set, the service falls back to `NODEDC_INTERNAL_ACCESS_TOKEN`.
|
|
|
|
Launcher entitlement adapter configuration:
|
|
|
|
```text
|
|
AI_WORKSPACE_LAUNCHER_ENTITLEMENT_URL=http://launcher:5173/api/ai-workspace/internal/v1/entitlements
|
|
AI_WORKSPACE_LAUNCHER_ENTITLEMENT_TOKEN=...
|
|
AI_WORKSPACE_LAUNCHER_ENTITLEMENT_REQUIRED=true
|
|
```
|
|
|
|
The Launcher adapter is evaluated after app-owned adapters and may return `launcher`, `ops`, and `engine` app grants. A Launcher denial is the top-level service-access decision and clears MCP servers for that app in the run profile; app-owned adapters still own app-local scopes and runtime tokens.
|
|
|
|
The first HUB action ids exposed to assistants are:
|
|
|
|
- `hub.user.read_admin_summary`
|
|
- `hub.invite.list_pending`
|
|
- `hub.access_request.list_pending`
|
|
|
|
Read actions can be executed without user confirmation after the assistant has selected the structured action. Privileged/write actions still require explicit preview, user confirmation, and execute.
|
|
|
|
App BFFs should pass active scope facts in action input (`clientId`, `coreAssistantRole`, `membershipRole`, `membershipStatus`) so policy stays data-driven instead of prompt-driven.
|
|
|
|
Supported initial surfaces:
|
|
|
|
- `engine`
|
|
- `ops`
|
|
- `global`
|
|
|
|
Supported initial tool packs:
|
|
|
|
- `engine`
|
|
- `ops`
|
|
- `ndc-agent-core`
|
|
- `deploy`
|
|
- `docs`
|
|
|
|
## Run Profile
|
|
|
|
Every dispatch builds an `ai-workspace.run-profile.v1` payload. The raw profile is sent only to the bridge worker; public API responses and run metadata keep MCP headers redacted.
|
|
|
|
The canonical cross-surface execution contract is [AI Workspace Protocol v1](./docs/AI_WORKSPACE_PROTOCOL_V1.md). It defines layer ownership, run profile shape, tool manifests, worker boundaries, Hub boundaries, app adapter rules, and the migration path from the current scaffold.
|
|
|
|
The worker uses `runProfile.toolProfile.mcpServers` to create an isolated per-run `CODEX_HOME/config.toml`. Install-time MCP config remains only as a legacy fallback when no dynamic profile is available.
|
|
|
|
Runtime deploy readiness is tracked in [TEST_MATRIX.md](./TEST_MATRIX.md). The `smoke:run-profile` script covers the entitlement adapter to run profile contract and public secret redaction.
|
|
|
|
## Entitlement Adapters
|
|
|
|
App grants can be resolved dynamically before dispatch through adapter endpoints. Configure adapters with:
|
|
|
|
```text
|
|
AI_WORKSPACE_ENTITLEMENT_ADAPTERS_JSON='{"ops":{"url":"https://ops.example/api/ai-workspace/entitlements","tokenEnv":"NODEDC_INTERNAL_ACCESS_TOKEN","required":false}}'
|
|
```
|
|
|
|
or app-specific variables:
|
|
|
|
```text
|
|
AI_WORKSPACE_OPS_ENTITLEMENT_URL=https://ops.example/api/ai-workspace/entitlements
|
|
AI_WORKSPACE_OPS_ENTITLEMENT_TOKEN=...
|
|
AI_WORKSPACE_OPS_ENTITLEMENT_REQUIRED=false
|
|
AI_WORKSPACE_ENGINE_ENTITLEMENT_URL=https://engine.example/api/ai-workspace/internal/v1/entitlements
|
|
AI_WORKSPACE_ENGINE_ENTITLEMENT_TOKEN=...
|
|
AI_WORKSPACE_ENGINE_ENTITLEMENT_REQUIRED=false
|
|
```
|
|
|
|
Adapter request body:
|
|
|
|
```json
|
|
{
|
|
"schemaVersion": "ai-workspace.entitlement-request.v1",
|
|
"appId": "ops",
|
|
"owner": {},
|
|
"activeContext": {},
|
|
"runContext": {},
|
|
"requestedAt": "2026-06-13T00:00:00.000Z"
|
|
}
|
|
```
|
|
|
|
Adapter response can return `appGrants`, `grants`, `grant`, `appGrant`, or a top-level grant with `mcpServers` and `scopes`. Adapter grants override matching settings grants for the current run only.
|