Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.awaithumans.dev/llms.txt

Use this file to discover all available pages before exploring further.

pip install awaithumans                  # SDK only (httpx + pydantic)
pip install "awaithumans[server]"        # SDK + server + CLI + dashboard
pip install "awaithumans[temporal]"      # + Temporal adapter peer dep
pip install "awaithumans[langgraph]"     # + LangGraph adapter peer dep
pip install "awaithumans[verifier-claude]"   # + Anthropic SDK
pip install "awaithumans[verifier-openai]"   # + OpenAI SDK
pip install "awaithumans[verifier-gemini]"   # + Google SDK
pip install "awaithumans[verifier-azure]"    # + Azure OpenAI
Python 3.10+. The base SDK (pip install awaithumans) has only two runtime deps: httpx and pydantic.

await_human / await_human_sync

The primitive. Async and sync flavors:
import asyncio
from pydantic import BaseModel
from awaithumans import await_human, await_human_sync


# Define the shape of the data your agent sends to the human...
class RefundPayload(BaseModel):
    amount: int
    customer: str


# ...and the shape of the response form they fill in.
class RefundDecision(BaseModel):
    approved: bool
    reason: str = ""


# Sync (from a regular Python script, Flask, Celery, etc.)
decision = await_human_sync(
    task="Approve refund?",
    payload_schema=RefundPayload,
    payload=RefundPayload(amount=250, customer="cus_123"),
    response_schema=RefundDecision,
    timeout_seconds=900,
)
print(decision.approved, decision.reason)


# Async (inside an existing asyncio context — agent frameworks, ASGI)
async def main() -> None:
    decision = await await_human(
        task="Approve refund?",
        payload_schema=RefundPayload,
        payload=RefundPayload(amount=250, customer="cus_123"),
        response_schema=RefundDecision,
        timeout_seconds=900,
    )
    print(decision.approved, decision.reason)


asyncio.run(main())

Parameters

ParameterTypeRequiredDescription
taskstryesHuman-readable task description (shown in the dashboard / Slack / email).
payload_schematype[BaseModel]yesPydantic class that defines the data the human reviews.
payloadBaseModelyesInstance of payload_schema — the actual data.
response_schematype[BaseModel]yesPydantic class for the response form. Drives the UI.
timeout_secondsintyesMin 60 (1 min), max 2,592,000 (30 days).
assign_tostr | list[str] | dict | NonenoRouting target. See Routing.
notifylist[str] | NonenoChannel destinations (slack:#x, email:y@z, …).
verifierVerifierConfig | NonenoServer-side LLM verification. See Verifier.
idempotency_keystr | NonenoDefault: sha256(task, payload)[:32]. See Idempotency.
redact_payloadboolnoDefault False. When true, audit log + verifier prompt are scrubbed.
server_urlstr | NonenoOverride AWAITHUMANS_URL env var / discovery file.
api_keystr | NonenoOverride AWAITHUMANS_ADMIN_API_TOKEN env var / discovery file.

Returns

An instance of response_schema — Pydantic-validated. If validation fails, raises SchemaValidationError.

Raises

ExceptionWhen
TaskTimeoutErrorTask hit timeout_seconds without completion.
TaskCancelledErrorAgent or operator cancelled.
VerificationExhaustedErrorVerifier rejected max_attempts times.
SchemaValidationErrorResponse didn’t match response_schema.
TaskNotFoundErrorTask ID disappeared (DB reset?).
TaskCreateErrorServer rejected POST /api/tasks.
PollErrorLong-poll returned non-200.
ServerUnreachableErrorCouldn’t connect to server_url.
MarketplaceNotAvailableErrorUsed assign_to={"marketplace": True}. Reserved for Phase 3.
All inherit from AwaitHumansError.

Verifier helpers

from awaithumans.verifiers.claude import claude_verifier
from awaithumans.verifiers.openai import openai_verifier
from awaithumans.verifiers.gemini import gemini_verifier
from awaithumans.verifiers.azure_openai import azure_openai_verifier

verifier = claude_verifier(
    instructions="Reject any refund decision that lacks a clear reason.",
    model="claude-sonnet-4-5",         # optional, has default
    max_attempts=3,                    # default 3
    api_key_env="ANTHROPIC_API_KEY",   # default
)
Each returns a VerifierConfig you pass to await_human(verifier=...). The actual LLM call runs server-side. See Verifier.

Adapters

Temporal

# Inside a Temporal workflow:
from temporalio import workflow
with workflow.unsafe.imports_passed_through():
    from awaithumans.adapters.temporal import await_human

# In your web server (separate process):
from awaithumans.adapters.temporal import dispatch_signal
See Temporal.

LangGraph

# Inside a LangGraph node:
from awaithumans.adapters.langgraph import await_human

# Driver — run the graph:
from awaithumans.adapters.langgraph import drive_human_loop
See LangGraph.

CLI

awaithumans dev               # boot server + auto-config for local dev
awaithumans add-user          # add a directory user (interactive)
awaithumans list-users        # list directory users
awaithumans version           # print version
awaithumans dev auto-generates PAYLOAD_KEY, ADMIN_API_TOKEN, and the SQLite DB if missing. Writes ~/.awaithumans-dev.json so the SDK auto-discovers the running server.

Configuration

The SDK reads configuration in this order (first match wins):
  1. Function-call args (server_url=, api_key=)
  2. Environment variables (AWAITHUMANS_URL, AWAITHUMANS_ADMIN_API_TOKEN)
  3. Discovery file (~/.awaithumans-dev.json)
  4. Defaults (http://localhost:3001, no token)
Production deployments should use environment variables. The discovery file is a dev affordance.

Type stubs

The package ships with py.typed. mypy/pyright pick up the types automatically:
# (using the RefundPayload / RefundDecision models defined earlier)
decision: RefundDecision = await_human_sync(
    task="Approve refund?",
    payload_schema=RefundPayload,
    payload=RefundPayload(amount=250, customer="cus_123"),
    response_schema=RefundDecision,
    timeout_seconds=900,
)
# `decision` is typed as RefundDecision — IDE autocomplete + mypy enforcement.