← Docs
🧭Agent ConfessionPOST /v1/confessions

Agent Confessions

A secure steering loop: an uncertain cloud agent reports its concerns, a human gives guidance, and the agent resumes safely.

What it does

Confessions let an agent ask a human to choose a direction when it lacks enough confidence to proceed. Creation persists the item, returns a one-time review URL, and asynchronously queues email notification. A reviewer approves or rejects it; the agent polls or receives a signed confession.resolved callback to resume.

Endpoint

Method: POST

Path: POST /v1/confessions

Auth: x-agent-id + x-api-key (creation and polling); x-admin-key, X-Approval-Key, or a short-lived review token (resolution)

Request shape

  • title: string — the decision or uncertainty that needs human review (required, max 256 characters)
  • summary?: string — optional concise context for the reviewer (max 4096 characters)
  • context?: JSON — private supporting context, maximum 50 KB
  • urgency?: normal | high | blocking; reviewer_email?: string
  • callback_url: HTTPS URL (required); callback_payload?: JSON up to 100 KB
  • expires_in_seconds?: integer (300–604800; defaults to 24 hours)

Example requests

Copy-pasteable examples for agents and automation.

cURL

curl -X POST https://www.agent-utils.com/v1/confessions \
  -H "x-agent-id: worker" -H "x-api-key: agutil_agt_…" \
  -H "content-type: application/json" \
  -d '{
    "title":"Which migration should we ship?",
    "summary":"Both schemas are active; I need a reviewer decision.",
    "urgency":"high",
    "callback_url":"https://your-app.example/confessions/resolved"
  }'

Python

import requests

resp = requests.post(
    "https://www.agent-utils.com/v1/confessions",
    headers={"x-agent-id": "worker", "x-api-key": "agutil_agt_…"},
    json={
        "title": "Which migration should we ship?",
        "summary": "Both schemas are active; I need a reviewer decision.",
        "urgency": "high",
        "callback_url": "https://your-app.example/confessions/resolved",
    },
)
review_url = resp.json()["data"]["review_url"]

JavaScript

const res = await fetch("https://www.agent-utils.com/v1/confessions", {
  method: "POST",
  headers: { "x-agent-id": "worker", "x-api-key": "agutil_agt_…", "content-type": "application/json" },
  body: JSON.stringify({
    title: "Which migration should we ship?",
    summary: "Both schemas are active; I need a reviewer decision.",
    urgency: "high",
    callback_url: "https://your-app.example/confessions/resolved",
  }),
});
const { data } = await res.json();
console.log(data.review_url);

How agents use it

Create a Confession with a title, optional summary/context, urgency, required callback URL, and optional reviewer email.
Use the returned one-time review_url or tenant email notification to bring an authorized reviewer to /c/{id}.
Poll GET /v1/confessions/{id}, or verify the signed confession.resolved callback, then resume according to the approved or rejected decision.

When to use it

  • The agent finds competing valid approaches and needs a human to choose the business or technical direction.
  • Proceeding with a guess could be costly, unsafe, or difficult to reverse.
  • A long-running cloud agent needs help without losing its current context or workflow state.

When not to use it

  • You only need approval or rejection for one proposed, well-defined action; use a checkpoint instead.
  • The task has already failed and needs retry or inspection; use the dead letter queue instead.
  • The agent can safely apply a deterministic fallback without human input.

Failure modes

  • An agent key can create, list, poll, and cancel only its own tenant’s Confessions; it cannot resolve one.
  • Resolution is terminal. A second resolution returns a conflict, so consumers must handle the callback idempotently.
  • An expired unanswered Confession is marked expired; pending notification work is cancelled and callback delivery failure is recoverable through the DLQ.
  • Email notification is asynchronous and non-blocking. If no reviewer email is configured, creation still succeeds and the agent can distribute review_url itself.

Machine-readable summary

This JSON block is stable for crawlers, agents, and downstream documentation pipelines.

{
  "slug": "confession",
  "title": "Agent Confessions",
  "canonical": "/docs/confessions",
  "endpoint": "POST /v1/confessions",
  "method": "POST",
  "auth": "x-agent-id + x-api-key (creation and polling); x-admin-key, X-Approval-Key, or a short-lived review token (resolution)",
  "machine_readable": true,
  "request_shape": [
    "title: string — the decision or uncertainty that needs human review (required, max 256 characters)",
    "summary?: string — optional concise context for the reviewer (max 4096 characters)",
    "context?: JSON — private supporting context, maximum 50 KB",
    "urgency?: normal | high | blocking; reviewer_email?: string",
    "callback_url: HTTPS URL (required); callback_payload?: JSON up to 100 KB",
    "expires_in_seconds?: integer (300–604800; defaults to 24 hours)"
  ],
  "agent_workflows": [
    "Create a Confession with a title, optional summary/context, urgency, required callback URL, and optional reviewer email.",
    "Use the returned one-time review_url or tenant email notification to bring an authorized reviewer to /c/{id}.",
    "Poll GET /v1/confessions/{id}, or verify the signed confession.resolved callback, then resume according to the approved or rejected decision."
  ],
  "failure_modes": [
    "An agent key can create, list, poll, and cancel only its own tenant’s Confessions; it cannot resolve one.",
    "Resolution is terminal. A second resolution returns a conflict, so consumers must handle the callback idempotently.",
    "An expired unanswered Confession is marked expired; pending notification work is cancelled and callback delivery failure is recoverable through the DLQ.",
    "Email notification is asynchronous and non-blocking. If no reviewer email is configured, creation still succeeds and the agent can distribute review_url itself."
  ]
}

Related docs