Pin an assessment's operating profile
Pin a version of the agent's operating profile to an assessment's draft: the one whose CID is given, or the agent's current profile when cid is omitted. It is read from the agent registry with the caller's token, so it must be one the assessed agent holds; browse them with the registry's profile/versions. A profile is optional. Pinned, it stands for the profile sections each control judges: a control that expects no evidence and judges only profile sections and captured configuration fields needs no declaration, and each control's evidence holds the values of the sections it judges. At submission the registry checks it against what the agent was seen with, and the submission keeps the check for reviewers. It may be pinned again or unpinned at any time; a submission keeps the profile it froze, and the next draft differs from it. Only the member who started the assessment may pin; an integration's API key bound to no project acts as its owner with full access or the submit_agent_assessments scope
https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/profilecurl --request PUT \
--url 'https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/profile' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{"cid":"urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"}'const response = await fetch("https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/profile", {
method: "PUT",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"
})
});
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/{assessmentId}/profile", {
method: "PUT",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"
})
});
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
const data: Assessment = await response.json();import requests
response = requests.put(
"https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/profile",
headers={
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
},
json={
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw",
},
)
response.raise_for_status()
print(response.json())package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"
}`)
req, err := http.NewRequest(http.MethodPut, "https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/profile", 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/{assessmentId}/profile"))
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString("""
{
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"
}
"""))
.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.Put, "https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/profile");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "<token>");
request.Content = new StringContent("""
{
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"
}
""", 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/{assessmentId}/profile');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer <token>',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"
}
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/{assessmentId}/profile")
request = Net::HTTP::Put.new(uri)
request["Authorization"] = "Bearer <token>"
request["Content-Type"] = "application/json"
request.body = <<~'JSON'
{
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"
}
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()
.put("https://localhost:10001/api/v1/organizations/{orgId}/assessments/{assessmentId}/profile")
.header("Authorization", "Bearer <token>")
.json(&json!({
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"
}))
.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) |
Request body
The profile version to pin
cidstringOne of the agent's profile versions, bare or urn:cid; its current profile when omitted
{
"cid": "urn:cid:baga6yaq6eb6jml6fjkop55ltrmueohlwstzxdwxvqcyjtqa7j3j3nei5jituw"
}Responses
200Assessment with its pinned operating profile
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, or the agent has no such profile
errorstring
{
"error": "Invalid request body"
}401Unauthorized - Authentication required
errorstring
{
"error": "Invalid request body"
}403Forbidden - Not the assessment's starter, 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"
}404Assessment or agent 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"
}