Developers · API Reference

Search Agent API

Embed the conversational Search Agent in your own portal: multi-turn conversations, live progress streaming, and grounded answers with source citations.

POST /api/v1/search-agent/conversations

Base URL and authentication

Send requests to https://{your_subdomain}.nousai.com, authenticated with the x-api-key header provided to you by Nous AI. See API Reference for keys and the errors shared by every API.

Overview

The Search Agent answers questions over your knowledge base in a multi-turn conversation. Start a conversation with POST /api/v1/search-agent/conversations/; the response includes a conversation_id. Send follow-up questions to POST /api/v1/search-agent/conversations/{conversation_id}/turns/, and the agent resolves references against the earlier turns ("what about last year?").

Because the agent researches across several rounds of retrieval before it answers, a turn takes longer than a one-shot search. Allow for that in your HTTP client's timeout settings, or use the streaming endpoints, which report progress while the agent works and keep the connection active.

Request

Headers

NameRequiredDescription
x-api-keyYesYour API key for authentication

Body

The request body should be in JSON format with the following parameters:

ParameterTypeRequiredDescription
querystringYesThe question for this turn, up to 5,000 characters
Example Request Body
{
	"query": "What was EMEA revenue in Q3?"
}

Response

Success Response

  • Code: 201 Created (new conversation) or 200 OK (follow-up turn)
  • Content-Type: application/json
Example Response Body
{
	"conversation_id": "7f9d2c48-1a9e-4a41-9c9a-1f2f2b1f6d2e",
	"turn_id": "a5b0f9f0-6a5f-4f5b-9e0d-8f6a1c2d3e4f",
	"ordinal": 0,
	"ai_summary": "EMEA Q3 revenue was €12.4M, up 8% on Q2 [0]...",
	"documents": [
		{
			"source": {
				"title": "Q3 Board Report",
				"path": "https://www.example.com/q3-board-report",
				"extension": "pdf"
			},
			"date": "2026-07-14",
			"extract": "EMEA revenue reached €12.4M in the third quarter..."
		}
	]
}
FieldTypeDescription
conversation_iduuidUse it to send follow-up turns and read the thread
turn_iduuidIdentifies this turn, e.g. for feedback
ordinalintegerZero-based position of the turn in the conversation
ai_summarystringThe answer, in Markdown, with [n] citations into documents
documentsarrayThe cited source documents, in citation order: title, path, extension, date, and extract

When the agent needs more information to answer, it asks for it in ai_summary and cites nothing; send the user's reply as the next turn.

Follow-up turns

Send the next question in the same conversation to POST /api/v1/search-agent/conversations/{conversation_id}/turns/ with the same body shape. The response is identical, with ordinal incremented. Retrying a request creates a new turn: requests are not idempotent, so avoid automatic retries of turn POSTs.

Error Responses

CodeMeaningContent
400Missing, empty, or over-length query{"error": "A non-empty query is required."}
403Missing or invalid API key, or the Search Agent is not enabled for your tenant{"detail": "Invalid API key"}
404Unknown conversation for this API key{"error": "Conversation not found."}
409The conversation reached the model's context limit and can't continue; start a new conversation{"error": "...", "disabled": true}
413Request body larger than 64 KB{"detail": "Request body too large."}
502The agent could not complete the turn; the failed turn is recorded on the conversation{"error": "The assistant could not complete this request."}

POST /api/v1/search-agent/conversations/stream

Base URL and authentication

Send requests to https://{your_subdomain}.nousai.com, authenticated with the x-api-key header provided to you by Nous AI. See API Reference for keys and the errors shared by every API.

Overview

The streaming endpoints run exactly the same turn as the JSON endpoints, but respond with Content-Type: text/event-stream (Server-Sent Events) and emit progress while the agent works. Use POST /api/v1/search-agent/conversations/stream/ to start a conversation, and POST /api/v1/search-agent/conversations/{conversation_id}/turns/stream/ for follow-ups. The request body and headers are identical to the non-streaming endpoints.

Streaming carries progress, not answer tokens: the answer arrives whole in the final result frame, whose payload is exactly the JSON endpoint's response body.

Frame contract

Each frame is a standard SSE event: an event: line naming the frame type and a data: line carrying a JSON payload. Comment frames (lines starting with :) are keep-alives; ignore them.

