🏠 Home ← Docs Index
Open Beta 📖 Interactive Reader Raw .md llms.txt

OpenAI-Compatible API

GoClaw's gateway serves an OpenAI-compatible POST /v1/chat/completions, streaming and non-streaming, so OpenAI SDK clients and tools such as Cursor can talk to the default agent without a GoClaw-specific client.

internal/gateway/openai_compat.go

Architecture

flowchart TD
    REQ["<b>POST /v1/chat/completions</b>"] --> PARSE["<b>Parse OAIRequest</b><br/>• model, messages, stream (max_tokens, temperature ignored)<br/>• Last user message = prompt; earlier messages = history<br/>• Session: openai-compat:&lt;client-ip&gt; (no history written)<br/>• Scope: default agent + channel=openai"]

    PARSE --> SUB{"/subagents command?"}
    SUB -->|Yes| SUBH["<b>HandleSubagentCommand</b><br/>Pass-through"]
    SUB -->|No| STR{"stream?"}

    STR -->|"stream = false"| SYNC["<b>ProcessStream → DrainToResultObserved</b><br/>→ OAIResponse JSON"]
    STR -->|"stream = true"| SSE["<b>ProcessStream events → SSE stream</b><br/>data: {&quot;choices&quot;:[{&quot;delta&quot;:{&quot;content&quot;:…}}]}<br/>data: [DONE]"]

Feature Comparison

# Feature OpenClaw GoClaw Status
1.1 /v1/chat/completions POST ✅ ✅ HandleChatCompletions Done
1.2 Streaming (SSE) ✅ ✅ handleStreamingCompletion — text/event-stream Done
1.3 Non-streaming ✅ ✅ JSON response Done
1.4 Token usage estimation ✅ ✅ ~4 chars/token approximation Done
1.5 Subagent command routing — ✅ HandleSubagentCommand pass-through (/subagents spawn|list|status|stop) GoClaw only
1.6 Session persistence ✅ A session openai-compat:<ip> is created, but no history is written to it: the client sends the conversation in messages Partial
1.7 Error formatting ✅ ✅ UserFacingErrorMessage → OpenAI error JSON Done
1.8 Trust proxy IP — ✅ extractIPFromRequest respects trustProxy config GoClaw only
1.9 Model routing model → provider Uses default agent Partial
1.10 /v1/models list ✅ — TODO
1.11 Function calling pass-through ✅ — TODO
1.12 Embeddings API ✅ — TODO
1.13 Multi-model support ✅ model param → provider — TODO

OpenAI-Compatible Types

Type Fields
OAIRequest model, messages[], stream, max_tokens, temperature (max_tokens and temperature are read and ignored; each message's content must be a string)
OAIResponse id, object, created, model, choices[], usage
OAIStreamChunk id, object, created, model, choices[] (index, delta, finish_reason)
OAIUsage prompt_tokens, completion_tokens, total_tokens

Streaming Format

data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","created":1760000000,"model":"gpt-4o","choices":[{"index":0,"delta":{"role":"assistant","content":"chunk"},"finish_reason":null}]}
data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","created":1760000000,"model":"gpt-4o","choices":[{"index":0,"delta":{"role":"","content":""},"finish_reason":"stop"}]}
data: [DONE]

Two more frames can appear in a stream. data: {"buffer_reset":true} tells the client to discard the text received so far (the reply is being retried). data: {"error":{"message":"…"}} reports a failure and ends the stream: no finish chunk and no data: [DONE] follow it.