Skip to content

Configuration

The SDK is configured through the ClientConfig interface passed to the ReasoningLayerClient constructor. Three fields are required: baseUrl, tenantId, and auth. Everything else has sensible defaults.

import { ReasoningLayerClient } from '@kortexya/reasoninglayer';
const client = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: '550e8400-e29b-41d4-a716-446655440000',
auth: { mode: 'bearer', token: process.env.RL_API_TOKEN! },
userId: '00000000-0000-0000-0000-000000000001',
namespaceId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
timeoutMs: 15000,
maxRetries: 2,
retryOn503: true,
});

ClientConfig reference

OptionTypeDefaultDescription
baseUrlstringrequiredBase URL of the Reasoning Layer API. Trailing slashes are stripped automatically.
tenantIdstringrequiredTenant UUID. Sent as X-Tenant-Id on every request. Not overridable per-call.
authAuthConfigrequiredAuthentication mode. See Authentication below.
userIdstringundefinedDefault user UUID. Sent as X-User-Id. Overridable per-call via RequestOptions.
namespaceIdstringundefinedDefault namespace UUID. Sent as X-Namespace-Id. Overridable per-call via RequestOptions.
authenticatedUserstringundefinedAuthenticated user identifier. Sent as X-Authenticated-User.
timeoutMsnumber30000Default request timeout in milliseconds. Overridable per-call.
maxRetriesnumber3Maximum retry attempts for retryable errors (429, optionally 503).
retryOn503booleanfalseWhether to retry on HTTP 503 (Service Unavailable). 429 is always retried.
interceptorsInterceptor[][]Request/response interceptors. See Interceptors below.
fetchtypeof globalThis.fetchglobalThis.fetchCustom fetch implementation for dependency injection or testing.

Authentication

The auth field is required and explicit — the SDK has no implicit unauthenticated mode. Pick one of two modes depending on where the SDK is running.

Bearer token — server-side / programmatic usage

Send a long-lived API token (typically a service-account token issued by the auth gateway) on every request as Authorization: Bearer <token>.

const client = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: '550e8400-e29b-41d4-a716-446655440000',
auth: { mode: 'bearer', token: process.env.RL_API_TOKEN! },
});

Rely on the session cookie set by the auth gateway after the user has logged in interactively. The SDK issues HTTP requests with credentials: 'include' so the cookie is attached even on cross-origin requests; WebSocket connections rely on the browser attaching the cookie automatically (same-origin).

const client = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: '550e8400-e29b-41d4-a716-446655440000',
auth: { mode: 'cookie' },
});

The choice between modes belongs to the deployment context of the caller, not the SDK — pick bearer from servers and CI, cookie from browser code that has already gone through the platform’s login flow.

Authentication headers

The SDK derives every authentication-related HTTP header from ClientConfig. You should not set them yourself.

HeaderSourcePer-call override
AuthorizationClientConfig.auth (bearer mode)No
X-Tenant-IdClientConfig.tenantIdNo — requires a separate client instance
X-User-IdClientConfig.userIdYes, via RequestOptions.userId
X-Namespace-IdClientConfig.namespaceIdYes, via RequestOptions.namespaceId
X-Authenticated-UserClientConfig.authenticatedUserNo

Retry behavior

The SDK automatically retries failed requests with exponential backoff and jitter.

Always retried:

  • HTTP 429 (Too Many Requests) — respects the Retry-After header if present

Optionally retried (when retryOn503: true):

  • HTTP 503 (Service Unavailable)

Never retried:

  • HTTP 4xx errors (400, 404, 409, etc.)
  • Timeout errors
  • User-initiated abort

Backoff formula

delay = min(1000ms * 2^(attempt-1) + random(0..1000ms), 30000ms)

For 429 responses with a Retry-After header, the SDK uses the server-specified delay instead.

Disabling retries

Set maxRetries: 0 globally:

const client = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: 'my-tenant-uuid',
auth: { mode: 'cookie' },
maxRetries: 0,
});

Timeouts

The default timeout is 30 seconds. When a request exceeds its timeout, the SDK throws a TimeoutError.

import { TimeoutError } from '@kortexya/reasoninglayer';
const client = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: 'my-tenant-uuid',
auth: { mode: 'cookie' },
timeoutMs: 10000, // 10 second default
});
try {
const result = await client.inference.backwardChain({
goal: psi('complex_goal', {}),
maxDepth: 200,
timeoutMs: 5000, // Server-side timeout: stop searching after 5 seconds
});
} catch (error) {
if (error instanceof TimeoutError) {
console.log(`Timed out after ${error.timeoutMs}ms`);
}
}

Interceptors

Interceptors are middleware functions that wrap each HTTP request. They receive the Request object and a next function, and must return a Response. Interceptors are called in the order they are provided.

import type { Interceptor } from '@kortexya/reasoninglayer';
// Logging interceptor
const logger: Interceptor = async (request, next) => {
const start = performance.now();
console.log(`--> ${request.method} ${request.url}`);
const response = await next(request);
const duration = Math.round(performance.now() - start);
console.log(`<-- ${response.status} (${duration}ms)`);
return response;
};
// Dynamic auth token interceptor (for token refresh scenarios)
const dynamicAuth: Interceptor = async (request, next) => {
const modified = new Request(request, {
headers: new Headers(request.headers),
});
modified.headers.set('Authorization', `Bearer ${await refreshToken()}`);
return next(modified);
};
const client = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: 'my-tenant-uuid',
auth: { mode: 'cookie' },
interceptors: [logger, dynamicAuth],
});

Interceptors execute in order: logger wraps authToken, which wraps the actual fetch call.

Custom fetch implementation

Inject a custom fetch for testing or specialized environments:

// Testing with a mock fetch
const client = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: 'my-tenant-uuid',
auth: { mode: 'cookie' },
fetch: myMockFetch,
});

This is useful for:

  • Unit testing without network calls
  • Custom HTTP agents or proxies
  • Environments where globalThis.fetch needs augmentation

Multi-tenant usage

Since tenantId is not overridable per-call, create separate clients for each tenant:

const tenantA = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: 'tenant-a-uuid',
auth: { mode: 'bearer', token: process.env.RL_TOKEN_A! },
});
const tenantB = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: 'tenant-b-uuid',
auth: { mode: 'bearer', token: process.env.RL_TOKEN_B! },
});
// Each client operates in complete tenant isolation
const sortsA = await tenantA.sorts.listSorts();
const sortsB = await tenantB.sorts.listSorts();

Full configuration example

import { ReasoningLayerClient } from '@kortexya/reasoninglayer';
import type { Interceptor } from '@kortexya/reasoninglayer';
const logger: Interceptor = async (request, next) => {
console.log(`${request.method} ${request.url}`);
return next(request);
};
const client = new ReasoningLayerClient({
baseUrl: 'https://api.example.com',
tenantId: '550e8400-e29b-41d4-a716-446655440000',
auth: { mode: 'bearer', token: process.env.RL_API_TOKEN! },
userId: '00000000-0000-0000-0000-000000000001',
namespaceId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
authenticatedUser: 'admin@example.com',
timeoutMs: 15000,
maxRetries: 2,
retryOn503: true,
interceptors: [logger],
});