Loading...
Loading...
Weekly AI insights —
Real strategies, no fluff. Unsubscribe anytime.
Written by Gareth Simono, Founder and CEO of Agentik {OS}. Full-stack developer and AI architect with years of experience shipping production applications across SaaS, mobile, and enterprise platforms. Gareth orchestrates 267 specialized AI agents to deliver production software 10x faster than traditional development teams.
Founder & CEO, Agentik {OS}
Full autonomy is a myth for any system that matters. The question is where to position humans so they add value without becoming the bottleneck.

Full autonomy is a myth. At least for any system that deals with things that matter.
Every AI agent in production needs a human somewhere in the loop. The debate is not about whether humans belong in agent systems. It is about where to put them so they add value without becoming the bottleneck that kills all the efficiency you built.
Get this wrong and you get one of two failure modes. The first: the agent runs unsupervised and makes expensive, embarrassing, or legally significant mistakes. I have seen an agent send 40,000 customer emails with wrong order totals because nobody reviewed the template before deployment. The second: humans are required to approve everything and the agent provides zero time savings, just a slightly different interface for the same manual work. Both failures are common. Both are preventable.
The patterns that work share a common principle: humans should be in the loop for decisions where their judgment adds value that the agent cannot provide, not for decisions where they are just rubber-stamping work the agent already did correctly.
Before designing human-in-the-loop patterns, it is worth being honest about what human judgment actually contributes. Not what we assume it contributes. What it actually adds.
Humans are better than agents at:
Context outside the system. The agent knows what is in the data. The human knows what the data means in organizational, political, or relational context. "Customer ID 4721 is the CEO's college roommate" is not in the CRM. The agent does not know. The human does.
Ethical judgment in novel situations. Edge cases that do not match any pattern in training data. The agent will pattern-match to the closest known case. The human can reason about first principles.
Relationship and political dynamics. Who is the right person to escalate to? What tone is appropriate given the history between these parties? What is the unspoken agenda behind this request? Agents do not have this knowledge.
Accountability. Someone has to be responsible for consequential decisions. Accountability requires human judgment.
Agents are better than humans at:
Volume. Handling 500 routine requests per hour without fatigue. Consistency. Applying the same standard to every case without mood-based variation. Recall. Accessing and synthesizing information across many sources simultaneously. Speed. Generating analysis, drafts, and options in seconds.
The optimal human-in-the-loop design puts humans in positions that leverage their strengths and removes them from positions where the agent is better. This sounds obvious. Most implementations do the opposite.
Approval gates are the most familiar human-in-the-loop pattern. Agent does analysis. Human reviews and approves. System executes.
They work well for decisions that are high-stakes (mistakes are costly) and low-frequency (the approval step does not become a constant bottleneck).
Good use cases: deployment approvals, bulk communications reaching hundreds or thousands of customers, financial transactions above a significant threshold, contract modifications, policy changes.
interface ApprovalRequest {
id: string;
agentAction: {
type: string;
description: string;
estimatedImpact: string;
};
agentReasoning: string; // Why the agent recommends this action
relevantContext: string; // Data and analysis supporting the recommendation
options: ApprovalOption[];
deadline?: Date; // Escalate automatically if not reviewed by deadline
escalationTarget?: string; // Who to escalate to if primary reviewer unavailable
}
interface ApprovalOption {
id: string;
label: string; // "Approve", "Reject", "Modify and Approve"
consequence: string; // What happens if this option is selected
requiresComment: boolean;
}
async function requestApproval(
request: ApprovalRequest,
reviewerUserId: string
): Promise<ApprovalDecision> {
// Send to reviewer via email, Slack, or approval dashboard
await notifyReviewer(reviewerUserId, request);
// Wait for decision with timeout
const decision = await waitForDecision(request.id, {
timeoutMs: request.deadline
? request.deadline.getTime() - Date.now()
: 86400000, // 24 hour default
onTimeout: () => escalateApproval(request, request.escalationTarget),
});
return decision;
}The failure mode of approval gates is approval fatigue. When humans are asked to approve too many things, they stop reading the work and start rubber-stamping. The gate provides the appearance of oversight without the substance.
The fix: be ruthless about what goes through the gate. Every approval request should answer the question "is a human making a judgment here that the agent genuinely cannot make?" If the answer is no, remove the gate. A human approving something the agent already did correctly, with reasoning the human is not actually evaluating, is not oversight. It is bureaucratic theater.
Reserve human approval for decisions where a mistake's cost justifies the time cost of review. Everything else should run autonomously.
The second pattern separates good agents from great ones. The ability to recognize when you are outside your competence and ask for help.
Agents are confidently wrong by default. They produce responses regardless of whether they actually know. Training artifact: models are rewarded for coherent responses, not for admitting ignorance. You have to explicitly engineer the uncertainty recognition.
The key insight: effective escalation criteria are observable, not internal. "Escalate when you are not confident" is useless. The agent does not have a reliable confidence meter. "Escalate when the customer mentions legal action" is precise, observable, and executable.
const ESCALATION_RULES: EscalationRule[] = [
{
trigger: "customer_mentions_legal",
description: "Any message mentioning lawyers, lawsuits, legal action, or threats to sue",
detect: (message: string) =>
/\b(lawyer|attorney|lawsuit|legal action|sue|court|litigation)\b/i.test(message),
escalateTo: "legal_support_specialist",
urgency: "high",
contextToInclude: ["full_conversation_history", "account_tier", "issue_history"],
},
{
trigger: "vulnerable_customer_indicator",
description: "Indicators of financial hardship, mental health crisis, or domestic situation",
detect: (message: string) =>
/\b(can't afford|lost my job|homeless|crisis|harm|hurt myself)\b/i.test(message),
escalateTo: "senior_support_specialist",
urgency: "critical",
contextToInclude: ["full_conversation_history", "account_tier"],
},
{
trigger: "data_access_request",
description: "Requests involving access to data the agent cannot verify authorization for",
detect: (context: AgentContext) =>
context.requestedResources.some(r => r.classification === "restricted"),
escalateTo: "data_security_team",
urgency: "medium",
contextToInclude: ["requested_resources", "user_identity", "stated_purpose"],
},
];
async function checkEscalation(
message: string,
context: AgentContext
): Promise<EscalationDecision> {
for (const rule of ESCALATION_RULES) {
const triggered = typeof rule.detect === "function"
? rule.detect(message) || rule.detect(context)
: false;
if (triggered) {
return {
shouldEscalate: true,
rule: rule.trigger,
escalateTo: rule.escalateTo,
urgency: rule.urgency,
context: buildEscalationContext(context, rule.contextToInclude),
};
}
}
return { shouldEscalate: false };
}Implement escalation as a tool call, not an instruction. When escalation is a tool the agent can call, it is a concrete action rather than an abstract concept. The agent calls escalate_to_human with structured parameters, and your system routes the escalation to the right person with the right context.
This is where human-agent collaboration gets genuinely powerful. Not humans approving agent work. Not agents escalating to humans. But humans and agents working on the same task, each contributing what they do best.
The pattern:
interface CollaborativeTask {
userIntent: string;
agentGenerated: {
options: Option[];
analysisPerOption: Record<string, Analysis>;
recommendation: string;
recommendationReasoning: string;
};
humanInput: {
selectedOption: string;
modifications?: string;
additionalContext?: string;
};
executionResult?: ExecutionResult;
}
// Example: marketing copy generation
const task: CollaborativeTask = {
userIntent: "Create email subject line for Black Friday campaign",
agentGenerated: {
options: [
{ id: "a", content: "Your exclusive early access starts NOW" },
{ id: "b", content: "48 hours only: the sale we planned all year" },
{ id: "c", content: "Save up to 60% - but only if you move fast" },
],
analysisPerOption: {
a: { predictedOpenRate: "22%", tone: "urgency", riskFlags: [] },
b: { predictedOpenRate: "19%", tone: "exclusivity", riskFlags: [] },
c: { predictedOpenRate: "24%", tone: "scarcity", riskFlags: ["may trigger spam filters"] },
},
recommendation: "c",
recommendationReasoning: "Highest predicted open rate, though spam filter risk should be reviewed.",
},
humanInput: {
selectedOption: "b",
modifications: "Change to: '48 hours only: the sale you've been waiting for'",
additionalContext: "Our spam filter risk tolerance is low given recent deliverability issues",
},
};This design respects both parties' strengths. The agent handles option generation and quantitative analysis, which it does quickly and thoroughly. The human applies judgment about brand voice, relationship context, and organizational constraints that the agent cannot access.
Critical design principle: minimize human cognitive load. Do not make humans write from scratch. Give them options to select from, or outputs to edit rather than create. Every additional decision required from the human is friction that reduces the quality of their input. A human choosing from three good options gives you good judgment. A human writing a brief from scratch is doing the agent's job.
The fourth pattern is invisible when it works and catastrophic when it does not. Exception handling for the cases the agent was not designed for.
Every agent system has a capability boundary. Inside the boundary, it handles tasks reliably. Outside the boundary, behavior is unpredictable. The human-in-the-loop design needs to include a mechanism for routing edge cases to humans before the agent makes a costly attempt.
interface ExceptionHandler {
// Agent calls this when it detects it is outside its competence
handleException(context: AgentContext): Promise<ExceptionHandlingDecision>;
}
class SmartExceptionHandler implements ExceptionHandler {
async handleException(context: AgentContext): Promise<ExceptionHandlingDecision> {
const similarCases = await this.findSimilarHistoricalCases(context);
if (similarCases.length > 0 && similarCases[0].resolutionConfidence > 0.85) {
// Learned from previous exceptions, can now handle autonomously
return {
action: "handle_autonomously",
approach: similarCases[0].resolution,
confidence: similarCases[0].resolutionConfidence,
};
}
// Genuinely novel case, route to human
return {
action: "escalate_to_human",
reason: "Novel case outside agent training distribution",
suggestedExpertise: this.identifyRequiredExpertise(context),
similarCases: similarCases.slice(0, 3), // Help human by showing closest precedents
};
}
}The smart exception handler learns over time. When a human resolves an exception, that resolution is added to the pattern library. The next time a similar case appears, the agent can handle it without escalation. Over months, the exception rate decreases as the agent learns from every human intervention.
This is the long-term trajectory you want: humans starting in oversight roles and gradually moving to higher-leverage strategic positions as the agent learns from their decisions.
Every human interaction is a training signal. Most teams waste it.
When a human corrects agent output, that correction contains information about what the agent got wrong and what the right answer looks like. Capture it systematically.
interface HumanCorrectionLog {
sessionId: string;
agentOutput: string;
humanCorrection: string;
correctionType: "factual" | "tone" | "completeness" | "format" | "approach";
correctionRationale?: string;
timestamp: Date;
}
// Aggregate corrections into system prompt examples
async function updateAgentFromCorrections(
corrections: HumanCorrectionLog[],
currentSystemPrompt: string
): Promise<string> {
const significantCorrections = corrections
.filter(c => c.correctionType === "approach" || c.correctionType === "factual")
.slice(0, 10); // Most recent significant corrections
if (significantCorrections.length === 0) return currentSystemPrompt;
const correctionExamples = significantCorrections
.map(c => `Example correction:\nAgent output: ${c.agentOutput}\nCorrect approach: ${c.humanCorrection}\nReason: ${c.correctionRationale || "Preference based on context"}`)
.join("\n\n");
return `${currentSystemPrompt}\n\n## Recent Corrections to Learn From\n\n${correctionExamples}`;
}This approach is faster and cheaper than fine-tuning and gives you more control. Corrections added to the system prompt are visible, inspectable, and reversible. You can see exactly what the agent learned and remove it if it creates unintended behavior.
Over time, the agent accumulates institutional knowledge through corrections. The human role shifts from correcting routine mistakes to handling genuinely novel situations. This is the trajectory that makes human-agent collaboration scale.
The agent evaluation frameworks you build should track whether this learning is happening: is the rate of human corrections decreasing over time? If not, the feedback loop is not working.
The quality of human review depends significantly on how you present the work to be reviewed. A well-designed interface produces better human decisions. A poorly designed one produces rubber-stamping.
Design principles for review interfaces:
Show reasoning, not just output. The reviewer should see why the agent made the decision, not just what it decided. This enables the reviewer to catch reasoning errors even when the output looks correct.
Surface the key decision point. What is the one thing the human actually needs to judge? Do not make them read everything. Highlight the specific element requiring human judgment.
Make options concrete. Present "Approve" / "Reject" / "Modify" rather than a free-text input. Every additional decision the reviewer must make reduces review quality.
Provide relevant context. What information does the reviewer need to make a good decision? Show it. Do not make them go look it up.
Set appropriate time expectations. "This review should take approximately 2 minutes" helps reviewers allocate attention appropriately.
Building on the production agent patterns from building production agent teams, human-in-the-loop design is not an afterthought. It is a core architectural decision that determines whether your agent system is trustworthy at scale.
Q: What is human-in-the-loop AI?
Human-in-the-loop (HITL) is a pattern where AI agents operate autonomously for routine tasks but pause for human approval on high-stakes decisions. The human provides judgment at critical checkpoints — approving deployments, reviewing security changes, confirming business logic — while the agent handles execution autonomously between checkpoints.
Q: When should AI agents escalate to humans?
Agents should escalate when the decision is irreversible (database migrations, production deployments), involves security-sensitive operations, exceeds confidence thresholds, affects financial transactions, touches compliance-regulated processes, or encounters novel situations not covered by their training or instructions.
Q: How do you design effective human-AI collaboration workflows?
Effective HITL workflows clearly define which decisions are autonomous and which require approval, minimize human interruptions by batching approval requests, provide rich context for each decision point, have timeout mechanisms for unresponsive humans, and degrade gracefully when human approval is delayed.
Full-stack developer and AI architect with years of experience shipping production applications across SaaS, mobile, and enterprise. Gareth built Agentik {OS} to prove that one person with the right AI system can outperform an entire traditional development team. He has personally architected and shipped 7+ production applications using AI-first workflows.

Autonomous AI Decisions: Real Trust and Control Patterns
Can we just let the agent run on its own? The answer depends entirely on what happens when it's wrong. Here's the engineering behind real autonomy.

Agent Evaluation: Measuring What Actually Matters
97% accuracy sounds impressive until you ask what was measured. Most evaluation frameworks produce numbers without insight. Build ones that work.

Production Agent Teams: From Demo to Reality
The demo worked perfectly. Three weeks into production, they pulled it. The gap between prototype and production is always the same set of problems.
Stop reading about AI and start building with it. Book a free discovery call and see how AI agents can accelerate your business.