curl --request POST \
--url https://api.persona.hasanraiyan.me/api/v1/developer/agui \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-agent-id: <x-agent-id>' \
--header 'x-persona-external-user-id: <x-persona-external-user-id>' \
--data '
{
"messages": [
{
"content": "<string>"
}
],
"resume": {},
"contextOverride": "<string>"
}
'import requests
url = "https://api.persona.hasanraiyan.me/api/v1/developer/agui"
payload = {
"messages": [{ "content": "<string>" }],
"resume": {},
"contextOverride": "<string>"
}
headers = {
"x-agent-id": "<x-agent-id>",
"x-persona-external-user-id": "<x-persona-external-user-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-agent-id': '<x-agent-id>',
'x-persona-external-user-id': '<x-persona-external-user-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({messages: [{content: '<string>'}], resume: {}, contextOverride: '<string>'})
};
fetch('https://api.persona.hasanraiyan.me/api/v1/developer/agui', 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.persona.hasanraiyan.me/api/v1/developer/agui",
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' => [
[
'content' => '<string>'
]
],
'resume' => [
],
'contextOverride' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-agent-id: <x-agent-id>",
"x-persona-external-user-id: <x-persona-external-user-id>"
],
]);
$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.persona.hasanraiyan.me/api/v1/developer/agui"
payload := strings.NewReader("{\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"resume\": {},\n \"contextOverride\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-agent-id", "<x-agent-id>")
req.Header.Add("x-persona-external-user-id", "<x-persona-external-user-id>")
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.persona.hasanraiyan.me/api/v1/developer/agui")
.header("x-agent-id", "<x-agent-id>")
.header("x-persona-external-user-id", "<x-persona-external-user-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"resume\": {},\n \"contextOverride\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.persona.hasanraiyan.me/api/v1/developer/agui")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-agent-id"] = '<x-agent-id>'
request["x-persona-external-user-id"] = '<x-persona-external-user-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"resume\": {},\n \"contextOverride\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyRun an Agent as an external user, streaming AG-UI events (SSE)
Requires a ProjectRuntimeContext — the credential must be paired with the x-persona-external-user-id header asserting which of the Project’s own external users is running the Agent. Reuses the exact same runtime as the Persona AG-UI route. Pass x-thread-id (a Thread id from POST /api/v1/developer/threads) to resume a named conversation — omit it to keep using the implicit, Domain-extended deterministic thread id (one conversation per Agent + external user). An unrecognized/foreign/wrong-agent x-thread-id is rejected with 404 rather than silently falling back to the deterministic id (same contract as the Persona AG-UI route).
curl --request POST \
--url https://api.persona.hasanraiyan.me/api/v1/developer/agui \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-agent-id: <x-agent-id>' \
--header 'x-persona-external-user-id: <x-persona-external-user-id>' \
--data '
{
"messages": [
{
"content": "<string>"
}
],
"resume": {},
"contextOverride": "<string>"
}
'import requests
url = "https://api.persona.hasanraiyan.me/api/v1/developer/agui"
payload = {
"messages": [{ "content": "<string>" }],
"resume": {},
"contextOverride": "<string>"
}
headers = {
"x-agent-id": "<x-agent-id>",
"x-persona-external-user-id": "<x-persona-external-user-id>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-agent-id': '<x-agent-id>',
'x-persona-external-user-id': '<x-persona-external-user-id>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({messages: [{content: '<string>'}], resume: {}, contextOverride: '<string>'})
};
fetch('https://api.persona.hasanraiyan.me/api/v1/developer/agui', 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.persona.hasanraiyan.me/api/v1/developer/agui",
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' => [
[
'content' => '<string>'
]
],
'resume' => [
],
'contextOverride' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-agent-id: <x-agent-id>",
"x-persona-external-user-id: <x-persona-external-user-id>"
],
]);
$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.persona.hasanraiyan.me/api/v1/developer/agui"
payload := strings.NewReader("{\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"resume\": {},\n \"contextOverride\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-agent-id", "<x-agent-id>")
req.Header.Add("x-persona-external-user-id", "<x-persona-external-user-id>")
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.persona.hasanraiyan.me/api/v1/developer/agui")
.header("x-agent-id", "<x-agent-id>")
.header("x-persona-external-user-id", "<x-persona-external-user-id>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"resume\": {},\n \"contextOverride\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.persona.hasanraiyan.me/api/v1/developer/agui")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-agent-id"] = '<x-agent-id>'
request["x-persona-external-user-id"] = '<x-persona-external-user-id>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"messages\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"resume\": {},\n \"contextOverride\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyAuthorizations
Developer Platform Project credential, minted via POST /api/v1/projects/{projectId}/credentials. Send as Authorization: Bearer <keyId>.<secret>. Optionally pair with the x-persona-external-user-id header to act on behalf of one of the Project's own external users. This credential is a server-side secret — see the Integration Guide.
Headers
A Thread id from the Developer Thread CRUD API — resumes that conversation instead of the implicit deterministic one.
Body
Show child attributes
Show child attributes
Resume data for a Thread paused on a human-in-the-loop interrupt (e.g. an agent-management tool the Agent's interruptOn config requires confirming). Pass { type: "decision", decision: "continue" | "reject" } to approve/deny a pending tool call, or an object shaped for the specific clarification the interrupted run is waiting on.
Caller-supplied context (e.g. a live founder profile snapshot) appended to this turn's system prompt only. Never persisted to any memory file and never visible to later turns.
4000Response
A text/event-stream SSE stream of AG-UI protocol events (the standard @ag-ui/core EventType values): RUN_STARTED once at the start of the run; TEXT_MESSAGE_CHUNK for streamed assistant text deltas; REASONING_MESSAGE_START/CONTENT/END for models that expose reasoning; TOOL_CALL_CHUNK/TOOL_CALL_RESULT for tool invocations and their results; STATE_SNAPSHOT for full-state updates; CUSTOM for Persona-specific side-channel events (e.g. subagent traces, MCP structured content, MCP App widgets); RUN_ERROR (native @ag-ui/core event, not CUSTOM) with code/message/retryable/providerName when the run fails genuinely rather than pausing on an interrupt — see GET /api/v1/developer/agui/schema for the CUSTOM event payload shapes and the RUN_ERROR code enum; and RUN_FINISHED once at the end. Each event is a JSON object sent as one data: line per SSE convention.