EventPayloadMeaning
start{}The turn has been accepted and is running
stage{"stage": "...", ...}Progress update; see stage names below
resultTurn response bodyThe finished answer, in the same shape as the JSON endpoint response. Final frame.
error{"error": "...", "disabled"?: true}The turn failed; disabled marks a conversation that can't continue. Final frame.

Stage names

StageExtra payloadMeaning
understandingThe agent is reading the question
searching{"round": n}A retrieval round is running
writingThe agent is composing the answer

Stages report progress only. The cited source documents arrive once, with the answer, in the result frame.

Example Stream
event: start
data: {}

event: stage
data: {"stage": "understanding"}

event: stage
data: {"stage": "searching", "round": 1}

event: stage
data: {"stage": "writing"}

event: result
data: {"conversation_id": "7f9d...", "ai_summary": "EMEA Q3 revenue was...", ...}

Note that the browser EventSource API only supports GET; consume these endpoints with fetch and a stream reader, or any SSE client library that supports POST. Bad input and unknown conversations are rejected with a JSON 400/404 before the stream opens; once the stream has opened, failures arrive as an error frame. Disconnecting mid-stream does not cancel the turn: it completes and is stored on the conversation.

GET /api/v1/search-agent/conversations

Base URL and authentication

Send requests to https://{your_subdomain}.nousai.com, authenticated with the x-api-key header provided to you by Nous AI. See API Reference for keys and the errors shared by every API.

List conversations

GET /api/v1/search-agent/conversations/ returns the conversations created with your API key, newest first.

Example Response Body
{
	"conversations": [
		{
			"id": "7f9d2c48-1a9e-4a41-9c9a-1f2f2b1f6d2e",
			"title": null,
			"display_title": "What was EMEA revenue in Q3?",
			"status": "active",
			"created_at": "2026-08-12T09:00:00Z",
			"updated_at": "2026-08-12T09:05:00Z",
			"turn_count": 2
		}
	]
}

Read a conversation thread

GET /api/v1/search-agent/conversations/{conversation_id}/ returns the full thread: every turn with its query, answer, cited documents, and status, in order. The top-level disabled flag is true when the conversation can take no further turns (it reached the model's context limit).

Example Response Body
{
	"id": "7f9d2c48-1a9e-4a41-9c9a-1f2f2b1f6d2e",
	"title": null,
	"status": "active",
	"created_at": "2026-08-12T09:00:00Z",
	"updated_at": "2026-08-12T09:05:00Z",
	"disabled": false,
	"turns": [
		{
			"id": "a5b0f9f0-6a5f-4f5b-9e0d-8f6a1c2d3e4f",
			"ordinal": 0,
			"query": "What was EMEA revenue in Q3?",
			"status": "completed",
			"created_at": "2026-08-12T09:00:00Z",
			"ai_summary": "EMEA Q3 revenue was...",
			"documents": [ ... ],
			"feedback_rating": null
		}
	]
}

Error Responses

Unknown Conversation

  • Code: 404 Not Found
  • Content: {"error": "Conversation not found."}

Invalid API Key

  • Code: 403 Forbidden
  • Content: {"detail": "Invalid API key"}

POST /api/v1/search-agent/conversations/{id}/turns/{turn_id}/feedback

Base URL and authentication

Send requests to https://{your_subdomain}.nousai.com, authenticated with the x-api-key header provided to you by Nous AI. See API Reference for keys and the errors shared by every API.

Overview

Record a rating on a turn's answer, for example when a user of your portal clicks thumbs up or down. Feedback helps Nous AI monitor and improve answer quality for your tenant.

Request

Body

ParameterTypeRequiredDescription
ratingenumYespositive or negative
issue_typestringNoIssue category for a negative rating, up to 100 characters
detailstringNoFree-text note, up to 2,000 characters
Example Request Body
{
	"rating": "negative",
	"issue_type": "wrong_answer",
	"detail": "The Q3 figure is from the draft report."
}

Response

Success Response

  • Code: 200 OK
  • Content: {"status": "ok", "feedback_rating": "negative"}

Error Responses

Invalid Rating

  • Code: 400 Bad Request
  • Content: {"error": "A valid rating is required."}

Unknown Turn

  • Code: 404 Not Found
  • Content: {"error": "Turn not found."}