HTTP API
Everything the web app and the CLI do goes through LangAlpha’s HTTP API, and you can call it from your own code. This page covers how the API behaves in general. A full endpoint reference is coming; until then, the CLI’s source is a compact, working example of the routes most people need.
Base URL
Section titled “Base URL”Every route lives under /api/v1 on your LangAlpha server, for example http://localhost:8000/api/v1/threads on a default self-hosted install.
Requests and errors
Section titled “Requests and errors”Requests and responses are JSON. An error comes back with an HTTP status and a detail field, which is one of:
- a sentence, such as
{"detail": "Thread not found"}; - an object with a
messageand a machine-readabletypeorcode, such asinsufficient_scope; - for a request that does not validate (422), a list of the problems found.
| Status | Meaning |
|---|---|
| 400, 422 | The request is invalid. |
| 401 | No credential, or one the server refuses. |
| 403 | The credential may not do this. |
| 404 | Not found. |
| 409 | A conflict with the current state, such as answering a thread that is waiting for nothing. |
| 429 | Too many requests; the Retry-After header says how many seconds to wait. |
| 503 | The server cannot answer right now; retry after Retry-After when it is set. |
Turns stream as server-sent events
Section titled “Turns stream as server-sent events”Sending a message runs a turn, and the response is a stream of server-sent events (text/event-stream) that lasts as long as the turn:
POST /api/v1/threads/messagesstarts a new thread. The body names aworkspace_idandmessages, a list holding one{"role": "user", "content": "..."}, and optionally anllm_model.POST /api/v1/threads/{thread_id}/messagessends to an existing thread. If a turn is running there, the message steers it.
Each event has a name, a numbered id, and JSON data. Among the first is metadata, which names the thread and the run. message_chunk events carry the reply as it is written, and tool calls and their results come as events of their own. The stream ends on interrupt when the agent waits for an answer, on error or retry when the turn fails (each says whether to retry the run or send again, in recovery), and on run_end with the run’s outcome. Comment lines keep an idle connection open every 15 seconds.
Reconnecting and reading back
Section titled “Reconnecting and reading back”Closing the connection does not stop the turn; it keeps running on the server.
GET /api/v1/threads/{thread_id}/messages/streamreconnects to the thread’s latest turn, or to one run with?run_id=. Pass the last event id you received as theLast-Event-IDheader (or?last_event_id=) and the stream resumes after it, without repeating what you already have.GET /api/v1/threads/{thread_id}/messages/replayreads back a thread’s turns, finished ones included, as the same kind of events.POST /api/v1/threads/{thread_id}/cancelstops the running turn.
Safe retries with a request key
Section titled “Safe retries with a request key”A send can carry a request_key, a UUID you generate for that one message. If the connection drops before you know whether the send arrived, send the same request again with the same key: the server recognizes it and connects you to the run the first copy started, rather than starting a second turn. A send without a key is never deduplicated.