Agent twin request contract 1.6¶
Previous contract. See request contract 1.7 for the current schema, including
customer_tier.
The external assessment service receives contract 1.6 when it previews or
claims an agent twin. This version adds the stored, preliminary gtm_obligations
brief alongside the submitted agent facts and metadata.
Endpoints and authentication¶
Base URL: https://app.carveragents.ai/api/v1/agent-compliance.
Send an enabled, approved super-admin API key in X-API-Key.
| Method and path | Effect |
|---|---|
GET /twin |
Preview matching twins. Does not change their state. |
POST /twin |
Claim matching twins and mark them in_progress. |
POST /twin/outputs |
Store the full assessment and return an acknowledgement. This is a separate response shape. |
GET uses query parameters; POST uses the equivalent JSON filters. Supported filters
include status, kind_type, organization_id, agent_id, twin_version_id,
created_since, updated_before, and limit. GET additionally supports offset.
The default status is pending. Incomplete twins are never offered.
Bulk-created twins in gtm_pending or gtm_failed are also excluded: they enter
the queue only after their quick brief is stored and their state becomes pending.
Posting outputs against either GTM state returns 409. GET can also
preview in_progress and completed; POST can claim pending work or reclaim
in_progress work. Use a cutoff in updated_before when reclaiming stale work.
The default limit is 50 and its maximum is 200.
export CARVER_API_KEY='YOUR_SUPER_ADMIN_API_KEY'
export CARVER_BASE='https://app.carveragents.ai/api/v1/agent-compliance'
# Read the queue without claiming work.
curl --fail-with-body --silent --show-error \
-H "X-API-Key: $CARVER_API_KEY" \
"$CARVER_BASE/twin?status=pending&kind_type=obligations&limit=10"
# Claim up to ten pending obligation assessments.
curl --fail-with-body --silent --show-error \
-X POST -H "X-API-Key: $CARVER_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"status":"pending","kind_type":"obligations","limit":10}' \
"$CARVER_BASE/twin"
Response envelope¶
Both GET and POST return:
The outer contract_version is present even for an empty queue. Every item also
carries contract_version: "1.6". GET's total counts all matching twins before
pagination. POST's total counts the twins actually claimed in that response.
Fields in each item¶
| Field | Type | Meaning |
|---|---|---|
contract_version |
string | "1.6", the version of this outbound twin request. |
metadata |
object | The linked lead's submission metadata. {} when there is no linked lead. Free-form values; preserve unknown keys. |
gtm_obligations |
object or null | The stored OpenAI quick brief, with its own schema_version: "1.0". Null is valid for older twins. |
request_id |
string or null | The mapping request identifier. Echo it when posting results. |
agent_id |
string | Agent UUID. |
twin_version |
integer | The version of this agent's description. |
twin_version_id |
string | UUID of this particular twin row. |
kind_type |
string or null | Requested artifact, normally "obligations". A worker should filter for the kind it supports. |
scope |
object or null | Normally { "name": "free" or "paid", "limits": {...} }. An empty limits object means no caps. |
created_at, updated_at |
timestamp string or null | Twin creation and latest state-update timestamps. |
input |
object | The existing submitted agent-facts shape. Includes routing fields and the description. Backend provenance and document bookkeeping are omitted. |
The routing fields agent_id, twin_version, and kind_type also remain inside
input. environment, system_context, and organization_context remain in
input. Neither top-level metadata nor gtm_obligations is injected into input.
If the submitted twin itself has an input.metadata field, it is separate from the
linked lead's top-level submission metadata.
Quick-brief structure¶
gtm_obligations has the following fields when it is not null:
| Field | Type |
|---|---|
schema_version |
"1.0" |
agent_description, lead_question, context_summary |
string |
known_facts |
array of { "text": string, "evidence_quote": string } |
findings |
array, zero to three findings in received order |
what_could_change, meeting_payoff |
string; change text may be empty |
limitations |
array of research qualification strings |
metadata |
generation provenance object, described below |
Each finding contains:
titleandtext;business_implicationandconfirmation_question;evidence_needed: an array of requested artifacts or facts;capability_evidence: a literal quote from the submitted description;fact_basis:"stated"or"conditional";inference: what remains unconfirmed; may be empty;legal_sources: one or two objects containingtitle,url,provision, andrelevance. An unavailable provision is an empty string.
The brief's nested metadata records generated_at, model, prompt_version,
prompt_sha256, input_sha256, response_id, and source_urls.
This generation metadata is distinct from the item's submission metadata.
The quick brief is preliminary research. Quoted agent facts and retrieved source
URLs are checked, but those checks do not prove legal applicability or that a
control is missing. The external system must assess the original input and
produce its own complete obligation output. Do not promote a quick-brief finding,
a metadata jurisdiction guess, or a conditional inference into a confirmed fact.
Complete item example¶
The following fictional example illustrates one pending twin. The identifiers, request ID, and hashes are placeholders; they are not production credentials.
{
"contract_version": "1.6",
"items": [
{
"contract_version": "1.6",
"metadata": {
"sender_type": "gtm",
"company_domain": "example.test",
"campaign_id": "example-campaign"
},
"gtm_obligations": {
"schema_version": "1.0",
"agent_description": "The agent drafts clinical notes from consultation audio for clinician review in California.",
"lead_question": "Who can access the consultation audio and draft notes?",
"context_summary": "Clarifying access and deployment roles can help prepare the evidence a reviewer needs.",
"known_facts": [
{
"text": "Draft notes are reviewed by a clinician.",
"evidence_quote": "for clinician review"
}
],
"findings": [
{
"title": "Access to consultation records",
"text": "Check whether the deployment handles electronic protected health information.",
"business_implication": "The answer could affect the access-control evidence needed for review.",
"confirmation_question": "Who operates the system and can access the audio and notes?",
"evidence_needed": [
"Data-flow diagram",
"Access-control configuration"
],
"capability_evidence": "drafts clinical notes from consultation audio",
"fact_basis": "conditional",
"inference": "HIPAA roles and protected-data status are not established.",
"legal_sources": [
{
"title": "HIPAA Security Rule",
"url": "https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/index.html",
"provision": "",
"relevance": "Security requirements may be relevant if the deployment handles ePHI in a covered role."
}
]
}
],
"what_could_change": "Patient communications or new jurisdictions could warrant reassessment.",
"meeting_payoff": "Clarify deployment roles and agree which access-control evidence to review.",
"limitations": [
"Preliminary AI-assisted research. Described facts and applicability need validation. Not legal advice."
],
"metadata": {
"generated_at": "2026-10-13T00:00:00+00:00",
"model": "gpt-5.4-mini",
"prompt_version": "1.0",
"prompt_sha256": "prompt-test",
"input_sha256": "input-test",
"response_id": "resp_test",
"source_urls": [
"https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/index.html"
]
}
},
"request_id": "req_2026-10-13_example",
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"twin_version": 1,
"twin_version_id": "550e8400-e29b-41d4-a716-446655440001",
"kind_type": "obligations",
"scope": {
"name": "free",
"limits": {
"max_acts": 3
}
},
"created_at": "2026-10-13T10:00:00+00:00",
"updated_at": "2026-10-13T10:00:00+00:00",
"input": {
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"twin_version": 1,
"kind_type": "obligations",
"environment": "production",
"system_context": null,
"description": "The agent drafts clinical notes from consultation audio for clinician review in California.",
"serves": [
"US-CA"
],
"organization_context": {}
}
}
],
"total": 1
}
Changes from 1.5 and consumer handling¶
Contract 1.5 added top-level submission metadata. Contract 1.6 adds the separate,
nullable gtm_obligations object and exposes contract_version on the outer queue
response as well as on each item. Existing routing fields, input, scope limits,
and claim behavior keep their meanings.
A consumer pinned to request contract 1.5 must accept "1.6" and the new fields.
Check the response version even when items is empty. Preserve the separate
versions: request contract 1.6, quick-brief schema 1.0, and the independent
full-assessment output contract produced by the external service. The backend's
integer twin-description schema version remains unchanged because input did
not change shape.
POST /twin/outputs still accepts the external full-assessment document. Echo the
routing identifiers and request ID for the claimed item. Its acknowledgement
includes the separately stored gtm_obligations and
response_schema_version: "1.2". Posting the full assessment never overwrites the
stored quick brief. Do not use the request's contract_version: "1.6" as the
external result's output version.
Related references¶
Short one-pager descriptions (brief content schema 1.1)¶
New quick briefs include agent_summary, a faithful summary capped at 160 characters,
returned in the same OpenAI response as the findings. One-pager HTML, PDF, and PNG
use this summary; agent_description and the original submitted description remain
available in the complete response. Existing schema 1.0 briefs remain readable and
use their full description until a summary is backfilled. Findings remain limited
to at most three; fewer are returned when evidence cannot support three distinct
review questions. The outer response schema stays 1.2 and /twin stays 1.6.
The admin one-pager has a Download 1 pager PDF button. It uses the authenticated
GET /api/v2/ismyagentlegal/admin/agents/{agent_id}/summary.pdf route, which renders
the same stored brief and PDF template as the integration download endpoint.
Exploratory GTM findings (brief schema 1.2, prompt 1.5)¶
Generation accepts plausible conditional review leads at model confidence estimates
as low as 25 percent. findings[].confidence_percent is an uncalibrated model
estimate of usefulness for GTM review, not a measured probability that a legal
obligation applies. Below 60 percent, findings are conditional and receive an
explicit exploratory caveat. capability_evidence may be empty for a context-based
hypothesis; it must not contain an invented quotation. Missing deployment facts
are confirmation questions rather than automatic exclusions. A lead still needs a
retrieved official legal-text citation or an explicitly approved mirror.
Research now uses medium search context, up to 12 tool calls per pass and 8,000
output tokens. A result with no retained findings receives one additional research
pass within the shared configured timeout. If both passes retain nothing,
generation reports failure instead of publishing an empty brief. Existing briefs
remain intact on failed regeneration. GTM_OBLIGATIONS_MAX_TOOL_CALLS can override
the per-pass search budget.
New content is version 1.2; older content versions 1.0/1.1 remain readable and may
omit confidence estimates. Agent response envelopes remain 1.2; /twin remains 1.6.
Exactly three findings (brief schema 1.3, prompt 1.8)¶
Every newly generated, successfully published one-pager contains exactly three findings. Both the OpenAI JSON schema and the stored-content validator enforce this count. Uncertain applicability is expressed through distinct conditional review questions, with confidence estimates as low as 25 percent and explicit caveats; confirmed legal obligations or deployment facts are not invented.
Incomplete model output, or grounding that reduces the result below three,
triggers the second research pass. If the result still lacks three findings,
generation fails and the existing stored brief is preserved rather than publishing
an incomplete replacement. Bulk worker retries remain automatic. Older content
versions 1.0–1.2 remain readable and may have fewer findings; regenerate them to
produce the new three-finding version. Response envelopes stay 1.2 and /twin
stays 1.6. No database migration is required.