Serve
crowe serve runs the agent as an OpenAI-compatible HTTP API on your machine. Any OpenAI client, the official SDK, LangChain, Cortex, can drive the same agent loop the console uses by pointing its base URL at the bridge. Each request becomes one headless turn; the bridge translates the request in and the event stream out.
Start it
$ crowe serve
Crowe Logic OpenAI bridge → http://127.0.0.1:8011/v1 (Ctrl+C to stop)
INFO: Uvicorn running on http://127.0.0.1:8011 (Press CTRL+C to quit)
| Flag | Meaning |
|---|---|
--host TEXT | Bind host. Default 127.0.0.1, or CROWE_BRIDGE_HOST. |
--port INTEGER | Bind port. Default 8011, or CROWE_BRIDGE_PORT. |
The bridge does not check an API key. Clients require one, so pass any string. Keep it bound to loopback unless you put your own authentication in front of it.
Endpoints
| Route | Returns |
|---|---|
GET /healthz | {"status":"ok","service":"crowe-logic-bridge"} |
GET /v1/models | An OpenAI model list: every selector from the model table except CroweLM Auto, each owned_by: crowe-logic. |
POST /v1/chat/completions | A chat completion, streamed or whole. |
$ curl -s http://127.0.0.1:8011/v1/models
{"object": "list", "data": [
{"id": "crowelm", "object": "model", "created": 1788249158, "owned_by": "crowe-logic"},
{"id": "crowelm-high", "object": "model", "created": 1788249158, "owned_by": "crowe-logic"},
{"id": "crowelm-max", "object": "model", "created": 1788249158, "owned_by": "crowe-logic"},
{"id": "crowelm-zenith", "object": "model", "created": 1788249158, "owned_by": "crowe-logic"},
...
]}
The request
The bridge reads four fields of the chat completions body and ignores the rest; each tier's own runtime parameters apply, so temperature, max_tokens and client-side tools have no effect.
messages, required. Rolessystem,userandassistant. A system message is folded into a user turn. Content may be a string or a list of text parts, which are joined. Empty entries are dropped, and the last message must be a user turn, or the request is refused with 400.model, optional. Any id from/v1/models. Defaultcrowelm.stream, optional.falseby default.user, optional. Used as the session tag for the turn. Defaultcrowe-bridge.
curl
curl -s http://127.0.0.1:8011/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "crowelm-flash",
"messages": [{"role": "user", "content": "Name the engine you run on."}]
}'
The answer is a chat.completion object with one choice and finish_reason: stop. Usage counts are approximate: prompt_tokens is 0 and completion_tokens is a word count of the answer.
{"id": "chatcmpl-...", "object": "chat.completion", "created": 1788249158, "model": "crowelm-flash",
"choices": [{"index": 0, "message": {"role": "assistant", "content": "..."}, "finish_reason": "stop"}],
"usage": {"prompt_tokens": 0, "completion_tokens": N, "total_tokens": N}}
With "stream": true the response is text/event-stream: chat.completion.chunk objects with delta.content, opened by one chunk with empty content as the role marker, closed by a chunk with finish_reason: stop and then data: [DONE]. A tool call the agent makes appears inline in the content as _[tool: name ok]_; reasoning deltas are not forwarded. An error mid-stream arrives as content of the form [error: message] followed by the stop chunk.
Python, with the OpenAI client
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8011/v1", api_key="not-checked")
reply = client.chat.completions.create(
model="crowelm",
messages=[{"role": "user", "content": "Name the engine you run on."}],
)
print(reply.choices[0].message.content)
for chunk in client.chat.completions.create(
model="crowelm-zenith",
messages=[{"role": "user", "content": "Outline a retry policy for a flaky upstream."}],
stream=True,
):
print(chunk.choices[0].delta.content or "", end="", flush=True)
Errors
400 when messages is missing, empty, or does not end with a user turn. 503 when the turn could not find a runtime; the detail reads: "This bridge runs the model on your own provider keys or a Crowe ID sign-in, and found neither. Put keys in .env or run crowe login; the free tier is available in crowe chat." 500 for any other provider error, with the headless error message as the detail.