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
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 throwsInferenceError, 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 inchunk.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: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: