Skip to main content
MossInference is the C client for Moss Inference. moss_inference_responses_create takes an OpenAI Responses request as JSON, searches your indexes, and returns OpenAI’s JSON.

Install

MossInference needs libmoss 0.29.0 or later. Set TARGET for your platform. The tarball holds the header, include/libmoss.h. A libmoss.h with these functions defines MOSS_INFERENCE_API_VERSION 3. For the other platforms and how to link the library, see Install.

Create a client

Copy the project id and key 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. The examples below use this client.

Get a response

With NULL for the callback, out_json gets the response as the JSON of one OpenAI Response. Free it with moss_free_string. The text is in the output_text parts of the message items of output. The response’s request_id is its X-Moss-Request-Id. Include it when you report a problem. It is left out when the response has none. Moss stores no response, so input holds the whole conversation. Pass a string, or a list of items such as {"role": "user", "content": "Hi"} and the output items of earlier responses. See Conversations.

Stream a response

The call blocks until the response ends. It hands the callback each event as the JSON text of one OpenAI Responses event, such as response.output_text.delta. That event carries the new text in delta. The stream ends after one of two events:
  • response.completed, when the response is done.
  • response.incomplete, when max_output_tokens or a content filter cut the response short.
A streaming call can pass out_json too. It then gets the response of the last event. To stop early, return a value other than 0 from the callback. The call then closes the connection, which stops the model, and returns OK. Streaming lists every event.

Ground it in your indexes

Moss searches the faq index and adds what it finds to the prompt. The Quickstart creates that index. Without indexes, Moss does not search and the model answers from input alone. You can name at most 32. "retrieve": false skips the search on a call that names indexes. Ground answers in your indexes covers the options and the cost.

Use a vendor model

Name a model from OpenAI, Anthropic or Google in model. The search of your indexes works the same for every model. Models lists them all.

On the Moss key

Without your own key, a listed vendor model runs on the Moss key and bills your credits. Routes shows who bills each call. A listed model that is not served right now fails with code "model_not_enabled" in moss_last_error_detail(). Send moss/fastlane-1 or use your own key.

With your own key

Pass your OpenAI, Anthropic or Google key to a client as api_key in options_json:
The key goes in the X-Moss-Provider-Key header, never in the body. To use a key for one call only, put api_key in call_options_json. The response’s model is the name you sent. Bring your own key covers model names and billing.

Tool calls

Pass OpenAI function tools in tools of the request JSON. A function tool is flat, as in OpenAI’s Responses API. Your code runs the tools.
Each call the model makes comes as a function_call item of output, with its call_id, name and arguments. Put the output items back into input as they are. Add one item per call, such as {"type": "function_call_output", "call_id": "...", "output": "Shipped on Oct 20."}. Call again with the same tools until the response has no calls. Each item keeps every field the model sent, such as the thought signature Gemini needs in the next turn. Tool calling covers tool_choice, parallel_tool_calls and structured output.

MCP servers

A tools entry of type "mcp" names an MCP server. Moss Inference runs its tools for the model within the same call, so your code sends no function_call_output items for them.
print_event is the callback from Stream a response. Each call comes as an mcp_call item. It arrives in a response.output_item.added event when it starts, and in response.output_item.done when it ends. The same items are in the response’s output. Send the items back in input with the rest of output. The model then sees the earlier tool results. MCP failures return a negative MossResult, with status, type, code and retry_after_ms in moss_last_error_detail(). A call that fails after a tool ran has code "failed_after_tool_call". The tool may already have changed data, so Moss Inference does not retry the call. Never replay a request that failed with failed_after_tool_call. MCP servers covers the server fields and every MCP error.

Errors

A failed call returns a negative MossResult. A streaming call returns it after the events the callback already got. A response.failed event fails the call too. Right after the failed call, on the same thread, moss_last_error() holds the message. moss_last_error_detail() holds a JSON object with these fields: A field the failure lacks is null. The SDK sets these types itself: Every other error carries what Moss Inference sent. The call returns:
  • ERR_UNAUTHORIZED for authentication_error and permission_error.
  • ERR_INVALID_ARG for invalid_request_error.
  • ERR_CLOUD for the rest.
Errors and limits lists every code. For a 429, see Limits.

Options

options_json of moss_inference_new: request_json of moss_inference_responses_create: call_options_json of moss_inference_responses_create, which may be NULL:

Memory and the event callback

  • The callback runs on the thread that made the call, once per event. It never runs after the call returns.
  • libmoss never reads or frees user_data.
  • The next event is read only after the callback returns. A slow callback holds up the stream, and its time counts toward timeout_ms.