Skip to main content

Session API

Xiaohe Agent exposes a REST Session API for programmatic agent workflows. The API hosts real CLI backends (for example Claude / Kimi) — it is not a separate agent SDK.

Start a local control plane with the OS service lifecycle commands:

xiaohe server install
xiaohe server start

Default local base (typical): http://127.0.0.1:8110. Hosted Session Web: https://agent.xiaohe.team (see the download page).

Authentication

When authentication is enabled, every /v1/* request (except health / public UI paths) needs a Bearer token:

Authorization: Bearer <api-key|access-jwt>

Issue and manage keys on the control-plane host:

xiaohe server pair # one-shot: mint a key, print apiBase + workspace_path
xiaohe keys issue --tenant local --label mac
xiaohe keys list
xiaohe keys revoke <id|prefix>

For EventSource / SSE (which cannot send Bearer headers), append the key as a query parameter:

GET /v1/sessions/{id}/events?access_token=<key>&after=0&follow=true

Core endpoints

MethodPathPurpose
POST/v1/sessionsCreate a hosted session
GET/v1/sessions/{id}Session status
POST/v1/sessions/{id}/messagesSend a user message
GET/v1/sessions/{id}/eventsSSE event stream
POST/v1/sessions/{id}/approvalsApprove / reject a pending action
POST/v1/sessions/{id}/cancelCancel an in-flight reply
DELETE/v1/sessions/{id}End a session
GET/v1/meCaller identity / workspace hints
GET/PUT/v1/providerList / switch the Claude LLM provider
GET/PUT/v1/voice/providerList / switch TTS/STT provider

Create a session

POST /v1/sessions

{
"tenant_id": "demo",
"backend": "claude",
"skill_ids": ["demo.echo"],
"message": "optional first turn",
"workspace_path": "/absolute/path/to/project",
"persistent": false
}
  • backendsclaude (default) | kimi | codex | cursor | fake (local testing). Sessions proxy the real CLIs; claude uses the Agent SDK with token streaming and --resume across turns.
  • workspace_path — use the caller's absolute project path as the working directory. Omit for a sandboxed workspace.
  • persistent — keep a long-lived host process for the session (instead of per-turn).
  • skill_ids — restrict which product skills the session may load.

Message + events

Send turns with POST /v1/sessions/{id}/messages:

{"content": "Hello"}

Progress arrives over SSE — reconnect with after=<last_event_seq> to resume:

GET /v1/sessions/{id}/events?after=0&follow=true

Attachments

Upload files up to 50 MiB:

  • POST /v1/sessions/{id}/attachments — multipart field file{id, name, mime, size, kind}
  • GET /v1/sessions/{id}/attachments — list metadata
  • GET /v1/sessions/{id}/attachments/{att_id} — download bytes

Inbound attachments are appended to the prompt as local paths (agent Read / image tools).

Transcript

GET /v1/sessions/{id}/messages returns stable chat bubbles (source of truth for UI reopen). Optional paging (newest-first window): limit (1–500), before_created_at + before_msg_id keyset cursor; omit limit for the full transcript.

Approvals (human-in-the-loop)

POST /v1/sessions/{id}/approvals

{"approval_id": "...", "approved": true, "note": ""}

When the agent needs a decision, the session enters waiting_approval and an approval_required event is emitted on SSE.

Workspaces

  • GET /v1/me — suggested workspace_path for the caller
  • GET /v1/workspaces — list registered workspaces for the key's tenant
  • POST /v1/workspaces — ensure / register a workspace

Model Gateway

Xiaohe also exposes a unified model gateway — one API key to talk to DeepSeek, Kimi and Claude through a single Anthropic-compatible endpoint. No per-provider accounts or SDKs needed on the client side.

Base: https://api.xiaohe.team/v1 (Anthropic Messages API)
MethodPathPurpose
POST/v1/messagesChat completion (Anthropic Messages API)
GET/v1/modelsList routed models

Send the gateway key as x-api-key (or Authorization: Bearer …), pick any routed model, and the gateway forwards to the configured provider:

{
"model": "deepseek-v4-pro",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello"}]
}

Routed models include DeepSeek (deepseek-v4-pro, deepseek-chat, deepseek-reasoner), Kimi (kimi-k2.6, kimi-for-coding) and Anthropic (claude-opus-5, claude-sonnet-5, claude-haiku-4-5, claude-fable-5). Usage is recorded per request and billed by token — costs are estimated from the built-in model pricing table.

TTS / STT

Voice is available to the hosted Session API:

  • POST /v1/tts — text → audio (audio/mpeg). Body { "text", "voice", "tenant_id" }. Voices: zh_male_m191_uranus_bigtts (经典男声), zh_female_xiaohe_uranus_bigtts (经典女声), ICL_uranus_zh_female_yuanqitianmei_tob (阳光甜妹). Max 2000 chars.
  • POST /v1/stt — multipart file{"text": "..."} (Doubao flash ASR).