curl --request POST \
--url https://api-dev.narrative.io/agents/conversations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"compute_pool_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"max_iterations": 8,
"max_tokens": 2048,
"temperature": 0,
"thinking": {
"type": "effort",
"level": "high"
},
"output_format_schema": {
"type": "object",
"additionalProperties": false,
"required": [
"text"
],
"properties": {
"text": {
"type": "string"
}
}
},
"mcp_servers": [],
"tools": []
},
"name": "rate-limiting q&a",
"system_prompt": "You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering."
}
'import requests
url = "https://api-dev.narrative.io/agents/conversations"
payload = {
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"compute_pool_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"max_iterations": 8,
"max_tokens": 2048,
"temperature": 0,
"thinking": {
"type": "effort",
"level": "high"
},
"output_format_schema": {
"type": "object",
"additionalProperties": False,
"required": ["text"],
"properties": { "text": { "type": "string" } }
},
"mcp_servers": [],
"tools": []
},
"name": "rate-limiting q&a",
"system_prompt": "You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering."
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
defaults: {
model: 'anthropic.claude-opus-4.6',
data_plane_id: 'f79cbdae-4848-47ca-95e8-69588364d185',
execution_cluster: 'shared',
compute_pool_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
max_iterations: 8,
max_tokens: 2048,
temperature: 0,
thinking: {type: 'effort', level: 'high'},
output_format_schema: {
type: 'object',
additionalProperties: false,
required: ['text'],
properties: {text: {type: 'string'}}
},
mcp_servers: [],
tools: []
},
name: 'rate-limiting q&a',
system_prompt: 'You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.'
})
};
fetch('https://api-dev.narrative.io/agents/conversations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-dev.narrative.io/agents/conversations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'defaults' => [
'model' => 'anthropic.claude-opus-4.6',
'data_plane_id' => 'f79cbdae-4848-47ca-95e8-69588364d185',
'execution_cluster' => 'shared',
'compute_pool_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'max_iterations' => 8,
'max_tokens' => 2048,
'temperature' => 0,
'thinking' => [
'type' => 'effort',
'level' => 'high'
],
'output_format_schema' => [
'type' => 'object',
'additionalProperties' => false,
'required' => [
'text'
],
'properties' => [
'text' => [
'type' => 'string'
]
]
],
'mcp_servers' => [
],
'tools' => [
]
],
'name' => 'rate-limiting q&a',
'system_prompt' => 'You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-dev.narrative.io/agents/conversations"
payload := strings.NewReader("{\n \"defaults\": {\n \"model\": \"anthropic.claude-opus-4.6\",\n \"data_plane_id\": \"f79cbdae-4848-47ca-95e8-69588364d185\",\n \"execution_cluster\": \"shared\",\n \"compute_pool_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"max_iterations\": 8,\n \"max_tokens\": 2048,\n \"temperature\": 0,\n \"thinking\": {\n \"type\": \"effort\",\n \"level\": \"high\"\n },\n \"output_format_schema\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"text\"\n ],\n \"properties\": {\n \"text\": {\n \"type\": \"string\"\n }\n }\n },\n \"mcp_servers\": [],\n \"tools\": []\n },\n \"name\": \"rate-limiting q&a\",\n \"system_prompt\": \"You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-dev.narrative.io/agents/conversations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"defaults\": {\n \"model\": \"anthropic.claude-opus-4.6\",\n \"data_plane_id\": \"f79cbdae-4848-47ca-95e8-69588364d185\",\n \"execution_cluster\": \"shared\",\n \"compute_pool_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"max_iterations\": 8,\n \"max_tokens\": 2048,\n \"temperature\": 0,\n \"thinking\": {\n \"type\": \"effort\",\n \"level\": \"high\"\n },\n \"output_format_schema\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"text\"\n ],\n \"properties\": {\n \"text\": {\n \"type\": \"string\"\n }\n }\n },\n \"mcp_servers\": [],\n \"tools\": []\n },\n \"name\": \"rate-limiting q&a\",\n \"system_prompt\": \"You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-dev.narrative.io/agents/conversations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"defaults\": {\n \"model\": \"anthropic.claude-opus-4.6\",\n \"data_plane_id\": \"f79cbdae-4848-47ca-95e8-69588364d185\",\n \"execution_cluster\": \"shared\",\n \"compute_pool_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"max_iterations\": 8,\n \"max_tokens\": 2048,\n \"temperature\": 0,\n \"thinking\": {\n \"type\": \"effort\",\n \"level\": \"high\"\n },\n \"output_format_schema\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"text\"\n ],\n \"properties\": {\n \"text\": {\n \"type\": \"string\"\n }\n }\n },\n \"mcp_servers\": [],\n \"tools\": []\n },\n \"name\": \"rate-limiting q&a\",\n \"system_prompt\": \"You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.\"\n}"
response = http.request(request)
puts response.read_body{
"id": "bc2505b7-068d-44ed-8055-a6f6ffe54ab1",
"company_id": 1,
"user_id": 407,
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"compute_pool_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"max_iterations": 8,
"max_tokens": 2048,
"temperature": 0,
"thinking": {
"type": "effort",
"level": "high"
},
"output_format_schema": {
"type": "object",
"additionalProperties": false,
"required": [
"text"
],
"properties": {
"text": {
"type": "string"
}
}
},
"mcp_servers": [],
"tools": []
},
"version": 4,
"created_at": "2026-05-18T13:21:30.355180Z",
"updated_at": "2026-05-18T13:21:51.983952Z",
"name": "<string>",
"system_prompt": "<string>"
}{
"type": "https://docs.narrative.io/reference/architecture/agent-conversations/errors/invalid-tool-alias",
"title": "Invalid Tool Alias",
"status": 400,
"detail": "invalid tool aliases (must match ^[a-zA-Z][a-zA-Z0-9]{0,7}$): with_underscore",
"instance": null,
"log_id": "1f6e5d4c-3b2a-1098-7654-3210fedcba98",
"debug": null
}{
"error": "Unauthorized",
"error_description": "You are not authorized to use this endpoint."
}Create an agent conversation
Creates a new agent conversation with a pinned system_prompt and a defaults block
that every subsequent run inherits. The conversation starts at version: 0 — your
first run’s expected_version will be 0.
What this endpoint actually does
- Validates the
defaultsblock. Failures here (alias regex, duplicate aliases, wire-name length, missing required fields) return 400 immediately — the conversation row is not created on validation failure. - Inserts a row in
agent_conversationswithversion = 0,company_idfrom your bearer token, and the validateddefaultsserialized as JSONB. - Returns the persisted conversation echo.
No workflows are started here. The conversation is a long-lived container; the
actual model execution happens later, in POST /agents/conversations/{id}/runs.
What you cannot change later
system_prompt— pinned for the conversation’s lifetime. If you need a different system prompt, create a new conversation.company_id/user_id— derived from the bearer token at creation time; not exposed in the request body. Both gate every subsequent read endpoint on this conversation: peers in the same company cannot see each other’s conversations, runs, or messages. Cross-user access surfaces as 404 — the API does not distinguish “doesn’t exist” from “owned by another user”.
Everything else in defaults (model, max_iterations, tools, etc.) is just a default
— any individual run can override any of those fields via config_override on its
POST .../runs body. See Agent Conversations
Reference
for the override semantics.
Permission
agent_conversations resource with write verb. The same permission gates
POST .../runs; read is required for the GET endpoints.
Example: minimal “hello world” conversation (no tools)
{
"name": "hello world",
"system_prompt": "You are a helpful assistant. Answer concisely.",
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"max_iterations": 10,
"max_tokens": 1024,
"temperature": 0.0,
"output_format_schema": {
"type": "object",
"additionalProperties": false,
"required": ["text"],
"properties": { "text": { "type": "string" } }
}
}
}
Example: conversation that can search the Narrative docs
The mcp_servers entry registers two tools the model can call server-side. The
platform handles the JSON-RPC calls to https://docs.narrative.io/mcp transparently.
{
"name": "docs search",
"system_prompt": "Use the available tools to look things up before answering.",
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"max_iterations": 8,
"max_tokens": 2048,
"temperature": 0.0,
"output_format_schema": {
"type": "object",
"additionalProperties": false,
"required": ["text"],
"properties": { "text": { "type": "string" } }
},
"mcp_servers": [{
"alias": "docs",
"url": "https://docs.narrative.io/mcp",
"description": "Narrative docs MCP server"
}]
}
}
Example: conversation using an external OAuth-connected MCP server
For an external server that requires user authorization, connect it first via POST /mcp-connections (the user consents in a browser; the connection becomes connected).
Then reference the returned connection_id in the mcp_servers entry — the platform
attaches and refreshes that connection’s bearer token server-side on every tool call. The
token never appears in the payload or run history. alias and url are still required;
the url should match the server you connected.
{
"name": "hugging face tools",
"system_prompt": "Use the available tools to look things up before answering.",
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"max_iterations": 8,
"max_tokens": 2048,
"temperature": 0.0,
"output_format_schema": {
"type": "object",
"additionalProperties": false,
"required": ["text"],
"properties": { "text": { "type": "string" } }
},
"mcp_servers": [{
"alias": "hf",
"url": "https://huggingface.co/mcp",
"description": "Hugging Face MCP server (external, OAuth)",
"connection_id": "b3f1c2a4-5d6e-47f8-9a0b-1c2d3e4f5a6b"
}]
}
}
Example: conversation with a caller-declared tool (human in the loop)
Caller-declared tools[] entries cause the model’s call to pause the run with
status: requires_action. The caller answers by posting a follow-up run with
payload.kind: tool_outputs. These tools have no alias — the model sees the bare
name, and the platform routes any dash-free tool call to caller-declared resolution.
{
"name": "booking flow",
"system_prompt": "You are a booking assistant.",
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"max_iterations": 5,
"output_format_schema": {
"type": "object",
"additionalProperties": false,
"required": ["text"],
"properties": { "text": { "type": "string" } }
},
"tools": [{
"name": "confirm_booking",
"description": "Ask the user to confirm a proposed booking slot.",
"input_schema": {
"type": "object",
"additionalProperties": false,
"required": ["proposed_slot"],
"properties": { "proposed_slot": { "type": "string" } }
}
}]
}
}
Common 400 errors
type URL slug | Cause |
|---|---|
/errors/invalid-tool-alias | MCP alias doesn’t match ^[a-zA-Z][a-zA-Z0-9]{0,7}$ |
/errors/duplicate-tool-alias | Same alias appears twice across mcp_servers |
/errors/invalid-caller-tool-name | Caller-declared tools[].name is empty, contains a dash, or exceeds 64 chars |
/errors/duplicate-caller-tool-name | Same tools[].name appears twice |
/errors/tool-name-too-long | Some MCP wire name {alias}-{tool_name} > 64 chars |
/errors/invalid-mcp-server-url | An mcp_servers[].url is not a public https URL |
/errors/reserved-tool-name | A tools[].name takes the name of a platform tool |
/errors/unknown-model | thinking is set and model is not a model the platform offers |
/errors/thinking-not-supported | thinking is set for a model that is not offered thinking |
/errors/thinking-setting-not-accepted | The model does not take this thinking setting |
/errors/thinking-budget-too-large | thinking.budget_tokens is not smaller than max_tokens |
A body that isn’t valid JSON, or doesn’t decode (a missing defaults field, an unknown
execution_cluster), gets a 400 with an {error, error_description} body instead.
See Agent Conversations error catalog for the full list.
curl --request POST \
--url https://api-dev.narrative.io/agents/conversations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"compute_pool_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"max_iterations": 8,
"max_tokens": 2048,
"temperature": 0,
"thinking": {
"type": "effort",
"level": "high"
},
"output_format_schema": {
"type": "object",
"additionalProperties": false,
"required": [
"text"
],
"properties": {
"text": {
"type": "string"
}
}
},
"mcp_servers": [],
"tools": []
},
"name": "rate-limiting q&a",
"system_prompt": "You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering."
}
'import requests
url = "https://api-dev.narrative.io/agents/conversations"
payload = {
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"compute_pool_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"max_iterations": 8,
"max_tokens": 2048,
"temperature": 0,
"thinking": {
"type": "effort",
"level": "high"
},
"output_format_schema": {
"type": "object",
"additionalProperties": False,
"required": ["text"],
"properties": { "text": { "type": "string" } }
},
"mcp_servers": [],
"tools": []
},
"name": "rate-limiting q&a",
"system_prompt": "You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering."
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
defaults: {
model: 'anthropic.claude-opus-4.6',
data_plane_id: 'f79cbdae-4848-47ca-95e8-69588364d185',
execution_cluster: 'shared',
compute_pool_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
max_iterations: 8,
max_tokens: 2048,
temperature: 0,
thinking: {type: 'effort', level: 'high'},
output_format_schema: {
type: 'object',
additionalProperties: false,
required: ['text'],
properties: {text: {type: 'string'}}
},
mcp_servers: [],
tools: []
},
name: 'rate-limiting q&a',
system_prompt: 'You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.'
})
};
fetch('https://api-dev.narrative.io/agents/conversations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-dev.narrative.io/agents/conversations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'defaults' => [
'model' => 'anthropic.claude-opus-4.6',
'data_plane_id' => 'f79cbdae-4848-47ca-95e8-69588364d185',
'execution_cluster' => 'shared',
'compute_pool_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'max_iterations' => 8,
'max_tokens' => 2048,
'temperature' => 0,
'thinking' => [
'type' => 'effort',
'level' => 'high'
],
'output_format_schema' => [
'type' => 'object',
'additionalProperties' => false,
'required' => [
'text'
],
'properties' => [
'text' => [
'type' => 'string'
]
]
],
'mcp_servers' => [
],
'tools' => [
]
],
'name' => 'rate-limiting q&a',
'system_prompt' => 'You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-dev.narrative.io/agents/conversations"
payload := strings.NewReader("{\n \"defaults\": {\n \"model\": \"anthropic.claude-opus-4.6\",\n \"data_plane_id\": \"f79cbdae-4848-47ca-95e8-69588364d185\",\n \"execution_cluster\": \"shared\",\n \"compute_pool_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"max_iterations\": 8,\n \"max_tokens\": 2048,\n \"temperature\": 0,\n \"thinking\": {\n \"type\": \"effort\",\n \"level\": \"high\"\n },\n \"output_format_schema\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"text\"\n ],\n \"properties\": {\n \"text\": {\n \"type\": \"string\"\n }\n }\n },\n \"mcp_servers\": [],\n \"tools\": []\n },\n \"name\": \"rate-limiting q&a\",\n \"system_prompt\": \"You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-dev.narrative.io/agents/conversations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"defaults\": {\n \"model\": \"anthropic.claude-opus-4.6\",\n \"data_plane_id\": \"f79cbdae-4848-47ca-95e8-69588364d185\",\n \"execution_cluster\": \"shared\",\n \"compute_pool_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"max_iterations\": 8,\n \"max_tokens\": 2048,\n \"temperature\": 0,\n \"thinking\": {\n \"type\": \"effort\",\n \"level\": \"high\"\n },\n \"output_format_schema\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"text\"\n ],\n \"properties\": {\n \"text\": {\n \"type\": \"string\"\n }\n }\n },\n \"mcp_servers\": [],\n \"tools\": []\n },\n \"name\": \"rate-limiting q&a\",\n \"system_prompt\": \"You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-dev.narrative.io/agents/conversations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"defaults\": {\n \"model\": \"anthropic.claude-opus-4.6\",\n \"data_plane_id\": \"f79cbdae-4848-47ca-95e8-69588364d185\",\n \"execution_cluster\": \"shared\",\n \"compute_pool_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"max_iterations\": 8,\n \"max_tokens\": 2048,\n \"temperature\": 0,\n \"thinking\": {\n \"type\": \"effort\",\n \"level\": \"high\"\n },\n \"output_format_schema\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"text\"\n ],\n \"properties\": {\n \"text\": {\n \"type\": \"string\"\n }\n }\n },\n \"mcp_servers\": [],\n \"tools\": []\n },\n \"name\": \"rate-limiting q&a\",\n \"system_prompt\": \"You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering.\"\n}"
response = http.request(request)
puts response.read_body{
"id": "bc2505b7-068d-44ed-8055-a6f6ffe54ab1",
"company_id": 1,
"user_id": 407,
"defaults": {
"model": "anthropic.claude-opus-4.6",
"data_plane_id": "f79cbdae-4848-47ca-95e8-69588364d185",
"execution_cluster": "shared",
"compute_pool_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"max_iterations": 8,
"max_tokens": 2048,
"temperature": 0,
"thinking": {
"type": "effort",
"level": "high"
},
"output_format_schema": {
"type": "object",
"additionalProperties": false,
"required": [
"text"
],
"properties": {
"text": {
"type": "string"
}
}
},
"mcp_servers": [],
"tools": []
},
"version": 4,
"created_at": "2026-05-18T13:21:30.355180Z",
"updated_at": "2026-05-18T13:21:51.983952Z",
"name": "<string>",
"system_prompt": "<string>"
}{
"type": "https://docs.narrative.io/reference/architecture/agent-conversations/errors/invalid-tool-alias",
"title": "Invalid Tool Alias",
"status": 400,
"detail": "invalid tool aliases (must match ^[a-zA-Z][a-zA-Z0-9]{0,7}$): with_underscore",
"instance": null,
"log_id": "1f6e5d4c-3b2a-1098-7654-3210fedcba98",
"debug": null
}{
"error": "Unauthorized",
"error_description": "You are not authorized to use this endpoint."
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Create an empty conversation with a pinned system_prompt and a defaults block
that every subsequent run inherits (and may sparsely override via config_override).
The system_prompt is permanently fixed. Everything in defaults is, well, a
default — runs can replace any individual field.
The configuration applied to every run on this conversation by default. Each field
can be overridden per-run via config_override on the POST .../runs body, except
system_prompt which is fixed at conversation creation time.
For mcp_servers and tools, overrides replace the whole list, not individual
entries. There is no per-server or per-tool merge — set the complete catalog you want
for that run.
In a request only model, data_plane_id and execution_cluster are required. A response
(defaults, effective_config) always carries every key, with null for an optional field
that has no value.
Show child attributes
Show child attributes
Optional human-readable label for your own use (logs, dashboards). The model never sees this. Leave it out (or null) and the platform names the conversation from its first user message.
"rate-limiting q&a"
"Stage direction" prepended to every run as a system-role message. Cannot be
overridden per-run — if you need different system prompts, create separate
conversations. Leaving it empty is allowed but rarely useful; even one line
("You are a helpful assistant. Answer concisely.") shapes model behavior.
"You are an AI assistant that answers questions about the Narrative Data Marketplace. Use the available tools to look things up before answering."
Response
Conversation created. Returns the persisted conversation row.
The conversation row as the API returns it. The same shape comes back from
POST /agents/conversations (201 Created) and GET /agents/conversations/{id} (200 OK).
A conversation may also carry platform-written tags — recording, for instance, the workflow
whose task created it. They are reserved (the _nio_ prefix), are not settable, and are not
returned here.
UUID identifying a conversation. Returned from POST /agents/conversations and used
in every other agent endpoint that operates on this conversation.
"bc2505b7-068d-44ed-8055-a6f6ffe54ab1"
Company ID derived from the bearer token. Pinned for the conversation's lifetime.
1
User ID derived from the bearer token. Pinned for the conversation's lifetime and gates every subsequent read endpoint — only the originating user can fetch the conversation, its messages, or its runs. Peers in the same company see 404.
407
The configuration applied to every run on this conversation by default. Each field
can be overridden per-run via config_override on the POST .../runs body, except
system_prompt which is fixed at conversation creation time.
For mcp_servers and tools, overrides replace the whole list, not individual
entries. There is no per-server or per-tool merge — set the complete catalog you want
for that run.
In a request only model, data_plane_id and execution_cluster are required. A response
(defaults, effective_config) always carries every key, with null for an optional field
that has no value.
Show child attributes
Show child attributes
Monotonic per-conversation counter, bumped by 1 (or more) every time a successful run appends messages. Two roles:
- Delta cursor for
GET .../messages?since=N— fetch only messages withsequence_no > N. - Compare-and-swap token for
POST .../runs— setexpected_versionto the conversation's current head; if it doesn't match at run-creation time, you get a Version Conflict (HTTP 409).
Always start a new run cycle by reading the current version from
GET /agents/conversations/{id} rather than caching a value from earlier.
x >= 04
"2026-05-18T13:21:30.355180Z"
"2026-05-18T13:21:51.983952Z"
Was this page helpful?

