> ## Documentation Index
> Fetch the complete documentation index at: https://docs.moss.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Responses

> OpenAI-compatible Responses API that answers from your Moss indexes.

`POST /v1/responses` takes an OpenAI [Responses request](https://platform.openai.com/docs/api-reference/responses/create), searches your project's indexes for the user's question, adds what it finds to the prompt, and returns the reply as OpenAI's [streaming events](https://platform.openai.com/docs/api-reference/responses-streaming) or one [Response object](https://platform.openai.com/docs/api-reference/responses/object). Any OpenAI client with the Responses API works: change the base URL and the key. This page covers only where Moss Inference differs from OpenAI.

> [!WARNING]
>
> Moss Inference stores no responses. `store` is ignored, and `previous_response_id` and `conversation` are refused: send the whole conversation in `input` on every call, as [Conversations](#conversations) shows. Background responses, OpenAI's built-in tools such as web search and file search, file and audio input, and images on the `moss` model are not supported either. See [Not supported](#not-supported) for the full list.

> **Base URL**
>
> ```text theme={null}
> https://inference.moss.dev/v1
> ```

## Authentication

Send the project id and project key from the [Moss portal](https://portal.usemoss.dev) as one bearer token:

```text theme={null}
Authorization: Bearer <project_id>:<project_key>
```

## Request

These fields are accepted. A field set to `null` counts as left out, and any other field returns `400`, as [Not supported](#not-supported) lists.

| Field | Default | Notes |
| - | - | - |
| `model` | `moss` | Or a model from the [list](https://docs.moss.dev/docs/api-reference/v1/inference/models.md#model-list) on the Moss key, if your organization has it turned on, or any vendor model on your own key. See [Models](https://docs.moss.dev/docs/api-reference/v1/inference/models.md). |
| `input` | required | A string, which is one user message, or a list of [input items](#input-items). |
| `instructions` | none | A string, sent as the system message before `input`. A list of items returns `400`. |
| `stream` | `false` | `true` streams [events](#streaming). |
| `tools` | none | `function` tools and `mcp` servers. See [Tool calls](#tool-calls) and [MCP servers](#mcp-servers). |
| `tool_choice` | `auto` | `none`, `auto`, `required`, `{"type": "function", "name": ...}`, or `{"type": "mcp", "server_label": ..., "name": ...}`. |
| `parallel_tool_calls` | `true` | Whether the model can call more than one tool at once. |
| `max_output_tokens` | none | The most tokens the reply can have. A reply cut at this limit has `status` `incomplete`. |
| `text` | plain text | `format` of type `text`, `json_object` or `json_schema`. `verbosity` can only be `medium`. |
| `reasoning` | none | `effort` only. A vendor model gets it as it is, and the values it takes depend on that model. The `moss` model ignores it. |
| `temperature`, `top_p`, `user` | the model's | Passed to the model. |
| `safety_identifier`, `prompt_cache_key`, `service_tier` | the model's | Passed to a vendor model. The `moss` model ignores them. |
| `metadata` | `{}` | Kept on the response. |
| `store`, `stream_options` | none | Ignored. |
| `background`, `truncation`, `include` | | Accepted only as `false`, `"disabled"` and `[]`. |

The headers (`X-Moss-Indexes`, `X-Moss-Retrieve`, `X-Moss-Cache`, `X-Moss-Provider-Key`), the reply headers such as `X-Moss-Request-Id`, and the [limits](https://docs.moss.dev/docs/api-reference/v1/inference/chat-completions.md#limits) are the same as on [Chat Completions](https://docs.moss.dev/docs/api-reference/v1/inference/chat-completions.md#request).

### Input items

| `type` | Notes |
| - | - |
| `message` | `role` is `user`, `system`, `developer` or `assistant`. `content` is a string or a list of `input_text` and `output_text` parts, plus `input_image` parts on a user message. `type` can be left out. |
| `function_call` | A call from an earlier response's `output`. Send it back unchanged. |
| `function_call_output` | Your tool's result, as a string or a list of text parts. |
| `mcp_call` | An MCP call from an earlier response's `output`. See [MCP servers](#mcp-servers). |
| `mcp_list_tools`, `reasoning` | Skipped. |

The search reads only the text of user messages, never images. An `input_image` part, given by its `image_url`, goes to the model as it is. The `moss` model reads text only, so send images to a vendor model that reads them.

## Conversations

Moss Inference keeps no conversation state. Each call sends the conversation so far, in order:

1. the earlier input items,
2. the `output` items of the last response, unchanged,
3. the new items: the next user message, or one `function_call_output` for each function call.

`instructions` belongs to each call, so send it every time. [Tool calls](#tool-calls) shows a full `input`.

## Streaming

The events follow OpenAI's [streaming events](https://platform.openai.com/docs/api-reference/responses-streaming). Moss Inference sends only these types: `response.created`, `response.in_progress`, `response.output_item.added` and `.done`, `response.content_part.added` and `.done`, `response.output_text.delta` and `.done`, `response.function_call_arguments.delta` and `.done`, and the `mcp_call` events under [MCP servers](#mcp-servers). The stream ends with one event that carries the whole response: `response.completed`, `response.incomplete` for a reply cut by `max_output_tokens` or a content filter, or `response.failed` (see [Errors](#errors)). There is no `data: [DONE]`.

## Response

Without `stream`, the body is the response that the last event carries, in OpenAI's [shape](https://platform.openai.com/docs/api-reference/responses/object). `store` is always `false`. `output` holds only `message`, `function_call` and `mcp_call` items. `model` is the name you sent, or `moss` when you sent none. `status` is `incomplete` for a reply cut short, and `incomplete_details.reason` says why: `max_output_tokens` or `content_filter`. `tools` leaves out MCP `headers`. `usage.input_tokens` includes the retrieved facts.

## Examples

The Python and JavaScript examples below use OpenAI's own clients. The Moss SDKs have their own client for this endpoint: [Python](https://docs.moss.dev/docs/reference/python/inference.md), [JavaScript](https://docs.moss.dev/docs/reference/js/inference.md), [Swift](https://docs.moss.dev/docs/reference/swift/inference.md), [Android](https://docs.moss.dev/docs/reference/android/inference.md), [Elixir](https://docs.moss.dev/docs/reference/elixir/inference.md), [Browser](https://docs.moss.dev/docs/reference/browser/inference.md), and [C](https://docs.moss.dev/docs/reference/c/inference.md).

```bash curl theme={null}
curl -N https://inference.moss.dev/v1/responses \
  -H "Authorization: Bearer $MOSS_PROJECT_ID:$MOSS_PROJECT_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Moss-Indexes: faq" \
  -d '{
    "model": "moss",
    "stream": true,
    "instructions": "You are the support agent for Acme.",
    "input": "Do you ship to Canada?"
  }'
```

```python Python theme={null}
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://inference.moss.dev/v1",
    api_key=f"{os.environ['MOSS_PROJECT_ID']}:{os.environ['MOSS_PROJECT_KEY']}",
    default_headers={"X-Moss-Indexes": "faq"},
)
stream = client.responses.create(
    model="moss",
    instructions="You are the support agent for Acme.",
    input="Do you ship to Canada?",
    stream=True,
)
for event in stream:
    if event.type == "response.output_text.delta":
        print(event.delta, end="", flush=True)
```

```typescript JavaScript theme={null}
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://inference.moss.dev/v1",
  apiKey: `${process.env.MOSS_PROJECT_ID}:${process.env.MOSS_PROJECT_KEY}`,
  defaultHeaders: { "X-Moss-Indexes": "faq" },
});
const stream = await client.responses.create({
  model: "moss",
  instructions: "You are the support agent for Acme.",
  input: "Do you ship to Canada?",
  stream: true,
});
for await (const event of stream) {
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta);
  }
}
```

## Tool calls

Function tools take OpenAI's flat shape, and your code runs them. Since nothing is stored, call again with the conversation, the `function_call` items unchanged, and one `function_call_output` for each call:

```json theme={null}
{
  "input": [
    {"role": "user", "content": "Where is order A1?"},
    {
      "id": "fc_8fd7_0",
      "type": "function_call",
      "status": "completed",
      "call_id": "call_1",
      "name": "lookup_order",
      "arguments": "{\"id\": \"A1\"}"
    },
    {"type": "function_call_output", "call_id": "call_1", "output": "Shipped on Oct 20."}
  ],
  "tools": [{
    "type": "function",
    "name": "lookup_order",
    "parameters": {"type": "object", "properties": {"id": {"type": "string"}}}
  }]
}
```

A `function_call` item can carry fields beyond OpenAI's, such as Gemini's `extra_content`. Keep them: the model needs them on the next turn.

## MCP servers

A `tools` entry of type `mcp` names an MCP server, with the fields listed on [Chat Completions](https://docs.moss.dev/docs/api-reference/v1/inference/chat-completions.md#mcp-servers). Moss Inference connects to it, offers its tools to the model, runs the calls the model makes, and streams the final answer. It never asks for approval: `require_approval` can only be `never`. OpenAI's connectors (`connector_id`) and its `authorization` field are not supported; send a token in `headers`.

Each MCP call is an `mcp_call` output item, streamed as `response.output_item.added`, `response.mcp_call.in_progress`, `response.mcp_call_arguments.done`, then `response.mcp_call.completed` or `response.mcp_call.failed`, and `response.output_item.done`:

```json theme={null}
{
  "id": "call_1",
  "type": "mcp_call",
  "status": "completed",
  "server_label": "crm",
  "name": "lookup_order",
  "arguments": "{\"id\": \"A1\"}",
  "output": "Shipped on Oct 20.",
  "error": null,
  "duration_ms": 41.2
}
```

A failed call has `status` `failed`, `output` null, and an `error` of `{"type": "mcp_tool_execution_error", "content": ...}`.

Send `mcp_call` items back in `input` with the rest of the output. The model sees their results and does not run the tools again. An `mcp_call` with neither `output` nor `error` never finished, and its tool may have run, so it returns `400`: check whether the tool ran, and send the outcome as a message in its place.

A tool may already have changed data when a call fails after it, so Moss Inference never retries that call. Without `stream`, it returns `424` with `code` `failed_after_tool_call`, the `output` items so far, and the header `x-should-retry: false`. On a stream, `response.failed` has `error.code` `failed_after_tool_call`. Do not replay such a call. The other MCP errors are listed under [MCP errors](https://docs.moss.dev/docs/api-reference/v1/inference/chat-completions.md#mcp-errors).

## Not supported

These return `400` with `type` `invalid_request_error`, `code` `unsupported_parameter`, and a message that names the field:

* `previous_response_id` and `conversation`. Nothing is stored, so send the whole conversation in `input`.
* `background: true`, a non-empty `include`, `prompt`, and `truncation: "auto"`.
* `reasoning` fields other than `effort`, such as `summary`, and `text.verbosity` other than `medium`.
* Tools other than `function` and `mcp`: OpenAI's built-in tools, such as `web_search`, `file_search`, `code_interpreter`, `image_generation`, computer use and shell, and custom tools. The same goes for a `tool_choice` that names one of them.
* Content parts other than `input_text`, `output_text` and `input_image` with an `image_url`: files (`input_file`), audio (`input_audio`), and images given by `file_id`.
* Input items other than those in [Input items](#input-items), such as `item_reference`.
* Any field not listed under [Request](#request), such as `max_tool_calls` or `top_logprobs`.

```json 400 - Bad Request theme={null}
{
  "error": {
    "message": "previous_response_id is not supported. Send the whole conversation in input.",
    "type": "invalid_request_error",
    "code": "unsupported_parameter"
  }
}
```

Images are not on this list because a vendor model can read them. The `moss` model reads text only. See [Input items](#input-items).

## Errors

An error before the stream starts has the same status, shape and cause as on [Chat Completions](https://docs.moss.dev/docs/api-reference/v1/inference/chat-completions.md#errors).

A failure after the stream starts ends it with `response.failed`. Its `response.error` has `type`, `code` and `message`, and its `response.output` holds the items so far. Without `stream`, the same failure returns `502` with the error shape, or `424` once an MCP call ran (see [MCP servers](#mcp-servers)).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.