Skip to main content

kt escalation

Use kt escalation to operate the control-plane review queue from a terminal or an automation that acts for an authenticated reviewer. The commands do not create escalations or configure reviewer routing.

Prerequisites

You need:

  • An existing escalation in the organization and region you will query.
  • KEEPTRUSTS_API_URL and KEEPTRUSTS_API_TOKEN, a configured profile, or an interactive CLI login.
  • escalations:read to list or inspect records.
  • escalations:claim to claim or unclaim records.
  • escalations:resolve to record a final decision.
  • An identity-bound user credential for claim, unclaim, and resolve. The API derives the actor from its authenticated request context; a machine credential with no user_id cannot act as a human reviewer.

Check the active identity before changing queue state:

kt auth whoami --json

For mutations, confirm that the response includes the expected organization and a non-null user_id. Run kt regions current to inspect the resolved region and API endpoint. Use --profile and --region on each command when the defaults are not the intended review boundary.

Understand the status lifecycle

StatusMeaningAvailable next action
queuedWaiting for a reviewer, including an item returned by unclaimClaim
claimedOwned by one reviewerResolve or unclaim
resolvedA final resolution is recordedRead only

open is not an escalation status accepted by the current API or CLI.

List a bounded queue

--since is required. It accepts an RFC 3339 timestamp or a relative duration ending in m, h, d, or w.

kt escalation list --since 24h
kt escalation list --since 7d --status queued --agent-id agent_abc123
kt escalation list --since 30d --status resolved --limit 100 --json

--status accepts only queued, claimed, or resolved. --limit accepts 1–100 and defaults to 25.

For pagination, use --json, copy the response's non-null next_cursor, and send it back with the same time window and filters:

kt escalation list \
--since 30d \
--status queued \
--cursor "$NEXT_CURSOR" \
--limit 100 \
--json

An empty result means that no records matched that organization, region, time window, and filter combination. It does not prove that no escalation exists in another region or outside the selected window.

Inspect one escalation

Start with the record itself:

kt escalation get --escalation-id esc_abc123
kt escalation get --escalation-id esc_abc123 --json

Review at least the request ID, reason code, status, configuration version, creation time, and current claimant. Ask the API for linked event context when you need to understand why the request entered review:

kt escalation get \
--escalation-id esc_abc123 \
--include-context \
--json

Context can be absent or redacted because of the original capture settings and data availability. Treat the returned escalation and governance Events as the authoritative queue evidence; do not infer a clean request merely from missing content.

Claim work

Claim only when you are ready to review the item:

kt escalation claim --escalation-id esc_abc123
kt escalation get --escalation-id esc_abc123 --json

The API attributes the mutation to the authenticated user_id. The CLI does not accept or send a caller-selected actor identity. Claiming is idempotent for that authenticated reviewer. The API returns a conflict if a different reviewer already owns the item or the item is already resolved.

Return work to the queue

Unclaim a record when you should no longer own it:

kt escalation unclaim --escalation-id esc_abc123
kt escalation get --escalation-id esc_abc123 --json

A successful unclaim changes claimed back to queued and clears the claimant and claim time. The claimant can release their own record; users with assignment management authority can release another reviewer's claim. An unclaimed or resolved item returns a conflict instead of being silently changed.

Resolve a claimed escalation

Only the actor who currently owns the claim can resolve it. Choose one supported resolution:

ResolutionUse when
allowRecord the reviewer disposition as allowed
blockRecord the reviewer disposition as blocked
rewriteRecord that a rewrite is required
redactRecord that redaction is required
rejectedRecord that the escalation is rejected

Resolving updates the review record. It does not replay or change the already handled gateway request.

Record the decision:

kt escalation resolve \
--escalation-id esc_abc123 \
--resolution allow \
--category false_positive \
--note "Reviewed against the active policy"

--note is optional and may contain at most 2,000 bytes. --category is optional and accepts:

  • false_positive
  • true_positive_approved
  • true_positive_blocked
  • needs_policy_update
  • needs_rewrite
  • duplicate
  • other

Resolution and category are separate fields. For example, block describes the final action, while true_positive_blocked classifies why that action was appropriate.

Read the record back before treating the workflow as complete:

kt escalation get --escalation-id esc_abc123 --json

Verify status: resolved, the selected resolution, and any note or category you supplied.

Troubleshoot safely

  • Missing API token: run kt auth login or provide KEEPTRUSTS_API_TOKEN; then verify with kt auth whoami --json.
  • No user_id in whoami or 403 auth.user_required: use an identity-bound user credential. A caller-chosen actor ID cannot substitute for authenticated user identity.
  • Permission denied: request only the permission required for the operation: escalations:read, escalations:claim, or escalations:resolve.
  • Validation error while listing: provide --since, use a supported status, and keep --limit between 1 and 100.
  • Validation error while resolving: use a supported resolution and category, and keep the note within the size limit.
  • Conflict: another reviewer changed the item, it is not claimed, or it is already resolved. Fetch the escalation again and decide from its current state; do not blindly retry a mutation.
  • Unexpected empty queue or not found: verify the organization, profile, region, time window, agent filter, and escalation ID.

For automation, use --json, preserve the same filters across cursor pages, and treat claim conflicts as concurrency signals that require a fresh read.

Next steps