Compare an assessment's configuration with the agent's current one
Compare the configuration an assessment's newest submission froze, or its draft's pin before it was ever submitted, with what the agent runs now; submission says which submission was compared. An agent runs as one key or many, so each of its active keys counts by its newest request, however long ago: the result is match while any key's newest request gives the compared configuration, whichever key signed the state it was pinned from, and mismatch once every key runs another, with currentConfigurationCid the one the newest of them runs. An agent whose requests all predate the gateway recording configurations is compared by its newest state instead, until its next request. It is computed on every read, and unknown with a reason when the comparison cannot be made (agent registry unavailable, agent not visible or inactive, no active key's newest request gave a configuration, an unusable current state, a current configuration derived under another schema version, or nothing captured to compare). An assessment with no pinned configuration is refused
https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-statuscurl --request GET \
--url 'https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status' \
--header 'Authorization: Bearer <token>'const response = await fetch("https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status", {
method: "GET",
headers: {
"Authorization": "Bearer <token>"
}
});
const data = await response.json();interface AssessmentConfigurationStatus {
checkedAt?: string;
currentConfigurationCid?: string;
currentObservation?: Record<string, unknown>;
detail?: string;
pinnedConfigurationCid?: string;
reason?: "not_captured" | "control_plane_unavailable" | "agent_unavailable" | "agent_inactive" | "no_current_state" | "current_state_unusable" | "schema_changed";
status?: "match" | "mismatch" | "unknown";
submission?: number;
}
const response = await fetch("https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status", {
method: "GET",
headers: {
"Authorization": "Bearer <token>"
}
});
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
const data: AssessmentConfigurationStatus = await response.json();import requests
response = requests.get(
"https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status",
headers={
"Authorization": "Bearer <token>",
},
)
response.raise_for_status()
print(response.json())package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, err := http.NewRequest(http.MethodGet, "https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status", nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer <token>")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(res.Status, string(data))
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status"))
.header("Authorization", "Bearer <token>")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}using System.Net.Http.Headers;
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "<token>");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");<?php
$ch = curl_init('https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer <token>',
],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
echo $status . " " . $response . PHP_EOL;require "net/http"
uri = URI("https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer <token>"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts "#{response.code} #{response.body}"// Cargo.toml dependencies: reqwest, tokio (features "full")
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let response = reqwest::Client::new()
.get("https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status")
.header("Authorization", "Bearer <token>")
.send()
.await?;
println!("{} {}", response.status(), response.text().await?);
Ok(())
}Authorizations
BearerAuth· API key in header "Authorization" — Type "Bearer" followed by a space and JWT token.
Parameters
Path parameters
| Name | Type | Description |
|---|---|---|
orgIdrequired | string | Organization ID or UUID (urn:uuid optional) |
assessmentIdrequired | string | Assessment UUID (urn:uuid optional) |
Responses
200Configuration status
checkedAtstring<date-time>currentConfigurationCidstringcurrentObservationcore.AssessmentObservationShow core.AssessmentObservation
correlationIdstringThe exchange's correlation ID
observedAtstring<date-time>When the gateway verified the exchange carrying it
requestobjectPer-request detail, evidence rather than configuration
Show properties
modelstringproviderstringsystemPromptCidstringtoolsstring[]
stateCidstringThe observed state in the gateway's store
subAgentstringThe custom agent's sub-agent that made the request, /-separated when nested; it shares the agent's configuration
viperVersionstringThe Viper version that captured it
detailstringpinnedConfigurationCidstringreasonobjectSet only when status is unknown
One of
not_capturedcontrol_plane_unavailableagent_unavailableagent_inactiveno_current_statecurrent_state_unusableschema_changedShow properties
object (enum)— Set only when status is unknown · one of not_captured, control_plane_unavailable, agent_unavailable, agent_inactive, no_current_state, current_state_unusable, schema_changedstatusobjectOne of
matchmismatchunknownShow properties
object (enum)· one of match, mismatch, unknownsubmissionintegerThe submission whose frozen configuration was compared; absent when the draft's pin was, before any submission
{
"checkedAt": "2025-01-01T00:00:00Z",
"currentConfigurationCid": "string",
"currentObservation": {
"correlationId": "string",
"observedAt": "2025-01-01T00:00:00Z",
"request": {
"model": "string",
"provider": "string",
"systemPromptCid": "string",
"tools": [
"string"
]
},
"stateCid": "string",
"subAgent": "string",
"viperVersion": "string"
},
"detail": "string",
"pinnedConfigurationCid": "string",
"reason": "not_captured",
"status": "match",
"submission": 0
}400Bad request - Invalid organization ID or assessment ID, or no configuration is pinned
errorstring
{
"error": "Invalid request body"
}401Unauthorized - Authentication required
errorstring
{
"error": "Invalid request body"
}403Forbidden - No organization access, or the agent registry refuses the caller
errorstring
{
"error": "Invalid request body"
}404Assessment not found, or not readable by the caller
errorstring
{
"error": "Invalid request body"
}500Internal server error
errorstring
{
"error": "Invalid request body"
}