Sol API Reference
This document describes the live HTTP APIs behind Sol-37 as they exist on this machine on 2026-04-17.
It is intentionally implementation-grounded:
- endpoint names match the current handlers in
random/bin - examples use the real public and local URI shapes
- limits and edge cases come from the running code, not from a wish-list schema
API Surface Map
Public base:
https://sol.system42.one
Local service origins:
http://127.0.0.1:8895for chathttp://127.0.0.1:8892for knowledge searchhttp://127.0.0.1:8890for logbook transport
Public reverse-proxied routes:
https://sol.system42.one/api/chathttps://sol.system42.one/api/chat/queryhttps://sol.system42.one/api/chat/healthhttps://sol.system42.one/api/chat/historyhttps://sol.system42.one/api/chat/resethttps://sol.system42.one/api/chat/speakhttps://sol.system42.one/api/knowledge/queryhttps://sol.system42.one/api/knowledge/healthhttps://sol.system42.one/api/logbook/messages
Related machine-readable schemas:
https://sol.system42.one/chat-openapi.jsonhttps://sol.system42.one/knowledge-openapi.jsonhttps://sol.system42.one/privacy.html
Related MCP connector surface:
https://sol.system42.one/api/mcp/solhttps://sol.system42.one/api/mcp/sol/health
Authentication:
- none
CORS:
- chat and knowledge explicitly send permissive CORS headers
- logbook supports same-origin browser use and preflight, but should still be treated as a site API rather than a generic public cross-origin service
MCP note:
- Sol also exposes a read-only ChatGPT App / MCP connector that fronts the same chat and knowledge stack.
- The ChatGPT App registration target is the root MCP endpoint
https://sol.system42.one/api/mcp/sol. - The legacy SSE endpoint
https://sol.system42.one/api/mcp/sol/sseexists for compatibility but is not the preferred app-registration URL.
Response Conventions
Patterns used across the stack:
- success responses are JSON unless the endpoint is SSE or audio
- errors usually return
{"error": "<code>"}and sometimesdetail - no route here uses bearer tokens or cookies today
- the chat and knowledge APIs are read-mostly; only chat session reset and logbook message creation mutate state
1. Sol Chat API
Implementation:
- handler:
/home/david/random/bin/sol_chat_api.py - public schema:
https://sol.system42.one/chat-openapi.json
Purpose:
- grounded chat over Sol knowledge
- optional session persistence
- optional image input
- optional page-context grounding
- native live-site-state grounding for greetings, diagnostics, and server/status questions
- speech synthesis
- health and history inspection
1.1 GET /api/chat/query
Use this for simple text-only calls, GPT Action retrieval-style calls, or copy-pasteable direct URLs.
Accepted query parameters:
- query or message
required text prompt
- profile
optional; reasoning, vision, or vision_fast
- session
optional session id
- persist
optional boolean-ish flag; 1 persists history, default is stateless
- page_context
optional JSON-encoded page context object
- page_title
- page_target
- page_content_type
- page_content
- page_heading
repeatable
- page_question
repeatable
Important limits:
- max message length:
12000chars - page context is sanitized and compacted server-side
- stateless requests get an ephemeral generated session id
Real URI examples:
- Public:
https://sol.system42.one/api/chat/query?query=What%20is%20Sol%3F
- Public with session persistence:
https://sol.system42.one/api/chat/query?query=Summarize%20the%20current%20system%20state&session=ops-notebook&persist=1
- Public with page grounding:
https://sol.system42.one/api/chat/query?query=Summarize%20this%20page&page_title=Traffic%20Monitor&page_target=%2Fsite-metrics.html&page_content_type=text%2Fhtml&page_content=The%20page%20shows%20visible%20hits%2C%20telemetry%2C%20and%20service%20status.
- Local:
http://127.0.0.1:8895/api/chat/query?query=What%20is%20Sol%3F
Example:
bash
curl -G 'https://sol.system42.one/api/chat/query' \
--data-urlencode 'query=What is Sol?' \
--data-urlencode 'session=docs-example' \
--data-urlencode 'persist=1'
Typical response shape:
json
{
"message": "Sol is a local-first cognitive annotation system that treats files and logs as the substrate for reasoning.",
"session": "docs-example",
"persisted": true,
"grounded": true,
"retrieval": {
"used": true,
"query": "What is Sol?",
"warning": null,
"grounding_mode": "normal",
"hits": [
{
"rank": 1,
"score": 0.72,
"path": "/home/david/knowledge/sol-readme.md",
"doc_key": "/home/david/knowledge/sol-readme.md#0",
"chunk": 0,
"text": "Sol is a local-first cognitive annotation system..."
}
],
"supplemental": {
"query": "local cognition annotation system files logs reasoning",
"used": true,
"warning": null,
"grounding_mode": "supplemental",
"hits": [
{
"rank": 1,
"score": 0.61,
"path": "/home/david/knowledge/sol-architecture.md",
"doc_key": "/home/david/knowledge/sol-architecture.md#2",
"chunk": 2,
"text": "Sol treats files, logs, and local state as a substrate for reasoning..."
}
],
"source_documents": []
},
"source_documents": [
{
"path": "/home/david/knowledge/sol-readme.md",
"resolved_path": "/home/david/knowledge/sol-readme.md",
"retrieved_snippet": "Sol is a local-first cognitive annotation system...",
"content_mode": "full_current_file",
"snippet_found_in_current_file": true,
"current_file_representation": "raw_file",
"current_file_content": "Sol is a local-first cognitive annotation system..."
}
]
},
"page_context_applied": false,
"history_size": 3,
"fallback_grounding_used": false,
"backend_profile": "reasoning",
"backend_model_id": "DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf",
"image_count": 0,
"query": "What is Sol?",
"cache_hit": false
}
Notes on retrieval metadata:
retrieval.hitsare the ranked embedding matches from the knowledge API.retrieval.supplementalis optional and appears when the chat backend generates a second knowledge query for the same turn and calls the knowledge API again with that query.retrieval.supplemental.queryis generated by the chat backend itself, not supplied by the caller.retrieval.supplementalis additive context; it does not replaceretrieval.queryor the primaryretrieval.hits.retrieval.source_documentsis optional and appears when the chat backend can open the underlying current file for one or more top hits.retrieval.live_site_stateis optional and can appear on ordinary text turns as additional context, not just on diagnostics or greeting probes.- when present,
retrieval.live_site_statecan include traffic totals, top paths, sensor readouts, recent requests, and runtime service status. - for
.htmland.htmfiles,current_file_contentis now derived from rendered visible document text rather than raw markup, andcurrent_file_representationisrendered_html_text - for plain text and markdown files,
current_file_representationis typicallyraw_file snippet_found_in_current_file=truemeans the retrieved snippet was found in the current readable file text, not just in the archived retrieval payload
Creative-prompt behavior:
- open-ended prompts like
tell me a storystill run normal retrieval and can use the current file content as seed material - those turns can also carry the normal live metrics/context bundle; metrics are not removed just because retrieval is present
- the retrieval/context bundle is intended to steer and enrich the generation, not force the response into extractive mode
- the backend prompt now explicitly tells the model to treat injected current-file text as accessible turn context rather than as an unavailable external file
Real-world uses:
- create a shareable URL that answers a narrow question against Sol knowledge
- run a lightweight health probe that still exercises retrieval and generation
- ask for current server health, traffic, or sensor state and get a live-site-state answer instead of archive-heavy retrieval
- summarize the page currently open inside the shell without using a POST body
- wire a GPT Action or bookmarklet that can only issue GET requests
Failure modes:
400 {"error":"missing_query"}400 {"error":"message_too_long"}400 {"error":"invalid_page_context:..."}in JSON-encoded page context failures502 {"error":"chat_failed","detail":"..."}when retrieval or model execution fails
1.2 POST /api/chat
Use this for full chat turns, multimodal turns, SSE streaming, or richer page context.
Request body fields:
- message
optional if images is supplied
- session
optional
- persist
boolean, default effectively true for POST requests
- stream
boolean; if true the response is SSE
- profile
optional; reasoning, vision, vision_fast
- page_context
object with:
- target
- title
- content_type
- headings
- suggested_questions
- content
- images
list of image objects
- name
- mime_type
- data_url
Image requirements:
- image input must currently be a base64 data URL
- max images per request:
3by default - max bytes per image:
10485760 - non-data-URL image inputs are rejected with
invalid_image_data
Real URI examples:
- Public JSON turn:
https://sol.system42.one/api/chat
- Local JSON turn:
http://127.0.0.1:8895/api/chat
Example: standard JSON chat turn
bash
curl 'https://sol.system42.one/api/chat' \
-H 'Content-Type: application/json' \
-d '{
"message": "Give me a grounded two-paragraph explanation of Sol.",
"session": "docs-post-example",
"persist": true,
"stream": false
}'
Example: page-aware assistant turn
bash
curl 'https://sol.system42.one/api/chat' \
-H 'Content-Type: application/json' \
-d '{
"message": "Summarize this page and suggest two follow-up questions.",
"session": "page-summary-demo",
"persist": false,
"page_context": {
"target": "/site-metrics.html",
"title": "Traffic Monitor",
"content_type": "text/html",
"headings": ["Visible Hits", "Archive Counters", "Telemetry"],
"suggested_questions": ["What changed recently?", "Are any services down?"],
"content": "This page shows current visible traffic, archive counters, and mirrored service telemetry."
}
}'
Example: multimodal POST
bash
curl 'https://sol.system42.one/api/chat' \
-H 'Content-Type: application/json' \
-d '{
"message": "Describe the visible scene and call out anything unusual.",
"profile": "vision_fast",
"persist": false,
"images": [
{
"name": "dashboard-camera.jpg",
"mime_type": "image/jpeg",
"data_url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ..."
}
]
}'
Example: SSE streaming
bash
curl 'https://sol.system42.one/api/chat' \
-H 'Content-Type: application/json' \
-H 'Accept: text/event-stream' \
-d '{
"message": "Explain how the knowledge API and chat API fit together.",
"session": "stream-demo",
"stream": true
}'
Streaming event types:
statusdeltadoneerror
Real-world uses:
- power the
/chatpage - power the floating desktop assistant
- ask page-specific questions against the current shell surface
- caption screenshots or dashboard camera frames
- run a stateless classification/explanation turn without polluting saved history
1.3 GET /api/chat/health
Use this to verify chat runtime readiness, model routing, and voice availability.
Real URI examples:
- Public:
https://sol.system42.one/api/chat/health
- Local:
http://127.0.0.1:8895/api/chat/health
Example:
bash
curl 'https://sol.system42.one/api/chat/health'
Current live response fields include:
okstrict_groundingbackend_configuredbackend_base_urlbackend_model_idbackend_profilevoice_availabletts_cache_enabledstackbackends
Real-world uses:
- confirm whether the reasoning lane is alive before routing users into
/chat - inspect whether voice playback is available
- show a dashboard card with active model and managed backends
1.4 GET /api/chat/history
Loads sanitized message history for a persisted session.
Required query parameter:
session
Real URI examples:
- Public:
https://sol.system42.one/api/chat/history?session=docs-example
- Local:
http://127.0.0.1:8895/api/chat/history?session=docs-example
Example:
bash
curl -G 'https://sol.system42.one/api/chat/history' \
--data-urlencode 'session=docs-example'
Response shape:
json
{
"session": "docs-example",
"messages": [
{"role": "system", "content": "..."},
{"role": "user", "content": "What is Sol?"},
{"role": "assistant", "content": "Sol is a local-first cognitive annotation system..."}
],
"assistant_debug": [
{
"grounded": true,
"fallback_grounding_used": false,
"page_context_applied": false,
"backend_profile": "reasoning",
"backend_model_id": "DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf"
}
]
}
1.5 POST /api/chat/reset
Resets a persisted session.
Request body:
session
Real URI examples:
- Public:
https://sol.system42.one/api/chat/reset
- Local:
http://127.0.0.1:8895/api/chat/reset
Example:
bash
curl 'https://sol.system42.one/api/chat/reset' \
-H 'Content-Type: application/json' \
-d '{"session":"docs-example"}'
Response:
json
{"ok": true, "session": "docs-example"}
1.6 GET or POST /api/chat/speak
Synthesizes reply text to MP3 using the configured voice backend.
Input:
- GET query parameter
text - or POST JSON body
{"text":"..."}
Output:
audio/mpeg
Real URI examples:
- Public GET:
https://sol.system42.one/api/chat/speak?text=Hello%20from%20Sol
- Local GET:
http://127.0.0.1:8895/api/chat/speak?text=Hello%20from%20Sol
- Public POST target:
https://sol.system42.one/api/chat/speak
Examples:
bash
curl -L 'https://sol.system42.one/api/chat/speak?text=Hello%20from%20Sol' \
--output sol-hello.mp3
bash
curl 'https://sol.system42.one/api/chat/speak' \
-H 'Content-Type: application/json' \
-d '{"text":"Read this aloud in Sol voice."}' \
--output sol-voice.mp3
Behavior notes:
- the server caches generated speech by prompt text and voice settings
- GET can stream bytes directly
- POST returns the synthesized bytes in one response
Common errors:
400 {"error":"missing_text"}400 {"error":"text_too_long"}503 {"error":"voice_unavailable"}502 {"error":"voice_failed:..."}or related voice backend failures
2. Knowledge Query API
Implementation:
- handler:
/home/david/random/bin/knowledge_query_api.py - public schema:
https://sol.system42.one/knowledge-openapi.json
Purpose:
- read-only semantic retrieval over the Sol knowledge cache
- no mutation
- intended as a retrieval primitive, not a final-answer API
Backing behavior:
- loads a cached embedding index from disk
- auto-reloads when the cache file mtime changes
- can fall back to
local-hashif the primary backend fails or times out - rejects
POST /querywith405
2.1 GET /api/knowledge/query
Required query parameters:
query
Optional query parameters:
- top_k
integer, clamped to 1..12, default 5
Hard limits:
- query length max:
2000chars
Real URI examples:
- Public:
https://sol.system42.one/api/knowledge/query?query=How%20does%20the%20knowledge%20API%20work%3F&top_k=2
- Local:
http://127.0.0.1:8892/api/knowledge/query?query=How%20does%20the%20knowledge%20API%20work%3F&top_k=2
Examples:
bash
curl -G 'https://sol.system42.one/api/knowledge/query' \
--data-urlencode 'query=How does the knowledge API work?' \
--data-urlencode 'top_k=2'
bash
python3 - <<'PY'
import json, urllib.parse, urllib.request
base = 'https://sol.system42.one/api/knowledge/query'
params = urllib.parse.urlencode({'query': 'MasterBot voice playback trials', 'top_k': 3})
with urllib.request.urlopen(f'{base}?{params}') as r:
data = json.load(r)
print(json.dumps(data, indent=2)[:2000])
PY
Typical response shape:
json
{
"query": "How does the knowledge API work?",
"top_k": 2,
"backend": "openai",
"cache_path": "/home/david/logs/sol_embeddings.openai.pkl",
"warning": null,
"results": [
{
"rank": 1,
"score": 0.83,
"path": "/home/david/knowledge/sol-site-server.md",
"chunk": 4,
"doc_key": "/home/david/knowledge/sol-site-server.md#4",
"text": "Serves a read-only semantic query endpoint..."
}
]
}
Fallback semantics:
- when the primary backend fails or times out, the response may include:
requested_backendwarning- example warning values:
primary_backend_failed:SomeErrorprimary_backend_timeout:8.0s
Real-world uses:
- power GPT Actions that need retrieval but not synthesis
- inspect relevant source chunks before asking the chat API to summarize them
- build search boxes inside the shell
- do linkable knowledge lookups with plain query-string URLs
Common errors:
400 {"error":"missing_query"}400 {"error":"invalid_top_k"}400 {"error":"query_too_long"}503 {"error":"cache_missing","detail":"..."}502 {"error":"search_failed","detail":"..."}
Method rule:
POST /api/knowledge/queryreturns405 Method Not AllowedAllow: GET, OPTIONS
2.2 GET /api/knowledge/health
Use this to check that the index is loaded and inspect query-cache metadata.
Real URI examples:
- Public:
https://sol.system42.one/api/knowledge/health
- Local:
http://127.0.0.1:8892/api/knowledge/health
Example:
bash
curl 'https://sol.system42.one/api/knowledge/health'
Current live response fields:
okbackendcache_pathknowledge_dirdocsquery_cache_pathquery_cache_entries
Important caveat:
healthonly proves the cache is loaded- it does not guarantee that live query embeddings will succeed against the primary backend
3. Public Logbook API
Implementation:
- handler:
/home/david/random/bin/public_logbook_api.py - transport helpers:
/home/david/random/bin/logbook_irc_common.py
Purpose:
- read and append public IRC-backed logbook messages for the Sol shell
Public route shape:
- public:
https://sol.system42.one/api/logbook/messages - local service:
http://127.0.0.1:8890/messages
Allowed channels:
public-logbookarchive-watchcivilization-sim
Unknown channels are normalized back to public-logbook.
3.1 GET /api/logbook/messages
Query parameters:
- limit
optional, default 80, clamped to 1..250
- channel
optional, default public-logbook
Real URI examples:
- Public latest 20:
https://sol.system42.one/api/logbook/messages?limit=20
- Public alternate channel:
https://sol.system42.one/api/logbook/messages?channel=archive-watch&limit=50
- Local:
http://127.0.0.1:8890/messages?limit=2
Example:
bash
curl -G 'https://sol.system42.one/api/logbook/messages' \
--data-urlencode 'channel=public-logbook' \
--data-urlencode 'limit=10'
Typical response:
json
{
"messages": [
{
"id": "1774482631974-f5d49e",
"name": "davidlones",
"message": "still alive",
"created_at": "2026-03-25T23:50:31.974201Z",
"channel": "public-logbook"
}
],
"limit": 10,
"channel": "public-logbook"
}
Real-world uses:
- render the public logbook program inside the shell
- build a “latest transmissions” widget
- watch a specific public channel without joining IRC directly
3.2 POST /api/logbook/messages
Creates a logbook message by sending through the IRC-backed transport.
JSON body:
- name
- message
- channel
optional, defaults to public-logbook
Request size rules:
Content-Lengthmust be1..8192- invalid JSON is rejected
Rate limiting:
- per-client IP
4requests per300seconds
Real URI examples:
- Public:
https://sol.system42.one/api/logbook/messages
- Local:
http://127.0.0.1:8890/messages
Example:
bash
curl 'https://sol.system42.one/api/logbook/messages' \
-H 'Content-Type: application/json' \
-d '{
"name": "Sol37",
"message": "Archive sync complete.",
"channel": "archive-watch"
}'
Success response:
json
{
"ok": true,
"message": {
"name": "Sol37",
"message": "Archive sync complete.",
"channel": "archive-watch"
}
}
Common errors:
400 {"error":"invalid_length"}400 {"error":"invalid_json"}400 {"error":"name_required"}400 {"error":"message_required"}409 {"error":"name_in_use"}429 {"error":"rate_limited"}502 {"error":"..."}
Real-world uses:
- allow the in-browser logbook client to post messages
- bridge lightweight site events into public channels
- provide a public-but-rate-limited append-only note path without exposing direct IRC credentials
4. Internal-Only Related API
local_dashboard_api.py exists and is important to the Sol stack, but it is not part of the general public external API contract in the same way as chat, knowledge, and logbook.
It should currently be treated as an internal service dependency for:
- dashboard telemetry
- camera captioning
- local launch actions
- service console state
- LAN/local gating behavior
If you want that surfaced as a stable public API, it should be documented separately as an internal operations API first, then promoted deliberately.
5. Real Integration Recipes
Recipe: direct retrieval, then grounded answer
1. Call:
GET https://sol.system42.one/api/knowledge/query?query=How%20does%20the%20knowledge%20API%20work%3F&top_k=3
2. Inspect the returned results
3. Call:
POST https://sol.system42.one/api/chat
4. Ask for a synthesis or explanation if you want a human-readable answer
Why this is useful:
- the knowledge API gives raw evidence
- the chat API gives interpretation, synthesis, and conversational framing
Recipe: page-aware shell assistant
- Capture the current shell page title, target, headings, and compact text
- Send them in
page_contexttoPOST /api/chat - Ask for summary, explanation, or navigation help
Why this is useful:
- it keeps the assistant anchored in the current UI state
- it avoids forcing retrieval when the page itself already contains the needed context
Recipe: persistent multi-turn operator session
1. Start with:
POST /api/chat using {"session":"ops-1","persist":true}
2. Continue with the same session id
3. Read back state with:
GET /api/chat/history?session=ops-1
4. Reset with:
POST /api/chat/reset
Recipe: voice playback for a finished assistant answer
- Get a response from
/api/chator/api/chat/query - Take the
messagetext - Feed it to
/api/chat/speak - Save the MP3 or stream it directly to the browser
Recipe: public logbook monitor
1. Poll:
GET /api/logbook/messages?channel=public-logbook&limit=20
2. Render newest entries
3. Post new lines only when needed, respecting the rate limit
6. Verification Notes
These docs were checked against the current implementation and local contract tests:
python3 /home/david/random/bin/check_knowledge_query_api_contract.pypython3 /home/david/random/bin/check_sol_chat_api_contract.py
They also reflect current live local responses from:
http://127.0.0.1:8895/api/chat/healthhttp://127.0.0.1:8892/api/knowledge/healthhttp://127.0.0.1:8890/messages?limit=2