EQTY LabDocs

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

gethttps://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status
bash
curl --request GET \
  --url 'https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/configuration-status' \
  --header 'Authorization: Bearer <token>'
javascript
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();
typescript
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();
python
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())
go
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))
}
java
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());
    }
}
csharp
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
<?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;
ruby
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}"
rust
// 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

NameTypeDescription
orgId
required
string

Organization ID or UUID (urn:uuid optional)

assessmentId
required
string

Assessment UUID (urn:uuid optional)

Responses

200Configuration status

application/json
  • checkedAtstring<date-time>
  • currentConfigurationCidstring
  • currentObservationcore.AssessmentObservation
    Show core.AssessmentObservation
    • correlationIdstring

      The exchange's correlation ID

    • observedAtstring<date-time>

      When the gateway verified the exchange carrying it

    • requestobject

      Per-request detail, evidence rather than configuration

      Show properties
      • modelstring
      • providerstring
      • systemPromptCidstring
      • toolsstring[]
    • stateCidstring

      The observed state in the gateway's store

    • subAgentstring

      The custom agent's sub-agent that made the request, /-separated when nested; it shares the agent's configuration

    • viperVersionstring

      The Viper version that captured it

  • detailstring
  • pinnedConfigurationCidstring
  • reasonobject

    Set only when status is unknown

    One ofnot_capturedcontrol_plane_unavailableagent_unavailableagent_inactiveno_current_statecurrent_state_unusableschema_changed

    Show 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_changed

  • statusobject

    One ofmatchmismatchunknown

    Show properties

    object (enum) · one of match, mismatch, unknown

  • submissioninteger

    The submission whose frozen configuration was compared; absent when the draft's pin was, before any submission

Examplejson
{
  "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

application/json
  • errorstring
Examplejson
{
  "error": "Invalid request body"
}

401Unauthorized - Authentication required

application/json
  • errorstring
Examplejson
{
  "error": "Invalid request body"
}

403Forbidden - No organization access, or the agent registry refuses the caller

application/json
  • errorstring
Examplejson
{
  "error": "Invalid request body"
}

404Assessment not found, or not readable by the caller

application/json
  • errorstring
Examplejson
{
  "error": "Invalid request body"
}

500Internal server error

application/json
  • errorstring
Examplejson
{
  "error": "Invalid request body"
}