OpenAI-compatible API
Use an existing OpenAI SDK for chat, generation, and background responses.
- Executor
chat_completion- Best for
- Assistants, drafting, summarization
AI Hub is a self-hosted control plane for local models. Your application sends authenticated requests to the Hub; an outbound-only worker runs the model and returns the result.
Both paths use the same application token, worker network, routing, and execution history. Choose based on the contract your application needs.
Use an existing OpenAI SDK for chat, generation, and background responses.
chat_completionPublish an immutable task and receive schema-validated, durable results.
typed_decision, structured_generationCreate an account and application in the console, then copy the application token when it is shown. AI Hub stores only its digest, so the plaintext token cannot be recovered later.
This gives your client an isolated namespace and application token.
Definitions are versioned and immutable so requests remain reproducible.
Issue a worker credential from Hosting and run the worker beside your model.
Use the OpenAI-compatible API or submit a durable native job.
shellAI_HUB_URL=https://your-hub.example \
AI_HUB_WORKER_TOKEN=aih_... \
AI_MODEL_URL=http://127.0.0.1:8080/v1 \
AI_MODEL=local-model \
bundle exec ruby worker/worker.rbConnect to the remote MCP server with scoped browser authorization. OAuth PKCE identifies the AI Hub user, agent, organization, and approved management capabilities. Application keys remain separate runtime credentials and are not needed in MCP configuration.
shellcodex mcp add ai-hub \
--url https://aihub.mohsal.dev/mcp \
--oauth-resource https://aihub.mohsal.dev/mcp
codex mcp login ai-hub --oauth-client-registration dcrshellclaude mcp add --transport http --scope user \
ai-hub https://aihub.mohsal.dev/mcp
claude mcp login ai-hubjson{
"mcpServers": {
"ai-hub": {
"url": "https://your-hub.example/mcp"
}
}
}APPScreate / update / revoke applicationOAuth-managed lifecycleKEYrotate_application_keyOne-time runtime credentialREADlist_task_definitionsApplication tasks by slugWRITEpublish_typed_decisionPublish immutable Laya questionsREADlist_workersWorker health and capabilitiesRUNsubmit_job / get_jobExecute and retrieve durable workAUDITlist_audit_eventsAgent-aware immutable historyOrganization owners can inspect agents, scopes, grant expiry, denials, and immutable activity—or restrict an agent to selected applications and revoke its grant immediately—from Agents & audit. Each application's Settings screen also provides application-level agent access controls.
A typed decision evaluates an input state against questions stored in the task definition. Questions cannot be replaced by the calling application, which makes the decision contract stable, auditable, and safe to reuse.
choiceSelect one optionReturns the selected label and a probability distribution over every option.
scoreRank criteriaReturns calibrated scores for the criteria defined by the task owner.
noulAnswer yes or noReturns a binary decision with confidence for a focused proposition.
Create the task once from the console or API. The input schema validates each submitted state; the executor configuration defines the questions the Laya worker will ask.
support.route@1curlcurl -X POST https://your-hub.example/api/v1/task_definitions \
-H 'Authorization: Bearer aih_...' \
-H 'Content-Type: application/json' \
-d '{
"task_definition": {
"key": "support.route",
"version": 1,
"executor": "typed_decision",
"instructions": "Route incoming support requests.",
"input_schema": {
"type": "object",
"additionalProperties": false,
"required": ["message"],
"properties": { "message": { "type": "string" } }
},
"executor_config": {
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this request?",
"criteria": {
"billing": "Payments, invoices, charges, or refunds",
"technical": "Product errors or technical help",
"other": "Anything else"
}
}
}
}
}
}'The client supplies only the state being evaluated. AI Hub waits for the durable job to finish and returns the typed answers directly. Send an Idempotency-Key so a retry returns the same decision.
support.route@1curlcurl -X POST https://your-hub.example/api/v1/typed-decisions/support.route@1/evaluate \
-H 'Authorization: Bearer aih_...' \
-H 'Idempotency-Key: ticket-4821-route-v1' \
-H 'Content-Type: application/json' \
-d '{
"input": {
"message": "Please refund the duplicate charge on my card."
}
}'json{
"id": "job_...",
"status": "completed",
"task": "support.route@1",
"decisions": {
"department": {
"type": "choice",
"choice": "billing",
"probabilities": {
"billing": 0.94,
"technical": 0.03,
"other": 0.03
}
}
},
"usage": {
"input_tokens": 51,
"output_tokens": 0,
"total_tokens": 51
}
}202 Accepted with the durable job ID, a Location header, and retrieve_url. Poll that URL with the same application key.The native job endpoint returns immediately. Put the idempotency key in the request body and poll the returned job.
curlcurl -X POST https://your-hub.example/api/v1/jobs \
-H 'Authorization: Bearer aih_...' \
-H 'Content-Type: application/json' \
-d '{
"task": "support.route@1",
"idempotency_key": "ticket-4821-route-v1",
"input": {
"message": "Please refund the duplicate charge on my card."
}
}'A submitted job moves from queued to leased, then to completed. Poll the returned job ID until it reaches a terminal state.
curlcurl https://your-hub.example/api/v1/jobs/job_... \
-H 'Authorization: Bearer aih_...'json{
"id": "job_...",
"status": "completed",
"task": "support.route@1",
"output": {
"answers": {
"department": {
"type": "choice",
"choice": "billing",
"probabilities": {
"billing": 0.94,
"technical": 0.03,
"other": 0.03
}
}
}
}
}A model profile is an immutable chat_completion definition. Its key and version become the public model ID, such as assistant.general@1. The profile controls system instructions; the worker’s AI_MODEL selects the underlying model.
Use the application token as the API key and append /v1 to the Hub origin.
pythonfrom openai import OpenAI
client = OpenAI(
api_key="aih_...",
base_url="https://your-hub.example/v1",
)
response = client.responses.create(
model="assistant.general@1",
input="Summarize this report",
)
print(response.output_text)GET/v1/modelsList model profilesPOST/v1/responsesCreate a responseGET/v1/responses/:idRetrieve a background responsePOST/v1/chat/completionsCreate a chat completionSet background: true when work may outlive one HTTP request. The create call returns a durable job ID immediately.
curlcurl -X POST https://your-hub.example/v1/responses \
-H 'Authorization: Bearer aih_...' \
-H 'Content-Type: application/json' \
-d '{"model":"assistant.general@1","input":"Write a brief","background":true}'
curl https://your-hub.example/v1/responses/job_... \
-H 'Authorization: Bearer aih_...'Use native jobs for structured output, retries, idempotency, explicit versions, and asynchronous execution.
GET/api/v1/task_definitionsList application definitionsPOST/api/v1/task_definitionsPublish an immutable definitionPOST/api/v1/jobsSubmit an idempotent jobGET/api/v1/jobs/:idRetrieve status and outputRetryable failures and expired leases return a job to the queue until its attempt budget is exhausted. Permanent failures end in failed; exhausted jobs end in dead.
Workers advertise executor capabilities and claim only compatible jobs. The official worker creates an Ed25519 device key on first boot and enrolls its public identity with a one-time owner-issued grant.
Read the identity protocol, threat model, and Laya MLX setup.
Every claim creates a separate execution record, including retries. Workers report bounded token counts, model identity, and inference duration. AI Hub measures elapsed Hub time and finalizes every record once.
For the full wire contract and operational details, see the OpenAI integration guide and protocol reference.