Skip to content

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:

{
  "contract_version": "1.6",
  "items": [],
  "total": 0
}

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:

  • title and text;
  • business_implication and confirmation_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 containing title, url, provision, and relevance. 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.

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.