curl --request POST \
--url https://api.sidenet.ai/v1/agents/{id}/run \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"messages": [
{
"role": "user",
"parts": [
{
"type": "text",
"text": "Where is my order?"
}
]
}
],
"approval": {
"runId": "run_6d20a95c",
"toolCallId": "call_a17f3b",
"approved": true
},
"agentVersionId": "b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55",
"threadId": "thread_2f81c04a",
"context": [
"The customer is on the enterprise plan."
],
"variables": {
"locale": "English",
"instance": {
"store_count": 12
}
},
"tools": {
"Acme_CRM_get_customer": {
"enabled": true
}
},
"metadata": {
"source": "web-widget"
},
"use_routing": true,
"suggest_followups": true
}
'import requests
url = "https://api.sidenet.ai/v1/agents/{id}/run"
payload = {
"messages": [
{
"role": "user",
"parts": [
{
"type": "text",
"text": "Where is my order?"
}
]
}
],
"approval": {
"runId": "run_6d20a95c",
"toolCallId": "call_a17f3b",
"approved": True
},
"agentVersionId": "b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55",
"threadId": "thread_2f81c04a",
"context": ["The customer is on the enterprise plan."],
"variables": {
"locale": "English",
"instance": { "store_count": 12 }
},
"tools": { "Acme_CRM_get_customer": { "enabled": True } },
"metadata": { "source": "web-widget" },
"use_routing": True,
"suggest_followups": True
}
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({
messages: [{role: 'user', parts: [{type: 'text', text: 'Where is my order?'}]}],
approval: {runId: 'run_6d20a95c', toolCallId: 'call_a17f3b', approved: true},
agentVersionId: 'b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55',
threadId: 'thread_2f81c04a',
context: ['The customer is on the enterprise plan.'],
variables: {locale: 'English', instance: {store_count: 12}},
tools: {Acme_CRM_get_customer: {enabled: true}},
metadata: {source: 'web-widget'},
use_routing: true,
suggest_followups: true
})
};
fetch('https://api.sidenet.ai/v1/agents/{id}/run', 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.sidenet.ai/v1/agents/{id}/run",
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([
'messages' => [
[
'role' => 'user',
'parts' => [
[
'type' => 'text',
'text' => 'Where is my order?'
]
]
]
],
'approval' => [
'runId' => 'run_6d20a95c',
'toolCallId' => 'call_a17f3b',
'approved' => true
],
'agentVersionId' => 'b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55',
'threadId' => 'thread_2f81c04a',
'context' => [
'The customer is on the enterprise plan.'
],
'variables' => [
'locale' => 'English',
'instance' => [
'store_count' => 12
]
],
'tools' => [
'Acme_CRM_get_customer' => [
'enabled' => true
]
],
'metadata' => [
'source' => 'web-widget'
],
'use_routing' => true,
'suggest_followups' => true
]),
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.sidenet.ai/v1/agents/{id}/run"
payload := strings.NewReader("{\n \"messages\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"type\": \"text\",\n \"text\": \"Where is my order?\"\n }\n ]\n }\n ],\n \"approval\": {\n \"runId\": \"run_6d20a95c\",\n \"toolCallId\": \"call_a17f3b\",\n \"approved\": true\n },\n \"agentVersionId\": \"b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55\",\n \"threadId\": \"thread_2f81c04a\",\n \"context\": [\n \"The customer is on the enterprise plan.\"\n ],\n \"variables\": {\n \"locale\": \"English\",\n \"instance\": {\n \"store_count\": 12\n }\n },\n \"tools\": {\n \"Acme_CRM_get_customer\": {\n \"enabled\": true\n }\n },\n \"metadata\": {\n \"source\": \"web-widget\"\n },\n \"use_routing\": true,\n \"suggest_followups\": true\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.sidenet.ai/v1/agents/{id}/run")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"messages\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"type\": \"text\",\n \"text\": \"Where is my order?\"\n }\n ]\n }\n ],\n \"approval\": {\n \"runId\": \"run_6d20a95c\",\n \"toolCallId\": \"call_a17f3b\",\n \"approved\": true\n },\n \"agentVersionId\": \"b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55\",\n \"threadId\": \"thread_2f81c04a\",\n \"context\": [\n \"The customer is on the enterprise plan.\"\n ],\n \"variables\": {\n \"locale\": \"English\",\n \"instance\": {\n \"store_count\": 12\n }\n },\n \"tools\": {\n \"Acme_CRM_get_customer\": {\n \"enabled\": true\n }\n },\n \"metadata\": {\n \"source\": \"web-widget\"\n },\n \"use_routing\": true,\n \"suggest_followups\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sidenet.ai/v1/agents/{id}/run")
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 \"messages\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"type\": \"text\",\n \"text\": \"Where is my order?\"\n }\n ]\n }\n ],\n \"approval\": {\n \"runId\": \"run_6d20a95c\",\n \"toolCallId\": \"call_a17f3b\",\n \"approved\": true\n },\n \"agentVersionId\": \"b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55\",\n \"threadId\": \"thread_2f81c04a\",\n \"context\": [\n \"The customer is on the enterprise plan.\"\n ],\n \"variables\": {\n \"locale\": \"English\",\n \"instance\": {\n \"store_count\": 12\n }\n },\n \"tools\": {\n \"Acme_CRM_get_customer\": {\n \"enabled\": true\n }\n },\n \"metadata\": {\n \"source\": \"web-widget\"\n },\n \"use_routing\": true,\n \"suggest_followups\": true\n}"
response = http.request(request)
puts response.read_body{
"threadId": "<string>",
"requestId": "<string>",
"text": "<string>",
"reasoning": "<string>",
"toolCalls": [
{
"toolCallId": "<string>",
"toolName": "<string>",
"input": {},
"output": {},
"error": "<string>"
}
],
"data": [
{
"type": "<string>",
"data": {}
}
],
"errors": [
"<string>"
],
"finishReason": "<string>"
}Run agent
Runs the agent’s active published version against messages. Send agentVersionId to run a specific version (a draft, or an older published one) instead. Returns the finished turn as JSON: text is the answer, toolCalls what the agent called on the way, data the custom parts. This is the same run POST /v1/chat performs — same routing, memory, tools, usage accounting and cost — with the stream collected server-side, so it responds only when the turn is complete and takes as long as the turn takes. Use /v1/chat when you want tokens as they are generated. Pass the returned threadId back to continue the conversation.
curl --request POST \
--url https://api.sidenet.ai/v1/agents/{id}/run \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"messages": [
{
"role": "user",
"parts": [
{
"type": "text",
"text": "Where is my order?"
}
]
}
],
"approval": {
"runId": "run_6d20a95c",
"toolCallId": "call_a17f3b",
"approved": true
},
"agentVersionId": "b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55",
"threadId": "thread_2f81c04a",
"context": [
"The customer is on the enterprise plan."
],
"variables": {
"locale": "English",
"instance": {
"store_count": 12
}
},
"tools": {
"Acme_CRM_get_customer": {
"enabled": true
}
},
"metadata": {
"source": "web-widget"
},
"use_routing": true,
"suggest_followups": true
}
'import requests
url = "https://api.sidenet.ai/v1/agents/{id}/run"
payload = {
"messages": [
{
"role": "user",
"parts": [
{
"type": "text",
"text": "Where is my order?"
}
]
}
],
"approval": {
"runId": "run_6d20a95c",
"toolCallId": "call_a17f3b",
"approved": True
},
"agentVersionId": "b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55",
"threadId": "thread_2f81c04a",
"context": ["The customer is on the enterprise plan."],
"variables": {
"locale": "English",
"instance": { "store_count": 12 }
},
"tools": { "Acme_CRM_get_customer": { "enabled": True } },
"metadata": { "source": "web-widget" },
"use_routing": True,
"suggest_followups": True
}
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({
messages: [{role: 'user', parts: [{type: 'text', text: 'Where is my order?'}]}],
approval: {runId: 'run_6d20a95c', toolCallId: 'call_a17f3b', approved: true},
agentVersionId: 'b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55',
threadId: 'thread_2f81c04a',
context: ['The customer is on the enterprise plan.'],
variables: {locale: 'English', instance: {store_count: 12}},
tools: {Acme_CRM_get_customer: {enabled: true}},
metadata: {source: 'web-widget'},
use_routing: true,
suggest_followups: true
})
};
fetch('https://api.sidenet.ai/v1/agents/{id}/run', 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.sidenet.ai/v1/agents/{id}/run",
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([
'messages' => [
[
'role' => 'user',
'parts' => [
[
'type' => 'text',
'text' => 'Where is my order?'
]
]
]
],
'approval' => [
'runId' => 'run_6d20a95c',
'toolCallId' => 'call_a17f3b',
'approved' => true
],
'agentVersionId' => 'b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55',
'threadId' => 'thread_2f81c04a',
'context' => [
'The customer is on the enterprise plan.'
],
'variables' => [
'locale' => 'English',
'instance' => [
'store_count' => 12
]
],
'tools' => [
'Acme_CRM_get_customer' => [
'enabled' => true
]
],
'metadata' => [
'source' => 'web-widget'
],
'use_routing' => true,
'suggest_followups' => true
]),
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.sidenet.ai/v1/agents/{id}/run"
payload := strings.NewReader("{\n \"messages\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"type\": \"text\",\n \"text\": \"Where is my order?\"\n }\n ]\n }\n ],\n \"approval\": {\n \"runId\": \"run_6d20a95c\",\n \"toolCallId\": \"call_a17f3b\",\n \"approved\": true\n },\n \"agentVersionId\": \"b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55\",\n \"threadId\": \"thread_2f81c04a\",\n \"context\": [\n \"The customer is on the enterprise plan.\"\n ],\n \"variables\": {\n \"locale\": \"English\",\n \"instance\": {\n \"store_count\": 12\n }\n },\n \"tools\": {\n \"Acme_CRM_get_customer\": {\n \"enabled\": true\n }\n },\n \"metadata\": {\n \"source\": \"web-widget\"\n },\n \"use_routing\": true,\n \"suggest_followups\": true\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.sidenet.ai/v1/agents/{id}/run")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"messages\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"type\": \"text\",\n \"text\": \"Where is my order?\"\n }\n ]\n }\n ],\n \"approval\": {\n \"runId\": \"run_6d20a95c\",\n \"toolCallId\": \"call_a17f3b\",\n \"approved\": true\n },\n \"agentVersionId\": \"b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55\",\n \"threadId\": \"thread_2f81c04a\",\n \"context\": [\n \"The customer is on the enterprise plan.\"\n ],\n \"variables\": {\n \"locale\": \"English\",\n \"instance\": {\n \"store_count\": 12\n }\n },\n \"tools\": {\n \"Acme_CRM_get_customer\": {\n \"enabled\": true\n }\n },\n \"metadata\": {\n \"source\": \"web-widget\"\n },\n \"use_routing\": true,\n \"suggest_followups\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sidenet.ai/v1/agents/{id}/run")
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 \"messages\": [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"type\": \"text\",\n \"text\": \"Where is my order?\"\n }\n ]\n }\n ],\n \"approval\": {\n \"runId\": \"run_6d20a95c\",\n \"toolCallId\": \"call_a17f3b\",\n \"approved\": true\n },\n \"agentVersionId\": \"b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55\",\n \"threadId\": \"thread_2f81c04a\",\n \"context\": [\n \"The customer is on the enterprise plan.\"\n ],\n \"variables\": {\n \"locale\": \"English\",\n \"instance\": {\n \"store_count\": 12\n }\n },\n \"tools\": {\n \"Acme_CRM_get_customer\": {\n \"enabled\": true\n }\n },\n \"metadata\": {\n \"source\": \"web-widget\"\n },\n \"use_routing\": true,\n \"suggest_followups\": true\n}"
response = http.request(request)
puts response.read_body{
"threadId": "<string>",
"requestId": "<string>",
"text": "<string>",
"reasoning": "<string>",
"toolCalls": [
{
"toolCallId": "<string>",
"toolName": "<string>",
"input": {},
"output": {},
"error": "<string>"
}
],
"data": [
{
"type": "<string>",
"data": {}
}
],
"errors": [
"<string>"
],
"finishReason": "<string>"
}Authorizations
Session token (snat_…) minted by POST /v1/token. Carries the organization and the end user; safe in a browser.
Path Parameters
Agent id.
"6f1c0f4e-2b7a-4a51-9a2f-0c9d1b3e5a10"
Body
The conversation, in AI SDK UIMessage format: [{ "role": "user", "parts": [{ "type": "text", "text": "..." }] }]. Send the whole exchange you want the agent to see; with a threadId the stored history is loaded too, so the new turn is usually the only entry. May be empty only on an approval continuation.
[
{
"role": "user",
"parts": [
{
"type": "text",
"text": "Where is my order?"
}
]
}
]
Approve or decline a tool call that paused the previous stream
Show child attributes
Show child attributes
{
"runId": "run_6d20a95c",
"toolCallId": "call_a17f3b",
"approved": true
}
Optional override: run a specific agent version (e.g. preview a draft or an earlier published version) instead of the active one
"b3f7a2c8-5d19-4e6b-8f02-1a4c9e7d3b55"
Conversation thread id
"thread_2f81c04a"
Additional context messages to provide to the agent.
["The customer is on the enterprise plan."]
Values for {{variable}} placeholders in the agent's prompt blocks. Scalars (string, number, boolean) or arrays of them. A dot path up to 3 segments may be sent nested or as a dotted key — { "user": { "language": "FR" } } and { "user.language": "FR" } both fill {{user.language}}. This is the shape GET /v1/copilots/{id} and GET /v1/agents/{id} return under variables: fill in the leaves you have and send the object back. A null leaf is ignored (the placeholder falls back to its own default), so leaving one unfilled is the same as omitting it. Display-only — never used for authorization or identity. Reserved: now.*. Entries with an unsupported key or value are dropped, not rejected: a display-only field must not fail a chat turn.
Show child attributes
Show child attributes
{
"locale": "English",
"instance": { "store_count": 12 }
}
AI SDK trigger type
submit-message, regenerate-message AI SDK client-side tools
Show child attributes
Show child attributes
{
"Acme_CRM_get_customer": { "enabled": true }
}
AI SDK session metadata
Show child attributes
Show child attributes
{ "source": "web-widget" }
Default true. When the request targets an orchestrator agent, routing picks whether to stream the orchestrator (multi-step / synthesis) or a single subagent directly (domain-specific ask). No effect when the resolved agent is not an orchestrator. Pass false to disable.
Default true. After the answer finishes streaming, a small model proposes up to 3 questions the user could ask next, emitted as a data-followups chunk for the client to render as chips. Costs one extra model call per turn and holds the stream open slightly longer — pass false to disable. Only applies to copilotId requests: an agentId run has no UI to render chips into, so suggestions never run there.
Response
The finished turn
The conversation this turn belongs to — the one you sent, or the one created for you. Send it back on the next call to continue.
Correlation id for this run; the join key for its traces and cost.
The agent's answer.
Reasoning text, when the model emitted any. Absent otherwise.
The tools the agent called, in order, each with its input and either its output or the error it failed with.
Show child attributes
Show child attributes
Custom parts the run emitted: data-handoff (which agent a network routed to), data-tool-workflow (workflow step progress), and data-tool-call-approval — that last one means the run PAUSED for human approval rather than finishing. Call again with approval and the same threadId to continue it.
Show child attributes
Show child attributes
Errors the run reported. A turn can fail after it began answering, so this can be non-empty alongside text — and the status is still 200, because the same failure over /v1/chat happens long after the headers.