The [server] extra installs the FastAPI server, dashboard, and CLI alongside the SDK. The base awaithumans package is just the lightweight HTTP client.
✓ Server running at http://localhost:3001✓ Database: ./.awaithumans/dev.db✓ Open the dashboard at: http://localhost:3001/setup?token=8aF... (one-shot setup link — paste it into your browser)
Open the printed /setup?token=... URL, paste a password, and create your operator account. You’re now logged into the dashboard at http://localhost:3001.
awaithumans dev auto-generates the encryption key, admin token, and SQLite database in ./.awaithumans/. The CLI also writes ~/.awaithumans-dev.json so the SDK can auto-discover the server URL and bearer token — you don’t have to set env vars.
Click the “Review at” URL (or refresh http://localhost:3001). You’ll see a task on your queue. Click in, fill the form, hit Submit.Within a second your script prints:
Refund approved: Duplicate charge confirmed by support team.
That’s the whole loop. The agent’s await_human() call blocked for as long as the human took to decide, then resumed with the typed RefundDecision instance.
The SDK long-polls until the task reaches a terminal state. For agents that can park for hours/days (Temporal, LangGraph workflows), the durable adapters replace polling with workflow-engine signals so you spend zero compute while waiting.
Right now the only place a human sees the task is the dashboard. Add Slack with one extra kwarg — the rest of the call is identical to the script above:
decision = await_human_sync( task="Approve $250 refund?", payload_schema=RefundPayload, payload=RefundPayload( amount_usd=250, customer_id="cus_demo", reason="Duplicate charge" ), response_schema=RefundDecision, timeout_seconds=900, notify=["slack:#approvals"], # ← post to this channel)
Set up the Slack channel first, otherwise the notify= line is silently dropped and the task only appears in the dashboard — the snippet above won’t post to any Slack workspace until you’ve configured the bot.You need three things on the awaithumans server (the process running awaithumans dev):
AWAITHUMANS_SLACK_BOT_TOKEN (xoxb-...) and AWAITHUMANS_SLACK_SIGNING_SECRET exported in the server’s environment.
The bot invited to the channel you’re posting to (/invite @Await Humans in #approvals).
Restart awaithumans dev after setting the env vars. Without this, the SDK call still succeeds — Slack delivery happens in a background task and only logs the failure server-side.
See Channels: Slack for the full setup walkthrough (static-token mode is the fastest path; OAuth multi-workspace mode is also documented).Email works the same way — notify=["email:approvals@acme.com"] — and has the same prerequisite: configure a transport (Resend or SMTP) on the server first. See Channels: Email.
Have an LLM gut-check the human’s decision before it lands.
Bring your own key. The verifier runs server-side, not in your agent process. That means your LLM provider API key must be exported on the awaithumans server’s environment (the same shell that ran awaithumans dev), not the shell running your agent script. If you skip this step, the task fails with VERIFIER_API_KEY_MISSING at submit time.
In the terminal that’s running awaithumans dev (or in your .env), set the key for whichever provider you’ll use:
export ANTHROPIC_API_KEY=sk-ant-...# then restart: awaithumans dev
You also need the provider’s SDK installed in the awaithumans server’s Python environment:
pip install "awaithumans[verifier-claude]" # for Claude — pick the one matching your provider
Then attach the verifier to your await_human call:
from awaithumans.verifiers.claude import claude_verifierdecision = await_human_sync( task="Approve $250 refund?", payload_schema=RefundPayload, payload=RefundPayload( amount_usd=250, customer_id="cus_demo", reason="Duplicate charge" ), response_schema=RefundDecision, timeout_seconds=900, verifier=claude_verifier( instructions=( "Reject if the notes contradict the decision, or if " "the amount is over $1000 and notes are empty." ), max_attempts=3, ),)
Your agent code doesn’t carry any API key — it just declares the verifier config; the server does the LLM call.See Verifier for the full provider list, custom env var names, and NL-parsing tricks.