EQTY LabDocs

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

posthttps://localhost:10001/api/v1/organizations/{orgId}/assessments
bash
curl --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"}'
javascript
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();
typescript
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();
python
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())
go
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))
}
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"))
            .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());
    }
}
csharp
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
<?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;
ruby
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}"
rust
// 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

NameTypeDescription
orgId
required
string

Organization ID or UUID (urn:uuid optional)

Request bodyrequired

Program version and agent to assess

application/json
  • agentIdstringrequired

    The agent's ID in the agent registry

  • configurationobject

    The configuration to pin as it starts, as the configuration pin route takes it; {} pins the latest state. Nothing is pinned when omitted

    Show properties
    • configurationCidstring

      A 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

    • stateCidstring

      A state from the agent's history; the latest when omitted

  • profileCidstring

    A version of the agent's operating profile to pin as it starts, bare or urn:cid; none when omitted

  • programIdstringrequired

    Program UUID (urn:uuid optional), slug:<slug>@<version>, or urn:cid:<manifest cid>

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

application/json
  • agentDidstringread-only

    The agent key that signed the pinned state; absent until a configuration is pinned

  • agentNamestringread-only

    The 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-only

    The agent's control-plane registry ID, whose UUID is the root of the assessment's integrity graph

  • canCertifybooleanread-only

    Whether 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-only

    Whether the caller may change and submit the draft: they started the assessment

  • canReviewbooleanread-only

    Whether the caller may review its submissions: they review its program and did not start it

  • configurationobjectread-only

    Pinned to the draft; a submission keeps its own copy, which a later pin does not change

    Show properties
    • cidstring

      urn:cid of Document, registered with the Integrity Service

    • documentobject

      The 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-only
  • configurationPinnedByUserIdstringread-only
  • createdAtstring<date-time>read-only
  • createdBystringread-only
  • createdByDidstringread-only
  • createdByUserIdstringread-only

    Who started it, the only member who may change its draft; absent on assessments started before it was recorded

  • draftVersionintegerread-only

    Increases with every change to the draft; submitting with it freezes exactly the draft the caller saw

  • hasUnsubmittedChangesbooleanread-only

    The draft changed since its newest submission, or was never submitted

  • latestSubmissionobjectread-only

    Absent until the first submission

    Show properties
    • controlCountinteger

      The program's controls, each of which is reviewed

    • draftVersioninteger

      The draft version it froze

    • lastReviewedAtstring<date-time>
    • numberinteger
    • reviewedCountinteger

      Controls with at least one review

    • statusobject

      One ofin_reviewpassedfailed

      Show properties

      object (enum) · one of in_review, passed, failed

    • submittedAtstring<date-time>
    • uuidstring

      urn:uuid form

  • observationobjectread-only
    Show properties
    • 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

  • organizationIdintegerread-only
  • profileobjectread-only

    Pinned to the draft, optionally; a submission keeps its own copy, which a later pin does not change

    Show properties
    • cidstring

      urn:cid of Document, registered with the Integrity Service

    • documentobject

      The AgentOperatingProfileV1 document, as the agent registry stores it. cid is over its JCS (RFC 8785) form

    • versioninteger

      The agent's version number of it, as the agent registry numbers them

  • profilePinnedAtstring<date-time>read-only
  • profilePinnedByUserIdstringread-only
  • programManifestCidstringread-only

    The requirements the agent is judged against

  • programSlugstringread-only

    The program the version belongs to, which its reviewers are assigned to

  • programUuidstringread-only

    urn:uuid form

  • statusobjectread-only

    One ofdraftin_reviewpassedfailed

    Show properties

    object (enum) · one of draft, in_review, passed, failed

  • uuidstringread-only

    urn:uuid form

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

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

401Unauthorized - Authentication required

application/json
  • errorstring
Examplejson
{
  "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

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

404Program, agent, or the state, configuration or profile version named, not found

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

500Internal server error

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

503The agent registry is unavailable

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