Skip to main content
C SDK / Inference MossInference is the C client for Moss Inference, a drop-in for OpenAI’s chat completions. moss_inference_chat_completions_create takes an OpenAI request as JSON, searches your indexes in the cloud, adds what it finds to the prompt, and hands back the reply as OpenAI’s JSON.
Requires libmoss 0.28.0 or later, installed as in Install. A libmoss.h with these functions defines MOSS_INFERENCE_API_VERSION. From version 2, the calls keep every tool call field and report MCP tool steps.

Create a client

The project id and key come from the Moss portal. Build one client and reuse it for every call, from any thread. Free it with moss_inference_free once no call on it is running.

Get a reply

With NULL for the callback, out_json gets the reply as the JSON of one OpenAI chat.completion:
The text is in choices[0].message.content, which is null when the reply only calls tools. The completion’s request_id is the response’s X-Moss-Request-Id. Include it when you report a problem. It is null when the response has none.

Stream a reply

The call blocks until the reply ends, and hands the callback each chunk as the JSON text of one OpenAI chat.completion.chunk, with the new text in choices[0].delta.content when choices is not empty. To stop early, return a value other than 0 from the callback: the call closes the connection, which stops the model, and returns OK. Only the last chunk carries usage, and it has no choices, so check choices before reading choices[0].

Errors

A failed call returns a negative MossResult, a streaming one after the chunks the callback already got. Right after it, on the same thread, moss_last_error() holds the message, and moss_last_error_detail() a JSON object in which status is the HTTP status of a refused request, type names the failure, code is the error code Moss Inference sent, such as "rate_limit_exceeded", request_id is the response’s X-Moss-Request-Id, and retry_after_ms is the wait in milliseconds that a Retry-After header asks for. A field the failure lacks is null. The SDK sets these itself: Every other error reports what Moss Inference sent. The call returns ERR_UNAUTHORIZED for authentication_error and permission_error, ERR_INVALID_ARG for invalid_request_error, ERR_DESERIALIZATION for a stream event that is not a JSON object, and ERR_CLOUD for the rest. See Errors, and Limits for a 429.

Tool calls

tools, tool_choice and parallel_tool_calls go in the request JSON as in OpenAI’s API, and your code runs the tools. Pass a callback to stream the reply and out_json to get it joined, in the same call:
print_chunk is the callback from Stream a reply. The joined message keeps every field of each call, with "" for an id, name or arguments the model left out. Append it to messages as it is, then one tool message per call, and call again with the same tools, as in Tool calls.

MCP servers

A tools entry of type "mcp" names an MCP server whose tools Moss Inference runs for the model within the same call, so you send no tool messages for them:
Steps arrive in each chunk’s moss_tool_step and the completion’s moss_tool_steps, and MCP failures return a negative MossResult, with status, type, code and retry_after_ms in moss_last_error_detail(), as in MCP servers.

Memory and the chunk callback

  • The callback runs on the thread that made the call, once per chunk, and never after the call returns. libmoss never reads or frees user_data.
  • The next chunk is read only after the callback returns, so a slow callback holds up the stream, and its time counts toward timeout_ms.
  • A streaming call can pass out_json too, and gets the reply as one chat.completion. When the callback stops the stream, that reply ends with the chunk it stopped at.

Options

options_json of moss_inference_new: options_json of moss_inference_chat_completions_create, which may be NULL: request_json of moss_inference_chat_completions_create: