Core API

Audit records and cases for autonomous agent actions

Use Contro1 audit records to log actions that agents are authorized to run autonomously, and correlation_id to connect requests and logs into one case timeline.

Create requests when a human must decide. Create audit records when the agent already acted within policy. Use correlation_id to keep the whole story together in one case.

Key takeaways

  • createProtocolRequest asks a human; logAction records an autonomous action.
  • Audit records use the same API key and base URL as requests.
  • correlation_id groups requests and audit records into one case timeline - Contro1 infers the case from this field automatically.
  • in_reply_to lets an agent attach a follow-up inside an existing case after an operator decision.
  • For US AI governance readiness, cases connect high-impact review, human decisions, callbacks, and audit-only evidence into one explainable timeline.

Two verbs, one API

Use the request API when the agent needs a human before it proceeds. Use audit records when the agent already has authority to act and Contro1 should retain a searchable, immutable record.

Both flows use the same base URL, API key, SDK client, and organization scope. The audit endpoint is shown below as a copyable code block.

audit.ts
await client.logAction({
  action: 'transfer.executed',
  summary: 'Transferred $500 to the approved vendor account.',
  source: { integration: 'finance-agent', workflow_id: 'vendor-payment' },
  outcome: 'success',
  correlation_id: caseId,
  in_reply_to: { type: 'request', id: request.id },
});
request.ts
const caseId = crypto.randomUUID(); // or derive from your business context

const request = await client.createProtocolRequest({
  title: 'Approve $500 vendor transfer?',
  request_type: 'approval',
  source: { integration: 'finance-agent', workflow_id: 'vendor-payment' },
  continuation: { mode: 'decision', webhook_url: 'https://agent.example.com/webhook' },
  correlation_id: caseId,
});

Audit record payload

Send audit records with the same Bearer API key used for requests.

Only action, summary, and source.integration are required. Add actor, resource, outcome, tags, and metadata when they help future investigation.

audit_endpoint.sh
curl -X POST https://api.contro1.com/api/centcom/v1/audit-records \
  -H "Authorization: Bearer $CENTCOM_API_KEY" \
  -H "Content-Type: application/json"
audit-record.json
{
  "action": "invoice.refund_issued",
  "summary": "Refunded $42 to customer c-8821 within support policy.",
  "source": { "integration": "support-agent", "workflow_id": "refund-flow", "run_id": "run_9x2" },
  "actor": { "agent_id": "support-agent-1", "agent_name": "Support Agent" },
  "resource": { "type": "customer", "id": "c-8821" },
  "outcome": "success",
  "severity": "info",
  "tags": ["refund", "policy"],
  "correlation_id": "case-refund-8821",
  "in_reply_to": { "type": "request", "id": "665f..." }
}

Cases: one conversation timeline

A case is the full conversation timeline between an agent and humans around one topic: the agent asks, a human answers, the agent may ask a follow-up question, and the agent can later log what it did.

Use the same correlation_id for every request and audit record in that topic. In the dashboard, this appears as one case timeline. Use in_reply_to when the new item is directly replying to a previous request or audit record.

in_reply_to must reference an item in the same organization. If you send both correlation_id and in_reply_to, the in_reply_to item must belong to the same case or the API returns 400.

For NIST AI RMF or OMB-style governance evidence, a case can represent one high-impact action, incident, or AI use case review. Contro1 keeps the operational evidence; your governance system still owns classification, impact assessment, and legal records.

  • correlation_id groups the whole case.
  • in_reply_to points to the specific prior item this one answers.
  • in_reply_to cannot point to another organization and cannot conflict with the case.
  • external_request_id is still per request/action for idempotency.
first_request.ts
const caseId = 'refund-flow:run_9x2'; // stable per business event

const approval = await client.createProtocolRequest({
  title: 'Approve refund for customer c-8821?',
  request_type: 'approval',
  source: { integration: 'support-agent', workflow_id: 'refund-flow', run_id: 'run_9x2' },
  continuation: { mode: 'decision', webhook_url: 'https://agent.example.com/webhook' },
  external_request_id: 'refund-flow:run_9x2:approve-refund',
  correlation_id: caseId,
});
follow_up_request.ts
const followUp = await client.createProtocolRequest({
  title: 'Operator approved. Should the agent also send the customer email?',
  request_type: 'decision',
  source: { integration: 'support-agent', workflow_id: 'refund-flow', run_id: 'run_9x2' },
  continuation: { mode: 'decision', webhook_url: 'https://agent.example.com/webhook' },
  external_request_id: 'refund-flow:run_9x2:send-email-decision',
  correlation_id: caseId,
  in_reply_to: { type: 'request', id: approval.id },
});
final_audit.ts
await client.logAction({
  action: 'refund.completed',
  summary: 'Refunded customer c-8821 and sent the approved follow-up email.',
  source: { integration: 'support-agent', workflow_id: 'refund-flow', run_id: 'run_9x2' },
  outcome: 'success',
  correlation_id: caseId,
  in_reply_to: { type: 'request', id: followUp.id },
});

Framework connector guidance

Connectors derive one stable correlation_id per native framework run or session, then pass it through every related request and audit record.

  • LangGraph maps config.configurable.thread_id (LangGraph's own state key) to Contro1 correlation_id automatically.
  • OpenAI Agents uses f"openai-{run_id}" as correlation_id and call_id as external_request_id.
  • CrewAI passes execution_id directly as correlation_id and task_id as external_request_id.
  • n8n uses {{$execution.id}} as correlation_id directly in the request body.
  • Claude managed agents use session_id as correlation_id and the blocking event_id as the per-action idempotency key.

Read APIs

  • GET /api/centcom/v1/audit-records lists audit records with filters for action, actor, source integration, tags, outcome, severity, correlation_id, and time range.
  • GET /api/centcom/v1/audit-records/{id} returns one record.
  • GET /api/centcom/v1/cases/{case_id} returns a mixed chronological timeline of requests and audit records for a case.

Frequently asked questions

Is logAction another approval request?

No. logAction never routes to an operator or blocks the agent. It records an action the agent was already authorized to perform.

Should every request have a correlation_id?

No. Standalone requests can stay flat. Use correlation_id only when multiple items belong to the same business case or incident.

Can an audit record reply to a request?

Yes. Set in_reply_to to { type: "request", id: request_id }. The server links it to the case and the dashboard shows both items together.