Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.swarmd.ai/llms.txt

Use this file to discover all available pages before exploring further.

Human-in-the-Loop (HITL)

Human-in-the-loop lets you pause agent communication and require manual approval before a message is forwarded. This is critical for high-stakes operations where you need a human to verify what an agent is about to do.

How HITL Gets Triggered

There are two distinct ways a message can be held for human review:
SourceHow it happensTypical use case
Policy escalationA detection policy with action HUMAN_REVIEW_REQUIRED matches the messageCompliance rules, PII detection, restricted operations
Agent-initiatedThe downstream agent returns task status INPUT_REQUIREDAgent is uncertain, needs clarification, or is designed to ask for confirmation
These are fundamentally different flows. Policy escalation is triggered by a detection policy (regex, Presidio, Comprehend) at the relay level — before or after the message reaches the agent, depending on which leg matched. Agent-initiated INPUT_REQUIRED happens when the agent has processed the message and decided it needs human input. Both are automatically intercepted by the relay’s built-in HITL middleware.

Setting Up Policy-Based HITL

To escalate messages for human review, set the action to HUMAN_REVIEW_REQUIRED on any detection policy (regex, Presidio, or Comprehend). There is no separate “HITL policy type” — human review is an action you configure on your existing detection policies.
curl -X POST https://api.swarmd.ai/relay/v1/policies \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $SWARMD_TOKEN" \
  -d '{
    "name": "Review Messages with SSNs",
    "description": "Escalate to human review when SSNs are detected",
    "config": {
      "type": "PRESIDIO_DETECTION",
      "enabledLegs": {
        "requestFromSource": true,
        "requestToSink": true,
        "responseFromSink": true,
        "responseToSource": true
      },
      "entity": {
        "type": "US_SSN",
        "scoreThreshold": 0.7,
        "action": "HUMAN_REVIEW_REQUIRED"
      }
    }
  }'
After creating your policy, remember to add it to a policy group and bind that group to a tenant, agent, or subscription. See the Policy Configuration tutorial for the full flow.

Reviewing Approvals

When a message is held for review, it appears as a pending approval.

List Pending Approvals

curl "https://api.swarmd.ai/relay/v1/approvals?status=PENDING" \
  -H "Authorization: Bearer $SWARMD_TOKEN"
Response:
[
  {
    "id": "a1b2c3d4-...",
    "taskId": "task-5678",
    "agentMessageRole": "user",
    "agentMessageText": "Please process this SSN: 123-45-6789",
    "detectionSource": "POLICY_ESCALATION",
    "sourceAgentId": "...",
    "sinkAgentId": "...",
    "policyName": "Review Messages with SSNs",
    "matchedContent": "123-45-6789",
    "createdAt": "2025-03-10T14:30:00",
    "resolution": null
  }
]
To see all approvals (including resolved ones):
curl "https://api.swarmd.ai/relay/v1/approvals?status=ALL" \
  -H "Authorization: Bearer $SWARMD_TOKEN"

Get a Specific Approval

curl https://api.swarmd.ai/relay/v1/approvals/APPROVAL_ID \
  -H "Authorization: Bearer $SWARMD_TOKEN"

Key Fields in an Approval

FieldDescription
detectionSourcePOLICY_ESCALATION (from a policy) or AGENT_INPUT_REQUIRED (from the agent)
agentMessageTextThe message content that triggered the review
matchedContentThe specific content that matched the policy (if policy-triggered)
policyNameThe name of the policy that triggered escalation (if policy-triggered)
sourceAgentId / sourceUserIdWho sent the message
sinkAgentIdThe target agent
resolutionnull if pending, otherwise contains the resolution details

Resolving Approvals

Approve

Approving a request allows the message to continue through the relay to the target agent.
curl -X POST https://api.swarmd.ai/relay/v1/approvals/APPROVAL_ID/resolve \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $SWARMD_TOKEN" \
  -d '{
    "action": "APPROVED",
    "message": "Verified — this is a test SSN for the demo environment"
  }'
What happens next:
  • The held message is forwarded to the target agent
  • The task resumes from where it was paused — callers polling tasks/get will see completed state with the full agent response
  • The relay_reason metadata is no longer present in the resolved response
  • The approval, resolution, and reviewer are recorded in the audit log

Reject

Rejecting a request stops the message from being forwarded. The task is cancelled.
curl -X POST https://api.swarmd.ai/relay/v1/approvals/APPROVAL_ID/resolve \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $SWARMD_TOKEN" \
  -d '{
    "action": "REJECTED",
    "message": "Contains real PII — must not be sent to external agent"
  }'
What happens next:
  • The message is not forwarded
  • The associated task is cancelled — callers polling tasks/get will see canceled state with relay_reason: "HITL_REJECTED" in the metadata (including policy_name, policy_version, and policy_level if the hold was policy-triggered)
  • The rejection reason is recorded in the audit log

Policy Escalation vs Agent INPUT_REQUIRED

It’s important to understand the difference between these two flows:
Policy EscalationAgent INPUT_REQUIRED
Triggered byA detection policy with HUMAN_REVIEW_REQUIRED actionDownstream agent returning INPUT_REQUIRED task status
WhenDuring relay policy evaluation (on the matching leg)After the agent has processed the message
Detection sourcePOLICY_ESCALATIONAGENT_INPUT_REQUIRED
Approval fieldspolicyName and matchedContent populatedpolicyName and matchedContent are null
Use caseCompliance, safety guardrailsAgent needs clarification or confirmation
On approveCalls resumeTask() — the original held message is forwarded to the target agentCalls resumeTask() — a confirmation response is sent to the agent
When an agent returns INPUT_REQUIRED, the agent has already seen the message and is asking for more input. The relay’s built-in HITL middleware automatically intercepts this and creates an approval request — you don’t need to configure a policy for this path. It happens by default.

Response Metadata — relay_reason

When the relay masks a response due to HITL (or a timeout), it sets a relay_reason field in the response metadata. This tells API consumers why the relay has taken ownership of the task. The response metadata is a strongly-typed discriminated union — the shape of the metadata depends on the relay_reason value.
relay_reasonstatus.stateMeaningAdditional fields
TIMEOUTworkingAgent didn’t respond within the early-return timeout window(none)
HITL_HELDworkingHeld for human review by a detection policypolicy_name, policy_version, policy_level
HITL_HELD_AGENT_INPUT_REQUIREDworkingAgent explicitly requested human input (no policy involved)(none)
HITL_REJECTEDcanceledHuman reviewer rejected the HITL requestpolicy_name, policy_version, policy_level (nullable)
Policy fields (policy_name, policy_version, policy_level) are included for HITL_HELD and HITL_REJECTED to give consumers context about which policy triggered the hold. These fields are nullable on HITL_REJECTED — they will be null if the original hold was agent-initiated rather than policy-triggered. policy_level indicates the scope at which the policy is bound: TENANT, AGENT, or SUBSCRIPTION. Example metadata for a policy-held response:
{
  "relay_reason": "HITL_HELD",
  "policy_name": "Review Messages with SSNs",
  "policy_version": "1.0.0",
  "policy_level": "TENANT"
}
Example metadata for an agent-initiated hold:
{
  "relay_reason": "HITL_HELD_AGENT_INPUT_REQUIRED"
}
For full frontend integration details — including how to route UI behavior based on relay_reason, polling patterns, and decision flowcharts — see the Frontend Integration tutorial.

Auditing HITL Decisions

Every HITL event is recorded in the audit log with specific audit types:
Audit TypeDescription
HITLHITL detection occurred (policy escalation or agent input-required)
HITL_GUARDThe message was held and the task is guarded pending review
HITL_RESOLUTIONThe approval was resolved (approved or rejected)
Query HITL-related events:
curl "https://api.swarmd.ai/audit/v1/events?auditType=HITL_RESOLUTION&page=0&size=10" \
  -H "Authorization: Bearer $SWARMD_TOKEN"
To see the complete flow — trigger, hold, and resolution — use the trace endpoint with the correlationId from the approval:
curl https://api.swarmd.ai/audit/v1/traces/CORRELATION_ID \
  -H "Authorization: Bearer $SWARMD_TOKEN"

Required Permissions

To manage HITL approvals, users need the following permissions (granted through group membership):
ActionRequired Permission
List / view approvalsAGENT_CONVERSATIONS:READ
Approve or rejectAGENT_CONVERSATIONS:WRITE
The default Editor group includes both of these permissions. See the User Management tutorial for how to manage groups and permissions.

Next Steps

Frontend Integration

Handle HITL responses in your frontend for both channel and user access.

Monitoring & Audit

Track all agent activity and HITL decisions in the audit log.