camelRun by camelAI
Human in the
loop
AI agents
camelRun by camelAI is a hosted runtime for AI agents that ask a person before a risky step, sleep with no agent time billed while they wait, and carry on from the same step when the answer comes.
Delete the staging database
Allow db__drop to run?
{"database":"staging"}Done. The staging database is gone.
input_resolved · answered · by alice
→ db__drop({"database":"staging"})
Done. The staging database is gone.
Four kinds of input
How AI agents ask a person
Approval is one of four ways an agent can ask. It can also ask a question, show a short form, or send someone to a web page to finish a step. Each one pauses the run the same way.
- 01Approval
Allow db__drop to run?
{ "database": "staging" }ApproveDenyApprove a tool call
Mark a tool
needsApproval, or give an MCP or OpenAPI source a policy. The person sees the exact call before it runs.needsApproval: true
- 02QuestionSnapshot
Keep a snapshot of staging before it goes?
- Keep one
- No snapshot
SubmitAnswer a question
Turn on the
ask_usertool and the model can ask multiple-choice questions, with room for the person's own words where it allows."builtins": ["ask_user"]
- 03Form
Where should the last backup go?
bucketops-archivelabelstaging-finalSubmitSkipFill in a short form
A tool calls
context.askwith a flat form, and the person's answers come back to it as fields.context.ask(message, schema)
- 04Web page
Connect the cloud account to finish
Open https://accounts.example.comDoneCancelFinish a step on a web page
A tool calls
context.requireUrlto send the person to an https page to connect an account or sign something.context.requireUrl(url, message)
Approvals in code
Add a human approval step to your AI agent
When a step needs a person, the run comes back with status input_required and the input it waits on. Answer it now or days later, from this process or another one, and you get the resumed run.
- Per tool
needsApproval: trueasks before every call.- Per call
- A function of the call's arguments decides each time.
- Per source
- MCP and OpenAPI tools take never, always or destructive.
import { mkdir, readdir, rm, writeFile } from "node:fs/promises";
import { basename } from "node:path";
import { createInterface } from "node:readline/promises";
import { Agents, schema, tool } from "@camelai/run";
// A throwaway folder for the agent to tidy.
const dir = "playground";
await mkdir(dir, { recursive: true });
for (const f of ["notes.md", "build.log", "cache.tmp", "old-draft.tmp"]) await writeFile(`${dir}/${f}`, "x");
const agents = new Agents();
const agent = await agents.upsert("approval-ts", {
model: "openrouter/openai/gpt-6-luna",
instructions: "You tidy the user's playground folder with your tools.",
tools: {
list_files: tool({
description: "List the files in the playground",
input: schema.Object({}),
execute: () => readdir(dir),
}),
delete_file: tool({
description: "Delete a file from the playground",
input: schema.Object({ name: schema.String() }),
needsApproval: true, // the run stops and waits for a person before each call
execute: async ({ name }) => (await rm(`${dir}/${basename(name)}`), { deleted: name }),
}),
},
});
const cli = createInterface({ input: process.stdin, output: process.stdout });
let run = await agent.run(process.argv.slice(2).join(" ") || "Delete the temporary files.", { user: "me" });
while (run.status === "input_required") {
const input = run.inputs[0];
const yes = (await cli.question(`${input.message} ${input.detail.argumentsPreview ?? JSON.stringify(input.detail.arguments)} [y/N] `)).trim() === "y";
run = await input.answer(yes, { from: "me" });
}
console.log(run.text, "\nleft:", await readdir(dir));
cli.close();
await agents.close();npm install
export CAMELAI_API_KEY=art_...
npm startAllow delete_file to run? {"name":"cache.tmp"} [y/N] y
Allow delete_file to run? {"name":"old-draft.tmp"} [y/N] n
Deleted `cache.tmp`. I couldn't delete `old-draft.tmp` because that deletion was declined.
left: [ 'build.log', 'notes.md', 'old-draft.tmp' ]Answer anywhere
Answer AI agent approvals in your app, in Slack or from your server
The waiting input lives in camelRun, not in the process that started the run. Answer it wherever your people are, and the turn picks up the same way.
- AgentChat
alice
Delete the staging database
Staging has no traffic this week. I'll drop it once you say so.
Allow db__drop to run?
{ "database": "staging" }ApproveDenyYour appThe React
<AgentChat>shows the call with Approve and Deny buttons. - Slack · thread
Thread
ops
alice5:58 PM@ops Delete the staging database
opsApp5:58 PMStaging has no traffic this week. I'll drop it once you say so.
Approve this action? db__drop (db) with {"database":"staging"}
Reply approve or deny.
alice9:12 AMapprove
opsApp9:12 AMDone. The staging database is gone.
Slack, Telegram or DiscordThe agent's reply ends with the request. Someone allowed to answer replies approve or deny.
- Webhook · RESTTo your server
POST https://example.com/hooks/agents
{"id": "evt_…", "type": "input.requested", "created": 1790000000, "data": {"agentId": "client_…", "requestId": "…", "inputId": "…", "toolCallId": "…", "kind": "approval", "expiresAt": …}}Your answerPOST /v1/agents/:id/inputs/:inputId
{"action": "accept", "from": "alice"}The turn resumes.
Your serverA webhook tells your server when an agent asks. Answer over the API, and build one approvals inbox across every agent with
agents.runtime.inbox.
Human in the loop authorization
Control who can approve your AI agent's actions
Human in the loop authorization decides who gets to say yes.
Runs as approved
An approved call runs with exactly the arguments the person saw.
Declined means never
A declined call never runs.
Your tool can check
The approval travels with the call, on
context.identity.approval.
- aliceStarted the turnCan answer
- slack:U0123An approver in the definitionCan answer
- samNot on the list403
- The modelHas no way to answerCan't answer
FAQ
Questions about human in the loop AI agents
- 01
What are human-in-the-loop agents?
AI agents that stop and ask a person before they act on something that matters, like deleting data or changing production. On camelRun the agent pauses at that step, waits for the answer, and then carries on with it.
- 02
What is human in the loop authorization for AI agents?
It's the rule for who may say yes to an agent. On camelRun that's whoever asked for the work plus a list of approvers you keep, and a request from anyone else gets a 403. The model itself can't answer.
- 03
What is human in the loop when using AI?
A person reviews or decides at the points where the AI shouldn't act alone. For an agent that can mean approving a tool call, answering a question, filling in a form, or finishing a step on a web page, while the agent waits.
- 04
How long can an AI agent wait for a person on camelRun?
Days. The run suspends and the agent sleeps until someone answers, and the agent's definition sets how long an input waits. When the answer comes, it picks up from the same step, even after a deploy or a crash in between.
- 05
Do I pay while my agent waits for approval?
No agent time is billed while it waits, because the agent is asleep. camelRun charges $0.01 per agent-hour only while an agent is in a run, and idle and sleeping agents cost only storage.
- 06
Can people approve agent actions from Slack, Telegram or Discord?
Yes. In Slack, Telegram or Discord the agent's reply ends with the request as text. The next message from someone allowed to answer settles it: approve or deny, an option's number, or done after a web page step.
- 07
What if someone sends a new message instead of answering?
The new message wins. The waiting inputs close with "Not answered: the user sent a new message instead", and then the agent takes the new message.
More on human in the loop AI agents
- DocsHuman input: approvals, questions and forms
- DocscamelRun concepts: agents, runs and waking later
- OverviewcamelRun, the hosted runtime for AI agents
- camelRunSlack AI agent
- camelRunDurable AI agents
- camelRunBackground AI agents
- camelRunTelegram AI bot
- camelRunMulti-agent orchestration
- camelRunGitHub AI agent
- GuideBuilding durable AI agents that wait days for a person
Put a person in the loop today
Get an API key, mark the risky tool, and let your agent ask. The human input guide has the rest.
Read https://run.camelai.com/SKILL.md and set up camelRun in this project. Ask me what the agent should do.
Paste into Claude Code, Codex, Cursor or any coding agent. It asks what your agent should do, then builds it.