Skip to content

feat(qortex): HTTP transport for QortexConnection #89

@Peleke

Description

@Peleke

Context

qortex is becoming a persistent HTTP service (port 8400) instead of an MCP subprocess. The migration is phased:

  • Phase 1 (done, qortex-track-c): async VectorIndex + PgVectorIndex — qortex can run against pgvector
  • Phase 2+3 (done, openclaw-sandbox): pgvector Docker role + systemd service — qortex serve runs as a daemon on the sandbox
  • Phase 4 (this issue): gateway side — make openclaw talk to qortex over HTTP instead of spawning a subprocess

The QortexConnection interface (src/qortex/types.ts:8-17) is already transport-agnostic:

export interface QortexConnection {
  readonly isConnected: boolean;
  init(): Promise<void>;
  callTool(
    name: string,
    args: Record<string, unknown>,
    opts?: { timeout?: number },
  ): Promise<unknown>;
  close(): Promise<void>;
}

Today the only implementation is QortexMcpConnection (src/qortex/connection.ts:86-171), which spawns a subprocess via StdioClientTransport. This issue adds a parallel QortexHttpConnection that hits the qortex REST API, a factory to pick the right transport at boot, and wires everything together.

Prerequisite (separate repo: qortex-track-c)

4 missing HTTP routes added: ingest/message, learning/reset, learning/sessions/start, learning/sessions/end.


Implementation Steps

Step 2: QortexHttpConnection class

New file: src/qortex/http-connection.ts

Implements the QortexConnection interface. Static TOOL_ROUTE_MAP maps MCP tool names to HTTP endpoints:

MCP tool name HTTP method Path Call sites
qortex_query POST /v1/query src/memory/providers/qortex.ts:148
qortex_feedback POST /v1/feedback src/memory/providers/qortex.ts:278
qortex_ingest POST /v1/ingest src/memory/providers/qortex.ts:236
qortex_ingest_message POST /v1/ingest/message src/qortex/online-ingest.ts:39,51
qortex_learning_select POST /v1/learning/select src/learning/qortex-client.ts:189
qortex_learning_observe POST /v1/learning/observe src/learning/qortex-client.ts:216
qortex_learning_posteriors GET /v1/learning/{learner}/posteriors src/learning/qortex-client.ts:245
qortex_learning_metrics GET /v1/learning/{learner}/metrics src/learning/qortex-client.ts:269
qortex_learning_reset POST /v1/learning/reset src/learning/qortex-client.ts:293
qortex_learning_session_start POST /v1/learning/sessions/start src/learning/qortex-client.ts:315
qortex_learning_session_end POST /v1/learning/sessions/end src/learning/qortex-client.ts:334

Behavior:

  • init(): GET /v1/health — sets isConnected = true on 200, throws on failure
  • callTool(name, args, opts): lookup route map → fetch with AbortController timeout → parse JSON → throw matching parseToolResult format on error
  • Retry on 5xx + network errors (3 attempts, exponential backoff). No retry on 4xx.
  • Optional health check heartbeat every 30s

Step 3: Connection factory

New file: src/qortex/connection-factory.ts

export function createQortexConnection(opts: {
  transport: "mcp" | "http";
  mcp?: { command: string; args: string[] };
  http?: { baseUrl: string; headers?: Record<string, string> };
}): QortexConnection;

Step 4: Config schema updates

Add transport + http fields to:

  • src/config/zod-schema.learning.ts — qortex sub-object
  • src/config/zod-schema.agent-runtime.ts — memorySearch.qortex
  • src/learning/types.ts — LearningConfig.qortex
  • src/config/types.tools.ts — MemorySearchConfig.qortex

Step 5: Gateway boot update

  • src/gateway/server-runtime-state.ts (lines 107-131): replace QortexMcpConnection with factory
  • src/learning/qortex-adapter.ts (lines 297-299): update fallback connection
  • src/memory/providers/qortex.ts (lines 135-139): update owned connection

Step 6: Tests

  • src/qortex/http-connection.test.ts: route mapping, arg transforms, retry, timeout, health
  • src/qortex/connection-factory.test.ts: transport switching

Files to create

File Purpose
src/qortex/http-connection.ts HTTP implementation of QortexConnection
src/qortex/connection-factory.ts Factory: createQortexConnection()
src/qortex/http-connection.test.ts Tests for HTTP connection
src/qortex/connection-factory.test.ts Tests for factory

Files to modify

File Change
src/gateway/server-runtime-state.ts Replace QortexMcpConnection with factory
src/learning/qortex-adapter.ts Replace fallback QortexMcpConnection with factory
src/memory/providers/qortex.ts Add transport to config, use factory
src/config/zod-schema.learning.ts Add transport + http to qortex schema
src/config/zod-schema.agent-runtime.ts Add transport + http to memorySearch qortex schema
src/config/types.tools.ts Add transport + http to MemorySearchConfig.qortex
src/learning/types.ts Add transport + http to LearningConfig.qortex

Migration strategy

  • Default transport stays "mcp" — no existing deployments break
  • Opt-in via config: learning.qortex.transport: "http"
  • Ansible injects transport: "http" when qortex_serve_enabled is true
  • Both transports can coexist in a mixed deployment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions