Skip to main content

Overview

The HITL (Human-in-the-Loop) review API provides endpoints for reviewing, refining, and approving AI-generated research plans before execution begins. These endpoints interact with the review state stored in Redis and coordinate with the Temporal workflow via gRPC signals. For a tutorial on using the HITL review system, see Human-in-the-Loop Review.

Authentication

Required: Yes Include API key in header:
X-API-Key: sk_test_123456
Ownership is enforced: only the user who submitted the task can interact with its review.

Get Review State

GET http://localhost:8080/api/v1/tasks/{workflow_id}/review

Description

Returns the current review conversation state for a workflow. Use this to retrieve the initial research plan and track the review cycle.

Path Parameters

ParameterTypeRequiredDescription
workflow_idstringYesWorkflow ID (from task submission response)

Headers

HeaderRequiredDescription
X-API-KeyYesAPI authentication key

Response

200 OK

{
  "status": "reviewing",
  "round": 1,
  "version": 1,
  "current_plan": "Based on your query, I propose researching...",
  "rounds": [
    {
      "role": "assistant",
      "message": "Based on your query, I propose researching...",
      "timestamp": "2025-01-15T10:30:00Z"
    }
  ],
  "query": "Research the competitive landscape of AI agent frameworks"
}
Response Headers:
HeaderDescription
ETagCurrent version number (use with If-Match for concurrency control)
Response Fields:
FieldTypeDescription
statusstring"reviewing" (waiting for input) or "approved" (plan accepted)
roundintegerCurrent conversation round (starts at 1)
versionintegerMonotonic version for optimistic concurrency
current_planstringLatest actionable plan (set when LLM intent is "ready"). May be empty if LLM is still asking clarifying questions.
roundsarrayFull conversation history
rounds[].rolestring"assistant" (LLM) or "user" (human feedback)
rounds[].messagestringMessage content
rounds[].timestampstringRFC 3339 timestamp
querystringOriginal task query

401 Unauthorized

{ "error": "Unauthorized" }

403 Forbidden

{ "error": "Forbidden: not the task owner" }

404 Not Found

{ "error": "Review session not found or expired" }

Example

curl -s http://localhost:8080/api/v1/tasks/task-abc123/review \
  -H "X-API-Key: $API_KEY" | jq

Submit Feedback

POST http://localhost:8080/api/v1/tasks/{workflow_id}/review

Description

Sends feedback to refine the research plan. The gateway forwards the feedback to the LLM service, which generates an updated plan incorporating the user’s input. The conversation round and version are incremented. A distributed Redis lock prevents concurrent feedback requests from racing during the LLM call.

Path Parameters

ParameterTypeRequiredDescription
workflow_idstringYesWorkflow ID

Headers

HeaderRequiredDescription
X-API-KeyYesAPI authentication key
Content-TypeYesapplication/json
If-MatchNoVersion number for optimistic concurrency. If provided, the request is rejected with 409 if the current version does not match.

Body Parameters

ParameterTypeRequiredDescription
actionstringYesMust be "feedback"
messagestringYesFeedback text (max 10 KB)

Request Body

{
  "action": "feedback",
  "message": "Focus on open-source frameworks and include pricing comparisons"
}

Response

200 OK

{
  "status": "reviewing",
  "plan": {
    "message": "I've updated the research plan to focus on...",
    "round": 2,
    "version": 2,
    "intent": "ready"
  }
}
Response Headers:
HeaderDescription
ETagUpdated version number
Response Fields:
FieldTypeDescription
statusstringAlways "reviewing" for feedback responses
plan.messagestringUpdated plan from the LLM
plan.roundintegerCurrent round number
plan.versionintegerUpdated version (for next If-Match)
plan.intentstring"feedback" (LLM asking questions) or "ready" (actionable plan proposed)

400 Bad Request

{ "error": "message is required for feedback" }
{ "error": "message exceeds maximum length (10KB)" }
{ "error": "action must be 'feedback' or 'approve'" }

404 Not Found

{ "error": "Review session not found or expired" }

409 Conflict

Version mismatch:
{ "error": "Conflict: state has been modified" }
Another feedback request in progress:
{ "error": "Another feedback request is in progress. Please wait." }
Maximum rounds exceeded:
{ "error": "Maximum review rounds reached. Please approve the plan." }

502 Bad Gateway

LLM service unavailable:
{ "error": "Failed to generate updated plan" }

Example

curl -X POST http://localhost:8080/api/v1/tasks/task-abc123/review \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -H "If-Match: 1" \
  -d '{
    "action": "feedback",
    "message": "Include a section on pricing and add LangGraph to the comparison"
  }'

Approve Plan

POST http://localhost:8080/api/v1/tasks/{workflow_id}/review

Description

Approves the current research plan, unblocking the workflow to proceed with execution. The gateway sends a Temporal Signal to the waiting workflow, injecting the confirmed plan and review conversation into the task context.

Path Parameters

ParameterTypeRequiredDescription
workflow_idstringYesWorkflow ID

Headers

HeaderRequiredDescription
X-API-KeyYesAPI authentication key
Content-TypeYesapplication/json
If-MatchNoVersion number for optimistic concurrency

Body Parameters

ParameterTypeRequiredDescription
actionstringYesMust be "approve"

Request Body

{
  "action": "approve"
}

Response

200 OK

{
  "status": "approved",
  "message": "Research started"
}

400 Bad Request

No plan available to approve:
{ "error": "No research plan to approve. Please provide feedback to generate a plan first." }

409 Conflict

Version mismatch:
{ "error": "Conflict: plan has been updated. Please review the latest version." }
Feedback in progress:
{ "error": "A feedback request is in progress. Please wait and try again." }

502 Bad Gateway

{ "error": "Failed to approve review" }

Example

curl -X POST http://localhost:8080/api/v1/tasks/task-abc123/review \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $API_KEY" \
  -H "If-Match: 2" \
  -d '{"action": "approve"}'

Behavior Notes

  • Redis TTL: Review state is stored in Redis with a TTL equal to the review timeout plus a 5-minute buffer (default: 20 minutes). After expiry, the review session is no longer accessible.
  • Maximum rounds: 10 feedback rounds are permitted. At the final round, the LLM is instructed to produce a definitive plan. Beyond this limit, only approval is accepted.
  • Ownership: Only the user who submitted the task can access its review state (enforced via owner_user_id stored in Redis).
  • Concurrency: Both feedback and approval acquire a distributed Redis lock. If a feedback request is in progress (holding the lock), approval will fail fast with 409.
  • SSE events: The review cycle emits RESEARCH_PLAN_READY, REVIEW_USER_FEEDBACK, RESEARCH_PLAN_UPDATED, and RESEARCH_PLAN_APPROVED events to the Redis event stream. These appear in the SSE stream and are persisted for session history.
  • Token tracking: LLM token usage during review (feedback rounds) is recorded via RecordTokenUsage gRPC for accurate cost accounting.