English · 简体中文
Package yourself as an LLM that existing clients can call.
Questions arrive in your web console or phone, and your human replies stream back through familiar model APIs.
Quick start · Deployment · Client setup · API compatibility · Architecture
iamllm is an open-source, self-hosted “human model” service. It turns OpenAI, Anthropic, and Gemini requests into a queue for a real person: callers still send normal model requests and receive native SSE streams, while the model has one human parameter and inference speed depends on typing speed.
It is not an AI proxy and does not secretly forward unanswered requests to another model. Unless an automation rule matches, the person running the instance writes the answer.
- Works with existing clients: OpenAI Chat Completions and Responses, Anthropic Messages, and Gemini GenerateContent.
- Human streaming: each Enter sends one chunk immediately; after at least one chunk, an empty Enter finishes the response.
- Stays responsive while you are away: keyword rules, schedules, quick replies, and a playful five-minute timeout fallback.
- Makes agent traffic readable: large system prompts, tool definitions, and internal memory live in a run log while the main chat shows the user-visible conversation.
- Handles multimodal requests and tools: inspect images and files, read tool schemas, and return tool names plus JSON arguments.
- Shares access safely: issue ordinary
sk-API keys with per-minute, daily, and concurrency limits; pause or revoke them at any time. - Web and mobile handoff: React and Flutter share drafts, read state, answer leases, and resumable realtime events.
- Runs on one server: one Go service with an embedded web app and SQLite—no Supabase, Redis, external database, or Python runtime required.
“Unlimited tokens” means iamllm does not charge by token. Client limits, HTTP body limits, storage, and human attention still apply.
The real web console separates pending, answered, and expired conversations and updates the queue in realtime.
| Client or protocol | Endpoint | Streaming | Images/files | Tools |
|---|---|---|---|---|
| OpenAI Chat Completions | POST /v1/chat/completions |
✓ | ✓ | ✓ |
| OpenAI Responses | POST /v1/responses |
✓ | ✓ | ✓ |
| Anthropic Messages / Claude Code | POST /v1/messages |
✓ | ✓ | ✓ |
| Gemini GenerateContent | POST /v1beta/models/{model}:generateContent |
✓ | ✓ | ✓ |
| Human async jobs | POST /v1/human/jobs |
Polling | ✓ | ✓ |
See API compatibility for exact behavior and known boundaries.
The host only needs Docker and Docker Compose:
cp .env.production.example .env.productionGenerate four different secrets and place them in .env.production:
echo "sk-$(openssl rand -hex 32)" # IAMLLM_API_KEY
openssl rand -hex 32 # IAMLLM_ADMIN_API_TOKEN
openssl rand -base64 24 # IAMLLM_ADMIN_PASSWORD
openssl rand -hex 32 # IAMLLM_SESSION_SECRETSet your public identity:
IAMLLM_MODEL_NAME=iam-human
IAMLLM_PUBLIC_BASE_URL=https://llm.example.com
IAMLLM_TIMEZONE=Asia/Shanghaidocker compose up -d --build
curl http://127.0.0.1:8000/healthPort 8000 binds to the server loopback interface by default so Caddy or Nginx can proxy it safely. For temporary LAN testing:
IAMLLM_BIND_IP=0.0.0.0 docker compose up -d --buildUse HTTPS in production. A ready-to-edit Caddy example and complete firewall, proxy, backup, and upgrade instructions are in Getting started.
Open http://127.0.0.1:8000/admin, sign in with the administrator credentials from .env.production, then:
- Confirm the public URL and model identifier under Service & devices.
- Create a managed key under API keys.
- Send a test question from
/playground. - Answer it from the Conversation desk.
IAMLLM_API_KEY is the unlimited owner key. Keep it private; share managed, revocable keys instead.
curl -N https://llm.example.com/v1/chat/completions \
-H 'Authorization: Bearer sk-your-managed-key' \
-H 'Content-Type: application/json' \
-d '{
"model": "iam-human",
"stream": true,
"messages": [{"role": "user", "content": "Are you free to answer?"}]
}'The request appears in the pending queue. The caller receives each chunk as soon as you send it; send an empty message after the first chunk to finish.
| Client | Base URL | API key | Model |
|---|---|---|---|
| OpenAI SDK / OpenCode | https://llm.example.com/v1 |
managed sk-... |
iam-human |
| Claude Code | https://llm.example.com |
managed sk-... |
iam-human |
| Gemini clients | https://llm.example.com |
managed sk-... |
iam-human |
Do not append /v1 to the Claude Code base URL; Claude Code adds /v1/messages itself.
export ANTHROPIC_BASE_URL=https://llm.example.com
export ANTHROPIC_AUTH_TOKEN=sk-your-managed-key
export ANTHROPIC_MODEL=iam-human
claudeSee Client integration for OpenCode, OpenAI Python/JavaScript SDKs, Responses, Gemini, images, and tool calls.
cd mobile
flutter pub get
flutter runThe app never hard-codes an instance address. Generate a QR code under Service & devices → Connect a device; scanning it transfers the server URL and a one-time pairing code. Manual URL/code entry and administrator login remain fallback options.
The Flutter app handles the queue, human streaming, tools, attachments, automation, API-key requests, and device management. Credentials stay in iOS Keychain or Android Keystore.
Rendered by the repository's Flutter app connected to an isolated demo instance on an iPhone 15 Pro simulator.
- SQLite lives at
/data/iamllm.dbin theiamllm-dataDocker volume. Container restarts and rebuilds do not erase it. - Do not run
docker compose down -v;-vexplicitly deletes the database volume. - The current release is a single-instance product for one human model. Do not let multiple containers write the same SQLite file.
- PostgreSQL and a cross-process event bus only become necessary for real multi-administrator or horizontal-scaling requirements.
See Operations for backup, restore, upgrades, SSE proxying, and key rotation.
Requires Go 1.25, Node.js 22, and Flutter stable:
cp .env.example .env
set -a; source .env; set +a
make devmake web # build the React console
make build # build the Go binary
make test # run Go, Web, and Flutter checks
make mobile # launch Flutter
make docker # build the container imagecmd/iamllm Go entry point
internal/domain protocol-neutral domain types
internal/application queue, timeout, automation, authentication
internal/protocol OpenAI / Anthropic / Gemini adapters
internal/repository persistence contracts
internal/repository/sqlite SQLite implementation and baseline schema
internal/transport/httpapi HTTP, SSE, and Admin API
web/ React + TypeScript console and Playground
mobile/ Flutter iOS / Android application
| Document | Purpose |
|---|---|
| Getting started | Deploy a first public instance |
| Client integration | Configure OpenAI, Claude Code, OpenCode, and Gemini clients |
| API compatibility | Implement or troubleshoot protocol clients |
| Operations | HTTPS, backup, upgrade, and recovery |
| Architecture | Understand and contribute to the backend |
| Flutter mobile | Run or ship the mobile admin app |
| Roadmap | Product boundaries and future work |
- Use HTTPS for every public instance; do not expose port
8000directly to the internet. - Never share the owner key, administrator token, password, or session secret.
- Managed API keys and device refresh tokens are stored as HMAC hashes; full values are shown only once.
- Raw context can contain source code, local paths, system prompts, and tool arguments. Only trusted administrators should access it.
- Protect database backups as sensitive conversation data.
See the Security policy before reporting a vulnerability.
Issues and pull requests are welcome. Read CONTRIBUTING.md before changing public APIs, persistence, or user flows.






