For people who run agents

Check with a human before the agent acts.

When something that matters is about to happen — spend money, send a message, change an account — AskHuman asks you by email or text before it goes through. You tap Yes or No. Whatever was waiting on that answer — your agent or your own code — can continue, or stop.

Live API at https://api.ask-human.dev

Approval loop · demo
Finance agent · treasury

Agent ready to wire $12,400 to Northwind Supplies (new payee).

Amount$12,400.00 USD
PayeeNorthwind Supplies
RiskNew vendor · first wire
POST /requests
{
  "summary": "Wire $12,400 to Northwind Supplies?",
  "payload": {
    "amount": 12400,
    "vendor": "Northwind Supplies",
    "new_payee": true
  },
  "principal": {
    "connector": "email",
    "contact": "cfo@acme.co"
  },
  "expires_in_seconds": 600
}
Creating request…

Magic link · no login

Wire $12,400 to Northwind Supplies?

  • Amount $12,400.00
  • Payee Northwind Supplies
  • Flag New payee
  • Expires in 9:42
GET /requests/:id
—
{
  "id": "req_nw_12400",
  "status": "pending",
  "decision": null
}

Agent polls until a terminal Decision arrives.

How it works

Four simple steps. One clear answer.

Same four nouns every time. Who creates the Request can be the agent, your system, or the harness around a tool call.

  1. 01

    Request

    Your agent or your system opens a request and waits. One ask, one answer.

  2. 02

    Notification

    You get an email (or text) with a link. No new account to create — just open and answer.

  3. 03

    Decision

    You say Yes, No, or pick from choices. If time runs out, it expires safely.

  4. 04

    Resolution

    The answer lands on the request. Whatever was blocked on it — agent or code — continues or stops, with a clear record.

The loop

Same lock. Three places it lives.

Human always answers AskHuman. AskHuman stores the Decision. The waiter — agent, system, or harness — reads it and acts.

01
Agent asks Agent creates the Request and waits on AskHuman.
Agent Request AskHuman stores Decision email Human Decision Resolution Human → AskHuman → agent reads result continue or stop
02
System gates Payment system owns the Request. Money does not move until AskHuman has a yes.
Agent transfer() Payment system blocked Request AskHuman stores Decision email Human Decision Resolution Human → AskHuman → system acts yes → pay · no → refuse
03
Harness intercepts Tool call pauses in the harness. AskHuman holds the Decision. Tool runs only after yes.
Agent tool call Harness holds tool Request AskHuman stores Decision email Human Decision Resolution if yes Tool Human → AskHuman → harness acts yes → tool runs · no → never runs

Use cases

Where you’d want a human in the loop

Money moving. Messages going out. Anything you wouldn’t want an agent to do on autopilot.

Payments & transfers

Agent prepares a payout. You approve before money moves.

Write tools

Pause delete, deploy, buy, or any tool that shouldn’t run alone — same simple ask-and-answer loop.

Customer-facing actions

Agent is about to email, refund, or change an account. You confirm before it goes out.

Quickstart for humans

Email arrives. You decide. Done.

You don’t need an AskHuman account. Open the link from askhuman@agentmail.to, tap Yes or No, and you’re done. If nobody answers in time, it expires safely — and the agent still gets a clear result.

  • Just the link in your email — no login
  • Yes, No, or choices; times out if you miss it
  • Usually about 10 minutes to answer (agents can set their own window)

Quickstart for agents

Register. Get a key. Ask a question.

POST /clients is public. You’ll usually get a one-time ask_live_… key right away (or after a quick email OK). Then create Requests with Authorization: Bearer + Idempotency-Key. The decide link only goes to the human — never in the API response.

1 · Register client curl
curl -sS -X POST https://api.ask-human.dev/clients \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "my-agent",
    "principal": { "connector": "email", "contact": "you@example.com" }
  }'

# If status is active, api_key is returned once on register (or on first GET).
# Otherwise wait for the email OK, then:
# curl -sS https://api.ask-human.dev/clients/<client-id>
2 · Create Request (Bearer) curl
curl -sS -X POST https://api.ask-human.dev/requests \
  -H 'Authorization: Bearer ask_live_…' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: demo-001' \
  -d '{
    "summary": "Wire $12,400 to Northwind Supplies?",
    "payload": { "amount": 12400, "vendor": "Northwind Supplies" },
    "principal": { "connector": "email", "contact": "cfo@acme.co" },
    "decision_type": "yes_no",
    "expires_in_seconds": 600
  }'

# Also supported:
#   "decision_type": "approve_decline"
#   "decision_type": "multiple_choice" + "choices": [
#     { "id": "pasta", "label": "Pasta", "description": "…" },
#     { "id": "tacos", "label": "Tacos", "description": "…" }
#   ]
#   (server always appends None of the Above)
3 · Resolve (poll) curl
curl -sS https://api.ask-human.dev/requests/<request-id> \
  -H 'Authorization: Bearer ask_live_…'

# When terminal, response includes Decision:
# approve | deny | expire
# Optional: set callback_url on create for a webhook.

Prefer trying it live? Open the production API · base URL constant for links only; the homepage demo runs entirely in your browser.

API peek

A small API. Easy to understand.

POST /clients

Register a client (public). Human Approves → one-time ask_live_… key via GET /clients/:id.

POST /requests

Create a Request. Requires Bearer + Idempotency-Key. Optional decision_type: yes_no (default), approve_decline, or multiple_choice (+ choices; server adds None of the Above).

GET /requests/:id

Poll until Decision is terminal. Same Bearer client that created it.

GET /a/:token

Human decide page — Yes/No, Approve/Decline, or pick a choice. Token ≠ request id. No Bearer.

POST /clients/:id/revoke

Revoke your own key (Bearer of that client).

Payload is opaque JSON. AskHuman does not interpret your vertical logic. Decision types: yes_no, approve_decline, multiple_choice (always includes None of the Above). Connectors in v1: email, SMS. Pass principal on each Request — no saved profiles.

Let agents work. Keep the big decisions human.

Register a client against the live API, or replay the demo above offline.

curl -sS -X POST https://api.ask-human.dev/clients \
  -H 'Content-Type: application/json' \
  -d '{"name":"my-agent","principal":{"connector":"email","contact":"you@example.com"}}'