curl --request POST \
--url http://127.0.0.1:4319/memory/reconcile/stream \
--header 'Content-Type: application/json' \
--data '
{
"mode": "dry_run",
"trigger": "manual",
"passes": [],
"budgetUsd": 49
}
'import requests
url = "http://127.0.0.1:4319/memory/reconcile/stream"
payload = {
"mode": "dry_run",
"trigger": "manual",
"passes": [],
"budgetUsd": 49
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({mode: 'dry_run', trigger: 'manual', passes: [], budgetUsd: 49})
};
fetch('http://127.0.0.1:4319/memory/reconcile/stream', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://127.0.0.1:4319/memory/reconcile/stream"
payload := strings.NewReader("{\n \"mode\": \"dry_run\",\n \"trigger\": \"manual\",\n \"passes\": [],\n \"budgetUsd\": 49\n}")
req, _ := http.NewRequest("POST", url, payload)
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))
}<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "4319",
CURLOPT_URL => "http://127.0.0.1:4319/memory/reconcile/stream",
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([
'mode' => 'dry_run',
'trigger' => 'manual',
'passes' => [
],
'budgetUsd' => 49
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}require 'uri'
require 'net/http'
url = URI("http://127.0.0.1:4319/memory/reconcile/stream")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"mode\": \"dry_run\",\n \"trigger\": \"manual\",\n \"passes\": [],\n \"budgetUsd\": 49\n}"
response = http.request(request)
puts response.read_bodyHttpResponse<String> response = Unirest.post("http://127.0.0.1:4319/memory/reconcile/stream")
.header("Content-Type", "application/json")
.body("{\n \"mode\": \"dry_run\",\n \"trigger\": \"manual\",\n \"passes\": [],\n \"budgetUsd\": 49\n}")
.asString();using RestSharp;
var options = new RestClientOptions("http://127.0.0.1:4319/memory/reconcile/stream");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddJsonBody("{\n \"mode\": \"dry_run\",\n \"trigger\": \"manual\",\n \"passes\": [],\n \"budgetUsd\": 49\n}", false);
var response = await client.PostAsync(request);
Console.WriteLine("{0}", response.Content);
"{\"type\":\"item\",\"runId\":\"0f2c7b18\",\"pass\":\"llm_recheck\",\"checked\":1,\"total\":200,\"found\":0}\n{\"type\":\"item\",\"runId\":\"0f2c7b18\",\"pass\":\"llm_recheck\",\"checked\":2,\"total\":200,\"found\":1}\n{\"type\":\"done\",\"run\":{\"id\":\"0f2c7b18\",\"mode\":\"apply\",\"status\":\"success\"},\"actions\":[]}\n"{
"error": "invalid request body",
"issues": [
{
"path": "query",
"message": "query must be a non-empty string"
}
]
}{
"error": "reconciliation is set to report only (RECONCILE_ENABLED=0)."
}Run the consolidation pass (NDJSON stream)
The same run, reported as it goes. NDJSON: one {"type":"item"} per belief checked, a
{"type":"ping"} every 15 seconds so the pipe never times out, and a final
{"type":"done"} carrying the report. A mid-stream failure arrives as
{"type":"error"}, since the response has already started.
Disconnecting stops the run, so nothing more is spent. Every belief already checked stays checked. The first event names the run id.
curl --request POST \
--url http://127.0.0.1:4319/memory/reconcile/stream \
--header 'Content-Type: application/json' \
--data '
{
"mode": "dry_run",
"trigger": "manual",
"passes": [],
"budgetUsd": 49
}
'import requests
url = "http://127.0.0.1:4319/memory/reconcile/stream"
payload = {
"mode": "dry_run",
"trigger": "manual",
"passes": [],
"budgetUsd": 49
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({mode: 'dry_run', trigger: 'manual', passes: [], budgetUsd: 49})
};
fetch('http://127.0.0.1:4319/memory/reconcile/stream', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://127.0.0.1:4319/memory/reconcile/stream"
payload := strings.NewReader("{\n \"mode\": \"dry_run\",\n \"trigger\": \"manual\",\n \"passes\": [],\n \"budgetUsd\": 49\n}")
req, _ := http.NewRequest("POST", url, payload)
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))
}<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "4319",
CURLOPT_URL => "http://127.0.0.1:4319/memory/reconcile/stream",
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([
'mode' => 'dry_run',
'trigger' => 'manual',
'passes' => [
],
'budgetUsd' => 49
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}require 'uri'
require 'net/http'
url = URI("http://127.0.0.1:4319/memory/reconcile/stream")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"mode\": \"dry_run\",\n \"trigger\": \"manual\",\n \"passes\": [],\n \"budgetUsd\": 49\n}"
response = http.request(request)
puts response.read_bodyHttpResponse<String> response = Unirest.post("http://127.0.0.1:4319/memory/reconcile/stream")
.header("Content-Type", "application/json")
.body("{\n \"mode\": \"dry_run\",\n \"trigger\": \"manual\",\n \"passes\": [],\n \"budgetUsd\": 49\n}")
.asString();using RestSharp;
var options = new RestClientOptions("http://127.0.0.1:4319/memory/reconcile/stream");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddJsonBody("{\n \"mode\": \"dry_run\",\n \"trigger\": \"manual\",\n \"passes\": [],\n \"budgetUsd\": 49\n}", false);
var response = await client.PostAsync(request);
Console.WriteLine("{0}", response.Content);
"{\"type\":\"item\",\"runId\":\"0f2c7b18\",\"pass\":\"llm_recheck\",\"checked\":1,\"total\":200,\"found\":0}\n{\"type\":\"item\",\"runId\":\"0f2c7b18\",\"pass\":\"llm_recheck\",\"checked\":2,\"total\":200,\"found\":1}\n{\"type\":\"done\",\"run\":{\"id\":\"0f2c7b18\",\"mode\":\"apply\",\"status\":\"success\"},\"actions\":[]}\n"{
"error": "invalid request body",
"issues": [
{
"path": "query",
"message": "query must be a non-empty string"
}
]
}{
"error": "reconciliation is set to report only (RECONCILE_ENABLED=0)."
}Headers
The owner this request acts for. Applies to every owner-scoped endpoint, reads as well
as writes. Omit it and the daemon's own default owner answers (see GET /health), which
is what a single-owner install has always used. A value that is not a uuid is refused
with 400 rather than coerced.
Body
What to run. Every field is optional.
dry_run reports and changes nothing, and never calls a model. apply acts.
dry_run, apply Recorded on the run, so the history says who started it.
manual, idle, startup Run exactly these passes, ignoring the saved settings. Omit to use the settings, which is what every shipped surface does. This overrides the settings for the three paid passes too, so a caller can start a run that spends money while the Settings toggles are off. RECONCILE_ENABLED=0 still refuses it.
invariants, entities, llm_entities, llm_conflicts, llm_recheck Keep re-checking past the per-run ceiling until nothing is due or this much has been billed, measured against the provider's own reported cost. Omit for one page and stop, which is the default. Capped at 50 because a typo here spends real money.
x <= 50Response
NDJSON progress stream ending with a done (or error) event.
The response is of type string.
"{\"type\":\"item\",\"runId\":\"0f2c7b18\",\"pass\":\"llm_recheck\",\"checked\":1,\"total\":200,\"found\":0}\n{\"type\":\"item\",\"runId\":\"0f2c7b18\",\"pass\":\"llm_recheck\",\"checked\":2,\"total\":200,\"found\":1}\n{\"type\":\"done\",\"run\":{\"id\":\"0f2c7b18\",\"mode\":\"apply\",\"status\":\"success\"},\"actions\":[]}\n"