All endpoints are prefixed with /api.
GET /api/health
Response: {"status": "ok"}
POST /api/upload
Content-Type: multipart/form-data
| Field | Type | Description |
|---|---|---|
file |
File | CSV file (max 50MB) |
Response:
{
"session_id": "abc12345",
"file_name": "data.csv",
"shape": [1000, 15],
"columns": ["col1", "col2"],
"preview": [],
"dataset_info": "Shape: (1000, 15)\nColumns: ..."
}Errors: 400 (invalid CSV), 413 (file too large), 415 (not CSV)
POST /api/sessions
Creates a new session without file upload. Use this for chat-only mode where no dataset is needed.
Response:
{
"session_id": "f9939f6b",
"status": "ok"
}POST /api/chat
Content-Type: application/json
Body:
{
"session_id": "abc12345",
"message": "Perform EDA on this dataset"
}Response:
{
"parts": [
{"type": "thinking", "content": "..."},
{"type": "code", "code": "df.head()", "result": {}},
{"type": "text", "content": "..."}
]
}Note: The WebSocket endpoint is preferred for real-time streaming. This HTTP endpoint is a synchronous fallback.
GET /api/settings
Response:
{
"llm_provider": "openai",
"openai_model": "gpt-4o",
"anthropic_model": "claude-sonnet-4-20250514",
"api_key_set": true
}POST /api/settings
Content-Type: application/json
Body:
{
"llm_provider": "openai",
"api_key": "sk-...",
"openai_model": "gpt-4o"
}List all sessions:
GET /api/sessions
Response:
{
"sessions": [
{"id": "abc12345", "name": "My Analysis", "file_name": "data.csv", "created_at": "..."}
]
}Get session detail (with paginated messages):
GET /api/sessions/{session_id}?limit=200&offset=0
Response includes session, messages, experiments, is_read_only, and pagination.
Delete session:
DELETE /api/sessions/{session_id}
Deletes session, kernel, uploaded file, and all messages.
Rename session:
PATCH /api/sessions/{session_id}
Content-Type: application/json
Body:
{
"name": "My Renamed Analysis"
}Response: {"status": "ok", "name": "My Renamed Analysis"}
Connect to: ws://{host}:{port}/ws/{session_id}
Chat message — trigger an agent run:
{
"type": "chat",
"message": "Perform EDA on this dataset",
"mode": "chat"
}| Field | Type | Description |
|---|---|---|
type |
string | Must be "chat" |
message |
string | User's message text |
mode |
string | Operating mode: "chat" (step-by-step) or "autonomous" (full pipeline). Stored on the session and used by the entry router. |
HITL response — respond to a human-in-the-loop request:
{
"type": "hitl_response",
"response": {
"action": "approve",
"text": ""
}
}| Field | Type | Description |
|---|---|---|
response.action |
string | "approve", "modify", or "reject" |
response.text |
string | Optional feedback text (used with "modify") |
Ping — keepalive response:
{
"type": "pong"
}All events have this structure:
{
"type": "<event_type>",
"data": {},
"stage": "eda",
"timestamp": "2025-02-17T12:00:00Z"
}Event types:
| Type | Data Fields | Description |
|---|---|---|
user_echo |
role, parts, timestamp |
Echo of the user's message after it's saved to the database. Confirms receipt. |
thinking |
content |
Agent's reasoning process (from <thinking> tags) |
decision |
content, importance |
Key decision (importance: "high" or "normal") |
text |
content |
Natural language response |
code |
code, result |
Code execution with result object |
stage_update |
stage, progress |
Pipeline stage transition (progress: 0.0-1.0) |
hitl_request |
question, options, context |
Human-in-the-loop approval gate |
hitl_resume |
action |
HITL response confirmation |
error |
message |
Error notification |
done |
(empty) | Agent turn completed |
ping |
(empty) | Server heartbeat (every 30s) |
Code result structure:
{
"success": true,
"stdout": "Dataset loaded: 1000 rows, 15 columns",
"stderr": "",
"error": null,
"plots": ["base64-encoded-png..."],
"tables": ["<table>...</table>"]
}- Client connects to
/ws/{session_id} - Server validates session exists; sends
error+ close with code4004if not found - Server resets pipeline stage to
idleon reconnect (prevents auto-resuming) - Server starts 30-second heartbeat ping loop
- Client sends
chatmessages; server streams events back - On disconnect, server cancels any running agent task and cleans up HITL waiters
- If the agent is already processing a request, a new
chatmessage returns anerrorevent: "Agent is already processing a request. Please wait." - Agent execution timeout: 5 minutes per message (300 seconds)
- WebSocket connection timeout: 10 seconds on initial connect
- Unexpected disconnect triggers automatic reconnection (3-second delay, client-side)