Run a Function in real time
curl --request POST \
--url https://your-sutro-deployment.example.com/v1/functions/{name}/run \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"input": {},
"confidence_scoring": true
}
'import requests
url = "https://your-sutro-deployment.example.com/v1/functions/{name}/run"
payload = {
"input": {},
"confidence_scoring": True
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({input: {}, confidence_scoring: true})
};
fetch('https://your-sutro-deployment.example.com/v1/functions/{name}/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://your-sutro-deployment.example.com/v1/functions/{name}/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([
'input' => [
],
'confidence_scoring' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$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://your-sutro-deployment.example.com/v1/functions/{name}/run"
payload := strings.NewReader("{\n \"input\": {},\n \"confidence_scoring\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://your-sutro-deployment.example.com/v1/functions/{name}/run")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"input\": {},\n \"confidence_scoring\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://your-sutro-deployment.example.com/v1/functions/{name}/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"input\": {},\n \"confidence_scoring\": true\n}"
response = http.request(request)
puts response.read_body{
"request_id": "<string>",
"function": {},
"output": {},
"confidence": {},
"usage": {}
}API
Run a Function in real time
Execute a published Function on one input and wait for the answer.
POST
/
v1
/
functions
/
{name}
/
run
Run a Function in real time
curl --request POST \
--url https://your-sutro-deployment.example.com/v1/functions/{name}/run \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"input": {},
"confidence_scoring": true
}
'import requests
url = "https://your-sutro-deployment.example.com/v1/functions/{name}/run"
payload = {
"input": {},
"confidence_scoring": True
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({input: {}, confidence_scoring: true})
};
fetch('https://your-sutro-deployment.example.com/v1/functions/{name}/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://your-sutro-deployment.example.com/v1/functions/{name}/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([
'input' => [
],
'confidence_scoring' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$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://your-sutro-deployment.example.com/v1/functions/{name}/run"
payload := strings.NewReader("{\n \"input\": {},\n \"confidence_scoring\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://your-sutro-deployment.example.com/v1/functions/{name}/run")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"input\": {},\n \"confidence_scoring\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://your-sutro-deployment.example.com/v1/functions/{name}/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"input\": {},\n \"confidence_scoring\": true\n}"
response = http.request(request)
puts response.read_body{
"request_id": "<string>",
"function": {},
"output": {},
"confidence": {},
"usage": {}
}Run a published Function on a single input. Hosted providers return the answer
with HTTP
Any other field returns
The response then carries the single answer with
Hosted providers accept PNG, JPEG, WebP, and PDF up to 20 MiB per asset.
Native vision models accept PNG, JPEG, and WebP up to 5 MiB each, with at most
eight images per row. The bytes are
sniffed, so a declared
Send
Every successful answer is also recorded in the Function’s Monitoring
tab, and low-confidence answers are added to Needs Review.
Deployment operators can change hosted defaults with
Requests are never retried automatically: a Function run can incur inference
costs, and a caller waiting on an answer should decide for itself whether to try
again.
The Python SDK wraps this endpoint as
200; native sidecar Functions return HTTP 202 and an authenticated
polling path. The Function supplies its optimized prompt, model, output schema, and
sampling defaults; none of them can be overridden per request. Use
Batch instead for tables of inputs.
Configure your deployment URL and API key before
using the examples below. Use the deployment where you published the Function.
string
required
The published Function name, without a namespace or revision.
Headers
string
required
Deployment API key in the form
Key YOUR_SUTRO_API_KEY.string
required
application/json. The body is limited to 32 MB.Body
object | string
required
The Function’s input fields. Keys must match the Function’s configured inputs; every field is required and unknown fields are rejected. Values that are not strings are converted the same way Batch converts a row:
null becomes an empty string, objects and lists become JSON, and anything else becomes its plain string form. A bare string is accepted in place of the object when the Function has exactly one text input. Image and PDF fields take an asset value.boolean
default:"true"
Whether to compute a confidence score for the answer. When
false, confidence is null. The answer still appears in Monitoring but is never added to Needs Review.422 invalid_input.
Run a published Function
curl --fail-with-body "${SUTRO_API_URL%/}/v1/functions/support-escalation/run" \
-H "Authorization: Key $SUTRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {"text": "The customer reports an unrecognized charge."}
}'
Confidence scores
The confidence score is computed the same way as in Batch and adds cost and latency to a request. A caller that will not act on the score can turn it off per request:curl --fail-with-body "${SUTRO_API_URL%/}/v1/functions/support-escalation/run" \
-H "Authorization: Key $SUTRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {"text": "The customer reports an unrecognized charge."},
"confidence_scoring": false
}'
"confidence": null.
Image and PDF inputs
An image or PDF input field takes one of three values.| Value | Shape |
|---|---|
| Inline bytes | {"base64": "...", "mime_type": "image/png"} |
| URL | {"url": "https://..."}. https only, public hosts only (no private, loopback, or link-local addresses), streamed with a 10 second timeout. |
| Stored asset | {"name": "march-invoice.pdf"}, or the name as a bare string. |
curl --fail-with-body "${SUTRO_API_URL%/}/v1/functions/invoice-reader/run" \
-H "Authorization: Key $SUTRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"note": "check page 2",
"scan": {"base64": "JVBERi0...", "mime_type": "application/pdf"},
"logo": {"url": "https://cdn.example.com/logo.png"},
"prior": {"name": "march-invoice.pdf"}
}
}'
type or mime_type that disagrees with the actual
content is rejected rather than passed to the model.
Native acceptance, polling, and cancellation
A native sidecar Function returns HTTP202 with a run handle:
{
"request_id": "rt_5d0c2f1e8a4b4c9e9f1a2b3c4d5e6f70",
"state": "pending",
"poll_path": "/v1/functions/support-escalation/runs/rt_5d0c2f1e8a4b4c9e9f1a2b3c4d5e6f70",
"deadline_seconds": 1800,
"retry_after_seconds": 1
}
GET to the returned poll_path on the same deployment with the original
API key. Wait the Retry-After interval between polls. HTTP 202 means the run
is still pending; HTTP 200 returns the completed response. A terminal failure
returns its ordinary error status and body. Polling does not repeat inference
or charge the request rate limit again.
# Set this to the request_id returned by POST.
REQUEST_ID="rt_5d0c2f1e8a4b4c9e9f1a2b3c4d5e6f70"
RUN_URL="${SUTRO_API_URL%/}/v1/functions/support-escalation/runs/$REQUEST_ID"
curl -i "$RUN_URL" -H "Authorization: Key $SUTRO_API_KEY"
# Cancel a pending run when its result is no longer needed.
curl -X DELETE "$RUN_URL" -H "Authorization: Key $SUTRO_API_KEY"
DELETE returns HTTP 202 while cancellation is pending, or HTTP 200 once
the run is terminal. Polling a cancelled run returns 409 cancelled. Unknown
run IDs and runs owned by another key or Function return 404 request_not_found.
The original deadline defaults to 1,800 seconds and includes worker startup;
polling does not extend it. Interrupted runs return 503 interrupted without
replaying inference. Hosted Functions keep their existing synchronous behavior.
The Python SDK handles this protocol
automatically while run_function() waits for the answer.
Completed response
{
"request_id": "rt_01j7wnq3f8k2c9x4",
"function": {
"name": "support-escalation",
"model": "claude-sonnet-4-5",
"model_source": "model-sweep"
},
"output": {"label": "billing", "reasoning": "..."},
"confidence": 0.8,
"usage": {"input_tokens": 412, "output_tokens": 38, "cost_usd": 0.0016}
}
string
This request’s ID. It also appears in the Function’s Monitoring tab and in every error body, for log and support lookups.
object
The Function that answered: its
name, the base model, and model_source. model_source is model-sweep when a model was set active from a model sweep, or sutro-default when the Function ran its latest iteration’s prompt on the Sutro default model.object | string
The answer, parsed against the Function’s output schema. A string when the Function has no schema.
number | null
A confidence score between 0 and 1 for this answer, computed the same way as in Batch. Answers at or below
0.6 are the ones worth a human look. See confidence scores. null when the request set confidence_scoring to false.object
Provider-reported
input_tokens and output_tokens, plus estimated provider
cost_usd when pricing is available, for the whole request.Limits
| Limit | Default |
|---|---|
| Requests per API key | 10 per second, bursting to 20 |
| In-flight requests per model | 64 per deployment |
| Hosted request timeout | 90 seconds |
| Native request deadline, including worker startup | 1,800 seconds |
| Input size | 200,000 characters, counted after the input fields are joined into the prompt the model receives |
| Asset size | Hosted: 20 MiB each; native PNG/JPEG/WebP: 5 MiB each |
| Request body | 32 MB |
HARMONIZE_REALTIME_*.
Native deadlines use HARMONIZE_NATIVE_FUNCTION_TIMEOUT_SECONDS; aggregate
pending inputs default to 64 MiB with HARMONIZE_NATIVE_FUNCTION_PENDING_BYTES.
Errors
Failures return{"detail": ..., "code": ..., "request_id": ...}. A 429 or
503 that can be retried carries a Retry-After header with the number of
seconds to wait.
| Status | code | Cause |
|---|---|---|
| 401 | unauthorized | Missing or invalid API key. |
| 404 | function_not_found | No Function by that name in this deployment. |
| 404 | request_not_found | The native run does not exist or does not belong to this key and Function. |
| 409 | cancelled | The native run was cancelled. |
| 409 | no_runnable_prompt | The Function has no published or completed prompt to run yet. |
| 409 | deployment_unpublished | The latest deploy or completed iteration failed to publish to Batch, so real time refuses to serve a prompt Batch does not. Retry the publish. |
| 413 | payload_too_large | The request body is over 32 MB. |
| 422 | invalid_input | Malformed body, a field other than input or confidence_scoring, missing, unknown, or oversized input, or an unreadable asset. |
| 422 | not_servable | The Function’s active model cannot serve it in real time. The message says why. |
| 429 | rate_limited | Your key’s request rate. See Retry-After. |
| 429 | at_capacity | The deployment has no room for another request on this model right now. Retry after Retry-After. |
| 429 | provider_rate_limited | The model provider rate limited the request. See Retry-After. |
| 502 | provider_error | The model provider failed or returned an unusable answer. |
| 503 | auth_unavailable | The deployment could not verify the API key. Retry. |
| 503 | interrupted | The native run’s process stopped; inference is not replayed. |
| 503 | provider_not_configured | No API key is configured for the Function’s provider. Add one in the app’s provider settings. |
| 503 | inference_spend_circuit_open | The deployment’s paid-inference budget is paused. See Retry-After. |
| 504 | timeout | The request exceeded its hosted or native deadline. |
run_function().