Create agent assessment
Start an individual-agent assessment of one agent against one Governance Program version, as a draft, and register its graph with the Integrity Service under the agent's. The agent is read with the caller's token, so only an active agent the caller can see in the agent registry, with a registry UUID, can be assessed. With configuration, profileCid or both, the start pins them as the pin routes do: each is read and checked before anything is registered, so a start that can't pin them starts nothing, and the assessment is created with its pins at once. A profile can be pinned without a configuration, as its pin route allows. Without either nothing is pinned yet: the member who starts it pins a configuration, adds declarations and submits it. Assessments target agents directly and involve no project. Certification is self-service: any organization member may start one for an agent they can see, normally its owners. An integration's API key bound to no project starts one as its owner with full access or the submit_agent_assessments scope
https://localhost:10001/api/v1/organizations/{orgId}/assessmentscurl --request POST \
--url 'https://localhost:10001/api/v1/organizations/{orgId}/assessments' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{"agentId":"urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60","configuration":{"configurationCid":"string","stateCid":"string"},"profileCid":"urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw","programId":"slug:agent-baseline@1.0.0"}'const response = await fetch("https://localhost:10001/api/v1/organizations/{orgId}/assessments", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string"
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0"
})
});
const data = await response.json();interface Assessment {
agentDid?: string;
agentName?: string;
agentUrn?: string;
canCertify?: boolean;
canEdit?: boolean;
canReview?: boolean;
configuration?: Record<string, unknown>;
configurationPinnedAt?: string;
configurationPinnedByUserId?: string;
createdAt?: string;
createdBy?: string;
createdByDid?: string;
createdByUserId?: string;
draftVersion?: number;
hasUnsubmittedChanges?: boolean;
latestSubmission?: Record<string, unknown>;
observation?: Record<string, unknown>;
organizationId?: number;
profile?: Record<string, unknown>;
profilePinnedAt?: string;
profilePinnedByUserId?: string;
programManifestCid?: string;
programSlug?: string;
programUuid?: string;
status?: "draft" | "in_review" | "passed" | "failed";
uuid?: string;
}
const response = await fetch("https://localhost:10001/api/v1/organizations/{orgId}/assessments", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string"
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0"
})
});
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
const data: Assessment = await response.json();import requests
response = requests.post(
"https://localhost:10001/api/v1/organizations/{orgId}/assessments",
headers={
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
},
json={
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string",
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0",
},
)
response.raise_for_status()
print(response.json())package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string"
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0"
}`)
req, err := http.NewRequest(http.MethodPost, "https://localhost:10001/api/v1/organizations/{orgId}/assessments", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
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"))
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string"
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0"
}
"""))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, "https://localhost:10001/api/v1/organizations/{orgId}/assessments");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "<token>");
request.Content = new StringContent("""
{
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string"
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0"
}
""", Encoding.UTF8, "application/json");
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');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer <token>',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string"
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0"
}
JSON,
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")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer <token>"
request["Content-Type"] = "application/json"
request.body = <<~'JSON'
{
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string"
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0"
}
JSON
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 (features "json"), serde_json, tokio (features "full")
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let response = reqwest::Client::new()
.post("https://localhost:10001/api/v1/organizations/{orgId}/assessments")
.header("Authorization", "Bearer <token>")
.json(&json!({
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string"
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0"
}))
.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) |
Request bodyrequired
Program version and agent to assess
agentIdstringrequiredThe agent's ID in the agent registry
configurationobjectThe configuration to pin as it starts, as the configuration pin route takes it; {} pins the latest state. Nothing is pinned when omitted
Show properties
configurationCidstringA configuration one of the agent's states gave, bare or urn:cid, as the registry's configurations list them; pins it from the newest state any active key sent that gave it. Not with stateCid
stateCidstringA state from the agent's history; the latest when omitted
profileCidstringA version of the agent's operating profile to pin as it starts, bare or urn:cid; none when omitted
programIdstringrequiredProgram UUID (urn:uuid optional), slug:<slug>@<version>, or urn:cid:<manifest cid>
{
"agentId": "urn:uuid:7c1f0b9e-6f7d-5d0a-9a8e-1b2c3d4e5f60",
"configuration": {
"configurationCid": "string",
"stateCid": "string"
},
"profileCid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
"programId": "slug:agent-baseline@1.0.0"
}Responses
201Created assessment
agentDidstringread-onlyThe agent key that signed the pinned state; absent until a configuration is pinned
agentNamestringread-onlyThe name the agent registry gave the agent, read when the assessment was started and on every submission; a label for those who cannot see the agent, never evidence. Absent when the registry gave none
agentUrnstringread-onlyThe agent's control-plane registry ID, whose UUID is the root of the assessment's integrity graph
canCertifybooleanread-onlyWhether the caller may ask for the certification its passed newest submission earned: nothing is recorded for it yet, certified or revoked, they neither started the assessment nor made the submission, and they administer programs, or still review its program and made one of the reviews it rests on. False until the assessment passes. Only a single assessment's response works it out; lists leave it false
canEditbooleanread-onlyWhether the caller may change and submit the draft: they started the assessment
canReviewbooleanread-onlyWhether the caller may review its submissions: they review its program and did not start it
configurationobjectread-onlyPinned to the draft; a submission keeps its own copy, which a later pin does not change
Show properties
cidstringurn:cid of Document, registered with the Integrity Service
documentobjectThe AgentConfigurationV1 document, including its coverage. Returned as stored, so its bytes are not canonical: cid is over its JCS (RFC 8785) form, which a verifier recomputes before hashing
schemaVersionstring
configurationPinnedAtstring<date-time>read-onlyconfigurationPinnedByUserIdstringread-onlycreatedAtstring<date-time>read-onlycreatedBystringread-onlycreatedByDidstringread-onlycreatedByUserIdstringread-onlyWho started it, the only member who may change its draft; absent on assessments started before it was recorded
draftVersionintegerread-onlyIncreases with every change to the draft; submitting with it freezes exactly the draft the caller saw
hasUnsubmittedChangesbooleanread-onlyThe draft changed since its newest submission, or was never submitted
latestSubmissionobjectread-onlyAbsent until the first submission
Show properties
controlCountintegerThe program's controls, each of which is reviewed
draftVersionintegerThe draft version it froze
lastReviewedAtstring<date-time>numberintegerreviewedCountintegerControls with at least one review
statusobjectOne of
in_reviewpassedfailedShow properties
object (enum)· one of in_review, passed, failedsubmittedAtstring<date-time>uuidstringurn:uuid form
observationobjectread-onlyShow properties
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
organizationIdintegerread-onlyprofileobjectread-onlyPinned to the draft, optionally; a submission keeps its own copy, which a later pin does not change
Show properties
cidstringurn:cid of Document, registered with the Integrity Service
documentobjectThe AgentOperatingProfileV1 document, as the agent registry stores it. cid is over its JCS (RFC 8785) form
versionintegerThe agent's version number of it, as the agent registry numbers them
profilePinnedAtstring<date-time>read-onlyprofilePinnedByUserIdstringread-onlyprogramManifestCidstringread-onlyThe requirements the agent is judged against
programSlugstringread-onlyThe program the version belongs to, which its reviewers are assigned to
programUuidstringread-onlyurn:uuid form
statusobjectread-onlyOne of
draftin_reviewpassedfailedShow properties
object (enum)· one of draft, in_review, passed, faileduuidstringread-onlyurn:uuid form
{
"agentDid": "string",
"agentName": "string",
"agentUrn": "string",
"canCertify": true,
"canEdit": true,
"canReview": true,
"configuration": {
"cid": "string",
"document": {},
"schemaVersion": "string"
},
"configurationPinnedAt": "2025-01-01T00:00:00Z",
"configurationPinnedByUserId": "string",
"createdAt": "2025-01-01T00:00:00Z",
"createdBy": "string",
"createdByDid": "string",
"createdByUserId": "string",
"draftVersion": 0,
"hasUnsubmittedChanges": true,
"latestSubmission": {
"controlCount": 0,
"draftVersion": 0,
"lastReviewedAt": "2025-01-01T00:00:00Z",
"number": 0,
"reviewedCount": 0,
"status": "in_review",
"submittedAt": "2025-01-01T00:00:00Z",
"uuid": "string"
},
"observation": {
"correlationId": "string",
"observedAt": "2025-01-01T00:00:00Z",
"request": {
"model": "string",
"provider": "string",
"systemPromptCid": "string",
"tools": [
"string"
]
},
"stateCid": "string",
"subAgent": "string",
"viperVersion": "string"
},
"organizationId": 0,
"profile": {
"cid": "string",
"document": {},
"version": 0
},
"profilePinnedAt": "2025-01-01T00:00:00Z",
"profilePinnedByUserId": "string",
"programManifestCid": "string",
"programSlug": "string",
"programUuid": "string",
"status": "draft",
"uuid": "string"
}400Bad request - Invalid request, the agent is not active or has no registry UUID, the program's controls are not registered with the Integrity Service, or the configuration or profile named can't be pinned
errorstring
{
"error": "Invalid request body"
}401Unauthorized - Authentication required
errorstring
{
"error": "Invalid request body"
}403Forbidden - No organization access, an API key with neither full access nor submit_agent_assessments, a project-bound key, or the agent registry refuses the caller
errorstring
{
"error": "Invalid request body"
}404Program, agent, or the state, configuration or profile version named, not found
errorstring
{
"error": "Invalid request body"
}500Internal server error
errorstring
{
"error": "Invalid request body"
}503The agent registry is unavailable
errorstring
{
"error": "Invalid request body"
}