Human-in-the-loop
Lantern has two mechanisms for inserting humans into agent workflows: approval nodes (structured workflow gates) and the confidence gate (automatic diversion of low-confidence steps). Both use the same takeover API to record the human decision and resume the workflow.
Approval workflow nodes
In the visual workflow editor, an approval node pauses execution until a human acts. Under the hood this uses park-without-compute: the run transitions to status: 'waiting', the goroutine is released (no compute cost while waiting), and a takeover_requests row is created. The request expires after 30 minutes if no action is taken.
Takeover API
# Create a pending takeover row (done by the workflow node automatically,
# or manually by an operator)
POST /v1/runs/{id}/takeover/request
{ "reason": "About to send email to 500 users" }
→ { "id": "tk-uuid", "status": "pending", "expiresAt": "..." }
# List takeover requests for a run
GET /v1/runs/{id}/takeover
→ [{ "id": "tk-uuid", "status": "pending", "reason": "...", "expiresAt": "..." }]
# Operator approves (optionally including an SDP offer for WebRTC takeover)
POST /v1/runs/{id}/takeover/{tkId}/grant
{ "sdpOffer": "v=0
..." } # optional
# Browser-side SDP answer (for live WebRTC session)
POST /v1/runs/{id}/takeover/{tkId}/answer
{ "sdpAnswer": "v=0
..." }
# Release — workflow resumes from the approval node
POST /v1/runs/{id}/takeover/{tkId}/release
→ run transitions back to "running", goroutine resumeswaiting status the goroutine is parked — no CPU or memory is consumed. This means long approval waits (hours or days) cost nothing. The workflow resumes from the exact node it paused at.Confidence gate
Enable the confidence gate with LANTERN_CONFIDENCE_GATE=1. Before a side-effecting node executes, the interpreter evaluates a confidence score. If the score falls below the threshold (LANTERN_CONFIDENCE_GATE_THRESHOLD, default 0.75), the step is diverted to human approval instead of auto-executing.
Gated node types
toolandconnector— always gated when the feature is onai-step— only gated whennode.Data["requiresConfidence"] = true
Estimators
Select the estimator with LANTERN_CONFIDENCE_ESTIMATOR:
| Estimator | How it scores | Failure mode |
|---|---|---|
verbalization_heuristic (default) | Scans prior step text for self-reported confidence ("Confidence: 85%"). Falls back to 0.9 when none found. | Silence → 0.9 → auto-execute. A model that hallucinates an action also writes "confidence: 95%". |
self_consistency | Re-poses the pending action to the model LANTERN_CONFIDENCE_SAMPLES times (default 5) as a fresh YES/NO judgment. Returns the fraction voting "execute". Consensus → high; split vote → low → divert. | Safer: silence is actively probed. Falls back to verbalization heuristic when no LLM sampler is wired. |
Outcome calibration
Enable with LANTERN_CONFIDENCE_CALIBRATE=1. Wraps the base estimator and lowers its score by the realized regret rate — the fraction of auto-executed steps of that type later thumbs-downed (feedback score ≤ 2) or ending in a failed run: adjusted = base × (1 − regret). Action types that have burned the owner get gated harder over time. Fail-safe: any error or fewer than 3 samples → regret 0 → base unchanged.
Journal events
Every gated step emits a confidence_evaluated journal event with { score, threshold, decision ("execute" | "divert"), node_type, estimator }. Diverted steps emit step_completed after approval or step_failed after denial.
Env vars
| Variable | Default | Purpose |
|---|---|---|
LANTERN_CONFIDENCE_GATE | off | 1/true/on enables gating |
LANTERN_CONFIDENCE_GATE_THRESHOLD | 0.75 | Minimum score [0,1] for auto-execution |
LANTERN_CONFIDENCE_ESTIMATOR | verbalization | self-consistency to poll for independent agreement |
LANTERN_CONFIDENCE_SAMPLES | 5 | Independent judgments for self-consistency (clamped [1,9]) |
LANTERN_CONFIDENCE_CALIBRATE | off | 1 wraps the estimator in outcome-regret calibration |
confidence_evaluated events in the run waterfall. Switch to self-consistency and tune threshold / samples. Then production.