Repository
human-api
Self-hosted OpenAI-compatible API backed by an authorized shared human response queue.
README
Human API
A self-hosted, OpenAI-compatible Chat Completions API where authorized human responders write the answer through a shared web queue.
Human-powered disclosure: this is not an autonomous model. API messages are shown to authorized people, may be stored for queue operation and audit, and the API response identifies its origin with X-Answer-Origin: human. Callers must not submit passwords, API keys, authentication codes, financial credentials, medical records, or other highly sensitive data.
The complete path
sequenceDiagram
participant C as OpenAI client
participant A as FastAPI
participant D as PostgreSQL
participant H as Human responder
C->>A: POST /v1/chat/completions
A->>D: Create pending question + stable chatcmpl_ ID
A-->>A: Async DB polling (no open transaction)
H->>A: Session login + heartbeat
H->>A: Claim question (conditional UPDATE)
H->>A: POST {content} only
A->>D: Atomic claimed → answered
A-->>C: Server-built chat.completion
The responder sees a controlled JSON-shaped editor:
{
"id": "chatcmpl_server-generated",
"content": ""
}
id is visible, copyable, and read-only. Only content is editable. The browser submits exactly:
{
"content": "The human-written answer."
}
The server creates id, object, created, model, choices, assistant role, index, and finish reason.
Features
GET /v1/models,GET /v1/models/{model}, andPOST /v1/chat/completions- Official OpenAI SDK compatibility for non-streaming text completions
- HMAC-SHA-256 API-key digests; raw keys are returned once
- HttpOnly responder sessions, Argon2 password hashes, and CSRF validation
- Atomic claims and answers, renewable claim leases, deadlines, cancellation, and audit events
- Database-backed waiting and reconciliation for multi-worker correctness
- Per-key database rate limits and idempotency keys
- Shared queue with polling, presence heartbeat, read-only ID, and controlled content editor
- PostgreSQL, Alembic, FastAPI, React, Docker Compose, tests, and CI
Quick start
Requirements: Docker with Compose.
git clone https://github.com/jzjzzzzzzz/human-api.git
cd human-api
cp .env.example .env
Replace both pepper values in .env with different random values:
python -c 'import secrets; print(secrets.token_urlsafe(48))'
python -c 'import secrets; print(secrets.token_urlsafe(48))'
Start the stack and create an administrator:
docker compose up --build -d
docker compose exec api python -m scripts.create_user [email protected] --role admin
Open http://localhost:8080, sign in, then create an external key through the admin API (the raw key appears once):
# First sign in and copy csrf_token plus the human_session cookie.
curl -c cookies.txt http://localhost:8080/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]","password":"your-password"}'
curl -b cookies.txt http://localhost:8080/api/admin/api-keys \
-H 'Content-Type: application/json' \
-H 'X-CSRF-Token: replace-with-login-csrf-token' \
-d '{"name":"Local client","rate_limit_per_minute":10}'
Keep the returned human_sk_... value secret.
OpenAI Python client
from openai import OpenAI
client = OpenAI(
api_key="human_sk_REPLACE_ME",
base_url="http://localhost:8080/v1",
timeout=240.0,
)
response = client.chat.completions.create(
model="human-1",
messages=[{"role": "user", "content": "Hello, human model."}],
)
print("ID:", response.id)
print("Answer:", response.choices[0].message.content)
The request waits until a responder claims and answers it, or until the configured deadline.
curl
curl http://localhost:8080/v1/chat/completions \
-H 'Authorization: Bearer human_sk_REPLACE_ME' \
-H 'Content-Type: application/json' \
-d '{
"model": "human-1",
"messages": [{"role": "user", "content": "Hello, human model."}]
}'
Supported request behavior
Supported roles are developer, system, user, and assistant. Content may be a string or text-only content-part array. stream must be absent or false; n must be absent or 1. Sampling values are validated but do not control a person.
The MVP rejects streaming, multiple choices, tools, function calling, multimodal content, and non-text response formats with structured OpenAI-style errors. It never calls another model or invents an answer.
See OpenAI compatibility, operations, security, and privacy.
Tests
make setup
make lint
make test
The backend suite includes a real asynchronous request → queue → atomic claim → strict answer → completion round trip and a concurrent two-responder claim race. examples/human_llm_e2e.py exercises running HTTP services through the official OpenAI client.
Related project
For a grounded personal Q&A agent framework, see Agent-Me Starter.