Skip to main content
Browser SDK / Inference MossInference takes OpenAI’s chat.completions.create arguments plus indexes, and returns OpenAI’s shapes from Moss Inference, which searches your indexes in the cloud, so the page loads no index. It works like the JavaScript client, and this page covers what differs in the browser.
Requires @moss-dev/moss-web 1.7.0 or later, installed as in Install.

Create a client

new MossInference(projectId, projectKey, options) takes your project id and key from the Moss portal. CORS is open, so the page can call Moss Inference directly, but a project key in page code is visible to every visitor and can also create and delete your indexes. Keep direct calls to prototypes, local demos and internal tools. On a public page, pass null for both and a baseURL path served by a route of yours that adds them. Build one client and reuse it for every call. It has nothing to close.

Get a reply

completion.requestId is the response’s X-Moss-Request-Id, and so is stream.requestId on a stream. Include it when you report a problem. Both are undefined when the response has none.

Stream a reply

To stop early, leave the loop or call stream.controller.abort(), as the stop button does: either closes the connection, which stops the model, and neither throws. Only the last chunk carries usage, and it has no choices, which is why the loop reads choices[0]?..

Errors

Every failure other than an abort throws InferenceError, from the for await loop once a stream has started. status is the HTTP status of a refused request, type names the failure, and message describes it. errorCode is the error code Moss Inference sent, such as "rate_limit_exceeded", requestId is the response’s X-Moss-Request-Id, and retryAfter is the wait in milliseconds that a Retry-After header asks for. A field the failure lacks is undefined. A call without baseURL gets no retryAfter, since Moss Inference does not expose Retry-After to the page. The SDK sets these types itself, with status undefined: Every other error reports what Moss Inference sent. See Errors, and Limits for a 429.

Tool calls

tools, tool_choice and parallel_tool_calls take OpenAI’s shapes, and your code runs each call. After the loop, stream.finalChatCompletion() joins every chunk into the completion that a call without stream: true returns. Push its message onto messages as it is, then one tool message per call, and call again, as in Tool calls:
orderStatus is your own function, and it returns text. finalChatCompletion() also works without the for await loop, and a second call returns the same completion. It rejects with what the loop would throw, or with the signal’s reason after an abort.

MCP servers

Add MCP entries in your server route, never in page code. Steps arrive in chunk.moss_tool_step and completion.moss_tool_steps, and MCP failures throw InferenceError with status, type, errorCode and retryAfter, as in MCP servers.

Keep the project key on your server

A public page calls Moss Inference through a route like this one, which adds the key on your server so it never reaches the page:
Every visitor can set any header, so the route forwards only the ones it names, refuses an index outside its list with 403, and always sends X-Moss-Indexes, because a call without it searches every index of the project. retrieve, cache, an empty indexes list and apiKey in page code therefore do not reach Moss Inference, and a route that wants them sets X-Moss-Retrieve, X-Moss-Cache or X-Moss-Provider-Key itself. With null credentials the client sends no Authorization header, so one you pass in headers, such as the visitor’s session token, reaches the route.

Options

new MossInference(projectId, projectKey, options?): chat.completions.create(params, options?) takes OpenAI’s fields and the Moss fields in params, and settings for this call only in options: