Human-in-the-loop safety controls — approval routing via human, LLM judge, or auto-approve with guardrail overrides.
You have access to AgentOS human-in-the-loop (HITL) safety controls. These gate dangerous or irreversible actions behind an approval step — either a human operator, an LLM judge, or a policy-based auto-decision — before execution proceeds.
Request approval before any action that is:
If the agent's security tier is paranoid, every tool invocation goes through HITL. At strict, destructive and external actions require approval. At balanced and below, HITL is opt-in per tool or workflow.
Import handlers from the top-level namespace:
import { hitl } from '@framers/agentos';
Always approves. Use only in development, testing, or when the security tier is permissive/dangerous and you trust all tool inputs.
Always denies with an optional reason string. Useful for locking down specific tools entirely.
Prompts the human operator in the terminal for a yes/no decision. Default handler when running wunderland chat interactively.
POSTs the approval request to an external URL and waits for a JSON response with { approved: boolean, reason?: string }. Use for custom dashboards or external approval systems.
Sends an approval request to a Slack channel and waits for a reaction or thread reply. In v1, defaults to auto-approve after notification.
Routes the approval decision through an LLM. The judge evaluates the pending action against the provided criteria string and returns approve/reject with a confidence score. When the confidence is below confidenceThreshold (default 0.7), the judge falls back to fallback (default: auto-reject).
Usage in agency():
agency({
hitl: {
handler: hitl.llmJudge({
model: 'gpt-4o-mini',
criteria: 'Is this action safe and relevant to the user request?',
confidenceThreshold: 0.7,
}),
},
});
Usage in CLI:
wunderland chat --llm-judge
Usage in agent.config.json:
{
"hitl": {
"mode": "llm-judge"
}
}
When guardrailOverride is true (the default), guardrails run after HITL approval and can veto actions that passed the approval gate. This provides defense-in-depth: even if a human or LLM judge approves an action, built-in safety checks still apply.
Built-in post-approval guardrail checks:
rm -rf /, DROP TABLE, FORMAT C:)Even auto-approved actions (via hitl.autoApprove()) are checked when guardrailOverride is enabled.
Disable guardrail overrides:
// In API
agency({ hitl: { guardrailOverride: false } });
# In CLI
wunderland chat --no-guardrail-override
// In agent.config.json
{ "hitl": { "guardrailOverride": false } }
When building agent graphs with AgentOS orchestration, use humanNode() to insert approval gates:
import { humanNode } from '@framers/agentos/orchestration';
humanNode({
prompt: 'Deploy to production?',
timeout: 300000, // 5 minutes
onTimeout: 'reject', // what happens when timeout expires
});
| Option | Type | Description |
|---|---|---|
prompt | string | The question shown to the approver |
autoAccept | boolean | Skip human, always approve |
autoReject | boolean | Always deny (with optional reason) |
judge | { model, criteria, confidenceThreshold } | Delegate decision to an LLM judge |
onTimeout | 'accept' | 'reject' | 'error' | Behavior when timeout expires |
timeout | number | Milliseconds before onTimeout fires |
LLM judge in a graph node:
humanNode({
prompt: 'Deploy to production?',
judge: {
model: 'gpt-4o-mini',
criteria: 'Is this deployment safe given the current test results?',
confidenceThreshold: 0.8,
},
onTimeout: 'reject',
timeout: 300000,
});
The full execution path for any HITL-gated action:
guardrailOverride is true, post-approval guardrails scan the actionIf either step rejects, the agent receives a denial message with a reason and can adjust its approach.
| Scenario | Recommended Handler |
|---|---|
| Development / testing | hitl.autoApprove() |
| Interactive CLI session | hitl.cli() |
| Production with human oversight | hitl.webhook(url) or hitl.slack(...) |
| High-volume autonomous agent | hitl.llmJudge(...) |
| Locked-down tool | hitl.autoReject('Tool disabled') |
Set the security tier in agent.config.json:
{
"security": {
"tier": "balanced"
}
}
Or programmatically:
import { SecurityTiers } from '@framers/agentos/safety/runtime';
agency({ security: { tier: SecurityTiers.BALANCED } });