Skip to content

API Reference

Two SSE channels serve different purposes:

Opened per chat request, closes when the response is complete. If the user switches conversations mid-stream, the client stops rendering but continues draining the stream so the server finishes processing and persists the full response. The explicit Stop button (double-tap) still aborts and prevents persistence.

Event flow: message_id (user) → context → thinking → content → tool_call → tool_result → image_generated → metrics → done → message_id (assistant)

Also emits dom_update events for UI changes triggered by tool execution, and status events for retry notifications and errors. The message_id event assigns database IDs to streaming-created DOM elements, enabling edit buttons without a page refresh.

Same SSE format as POST /api/chat, but re-attempts the last user message without re-persisting it. Used by the Retry button shown when a turn fails with no assistant content. The server retrieves the last user message from the database and passes { retry: true } to the entity loop, which skips user message insertion and avoids double-appending the message to the LLM context.

Opened on page load, stays open indefinitely. Server can push events at any time.

Used for: auto-title updates, background operations, and any UI changes that happen outside of a chat request.

Managed by EventBroadcaster singleton in src/server/broadcaster.ts.

MethodPathDescription
GET/App shell HTML
GET/c/:idConversation page
GET/healthIdentity + version JSON (name, version, version_base, version_suffix, is_staging, is_prerelease, flavor, entity_core_version, started_at). Container HEALTHCHECK ignores the body and only reads r.ok.
GET/api/eventsPersistent SSE channel
GET/fragments/*HTML fragments for HTMX
MethodPathDescription
POST/api/chatSend message, stream response (SSE)
POST/api/chat/retryRetry failed turn without re-persisting user message (SSE)

Chat request body: { "conversationId": string, "message": string, "attachmentId"?: string, "deviceType"?: "desktop"|"mobile" }. The deviceType field is used by the Situational Awareness system.

MethodPathDescription
GET/api/conversationsList conversations
POST/api/conversationsCreate conversation
GET/api/conversations/:id/messagesGet messages
GET/api/conversations/:id/messages/paginatedGet paginated messages (query: before, limit)
GET/api/conversations/:id/contextGet all context snapshots
GET/api/conversations/:id/context/latestGet latest context snapshot
PATCH/api/conversations/:id/titleUpdate title (auto-deduplicates with numeric suffix)
DELETE/api/conversations/:idDelete conversation
DELETE/api/conversationsBatch delete conversations
MethodPathDescription
PUT/api/messages/:idUpdate message content
MethodPathDescription
POST/api/memory/consolidate/:granularityTrigger memory consolidation
POST/api/memories/consolidation/runRun catch-up consolidation for all missed periods
POST/api/memories/:granularity/:dateSave edited memory (writes local file, pushes MCP update, reindexes RAG)
POST/api/memories/significant/createCreate new significant memory
DELETE/api/memories/significant/:filenameDelete a significant memory (removes file, clears RAG index)
MethodPathDescription
POST/api/settings/file/:dir/:filenameSave core prompt file
POST/api/settings/customCreate custom identity file
DELETE/api/settings/custom/:filenameDelete custom identity file
MethodPathDescription
POST/api/entity-core/consolidation/runRun catch-up memory consolidation (delegates to entity-core)
POST/api/entity-core/syncManually trigger identity pull then push sync
POST/api/entity-core/actions/embed-memoriesRun embed-existing-memories script in entity-core
MethodPathDescription
GET/api/snapshotsList snapshots (requires MCP)
POST/api/snapshots/createCreate manual snapshot
POST/api/snapshots/:id/restoreRestore from snapshot
MethodPathDescription
GET/api/lorebooksList all lorebooks
POST/api/lorebooksCreate new lorebook
GET/api/lorebooks/:idGet specific lorebook
PUT/api/lorebooks/:idUpdate lorebook
DELETE/api/lorebooks/:idDelete lorebook
GET/api/lorebooks/:id/entriesList lorebook entries
POST/api/lorebooks/:id/entriesCreate lorebook entry
PUT/api/lorebooks/:id/entries/:entryIdUpdate lorebook entry
DELETE/api/lorebooks/:id/entries/:entryIdDelete lorebook entry
DELETE/api/lorebooks/state/:conversationIdReset lorebook state
POST/api/lorebooks/import-sillytavernImport SillyTavern lorebook (multipart JSON file)
MethodPathDescription
GET/api/graphGet full knowledge graph (nodes, edges, stats)
POST/api/graph/nodesCreate graph node (auto-generates embedding)
POST/api/graph/edgesCreate graph edge
PUT/api/graph/nodes/:idUpdate graph node (re-generates embedding)
PUT/api/graph/edges/:idUpdate graph edge
DELETE/api/graph/nodes/:idDelete graph node (cascades to edges)
DELETE/api/graph/edges/:idDelete graph edge
MethodPathDescription
GET/api/backgroundsList uploaded backgrounds
POST/api/backgroundsUpload background image
DELETE/api/backgrounds/:filenameDelete background image
GET/backgrounds/:filenameServe background image file
MethodPathDescription
GET/api/appearance-settingsGet current appearance settings
POST/api/appearance-settingsSave appearance settings

Settings stored in .psycheros/appearance-settings.json. Shape: { "preset": string|null, "customAccent": string|null, "bgImage": string|null, "bgBlur": number, "bgOverlayOpacity": number, "glassEnabled": boolean }. Defaults to violet preset with no background.

MethodPathDescription
GET/api/vaultList vault documents
POST/api/vaultUpload vault document (multipart: document, title, scope)
GET/api/vault/:idGet vault document metadata
PUT/api/vault/:idUpdate vault document title/content
DELETE/api/vault/:idDelete vault document
POST/api/vault/searchSearch vault by query
MethodPathDescription
GET/api/general-settingsGet general settings (entity name, user name)
POST/api/general-settingsSave general settings

Settings stored in .psycheros/general-settings.json. Defaults: { "entityName": "Assistant", "userName": "You" }.

MethodPathDescription
GET/api/sa-settingsGet current SA settings
POST/api/sa-settingsSave SA settings

Settings stored in .psycheros/sa-settings.json. Shape: { "enabled": boolean }. Defaults to { "enabled": true }. When enabled, the entity receives a <situational_awareness> XML block in its system message each turn containing the current conversation, last user message (cross-conversation, excluding Pulses), user device type, and connected devices (Lovense, Intiface, home).

MethodPathDescription
GET/api/llm-settingsGet all profiles and active ID (API keys masked)
POST/api/llm-settingsBulk save (used by delete operations)
POST/api/llm-settings/profileAdd or update a single profile (server-side merge)
POST/api/llm-settings/set-activeSet active profile by ID (triggers entity-core restart if connected)
POST/api/llm-settings/resetReset to environment variable defaults
POST/api/llm-settings/testTest connection for a profile (accepts partial profile)
GET/fragments/settings/llmHub view (card grid of all profiles)
GET/fragments/settings/llm/newNew profile edit form
GET/fragments/settings/llm/:idEdit existing profile form
MethodPathDescription
GET/api/web-search-settingsGet current web search settings (API keys masked)
POST/api/web-search-settingsSave web search settings
POST/api/web-search-settings/resetReset to environment variable defaults
MethodPathDescription
GET/api/discord-settingsGet current Discord settings (bot token masked)
POST/api/discord-settingsSave Discord settings
POST/api/discord-settings/resetReset to environment variable defaults

Settings stored in .psycheros/discord-settings.json. Shape: { "enabled": boolean, "botToken": string, "defaultChannelId": string }.

MethodPathDescription
GET/api/home-settingsGet current home device settings
POST/api/home-settingsSave home device settings and hot-reload tool registry

Settings stored in .psycheros/home-settings.json. Shape: { "devices": Array<{ name: string, type: string, address: string, enabled: boolean }> }. The control_device tool is auto-enabled when any device has enabled: true.

MethodPathDescription
GET/api/lovense-settingsGet current Lovense connection settings
POST/api/lovense-settingsSave Lovense settings and hot-reload tool registry
POST/api/lovense-settings/testTest connection to Lovense Connect bridge, returns connected toys
GET/api/lovense-statusQuick connection check for header icon (3s timeout), returns { connected, toy? }

Settings stored in .psycheros/lovense-settings.json. Shape: { "enabled": boolean, "connection": { "domain": string, "port": number, "secure": boolean } }. Supports two modes: LAN Mode (port 20010, HTTP) and Game Mode (port 34568 mobile / 30010 PC, HTTPS). Domain format: 192-168-X-X.lovense.club (dashes, not dots). The control_lovense tool is auto-enabled when enabled: true and domain is set. Settings page auto-reloads after save.

MethodPathDescription
GET/api/buttplug-settingsGet current Buttplug/WebSocket settings
POST/api/buttplug-settingsSave Buttplug settings and hot-reload tool registry
POST/api/buttplug-settings/testTest connection to Intiface Central, returns discovered devices
GET/api/buttplug-statusQuick connection check for header icon (2s timeout), returns { connected, deviceCount?, devices? }

Settings stored in .psycheros/buttplug-settings.json. Shape: { "enabled": boolean, "websocketUrl": string }. Connects to Intiface Central over WebSocket (default ws://127.0.0.1:12345). The control_toy tool is auto-enabled when enabled: true. Both Lovense and Buttplug status are polled for the intimacy heart icon in the header.

MethodPathDescription
GET/api/image-gen-settingsGet current image generator settings (API keys masked)
POST/api/image-gen-settingsSave image generator settings and hot-reload tool registry
POST/api/image-gen-settings/resetReset to defaults (empty generators list)

Settings stored in .psycheros/image-gen-settings.json. Shape: { "generators": Array<ImageGenConfig>, "captioning": CaptioningSettings } where each generator config has id, name, description, enabled, nsfw, provider (openrouter/gemini), and provider-specific settings (API keys, model, etc.). Captioning settings have enabled, provider (gemini/openrouter), and provider-specific settings (API key, model). The generate_image tool is auto-enabled when any generator has enabled: true. The describe_image tool is auto-enabled when captioning has a provider configured.

The POST handler supports partial updates: if the body contains only a captioning field (no generators), only the captioning settings are merged into existing settings. This prevents the common pattern of fetching masked settings and writing them back from corrupting API keys.

MethodPathDescription
GET/api/anchor-imagesList all anchor images (metadata from DB)
POST/api/anchor-imagesUpload anchor image (multipart: image file, label, description; max 10MB)
PATCH/api/anchor-images/:idUpdate anchor image label/description
DELETE/api/anchor-images/:idDelete anchor image (file + DB row)

Anchor images are stored in .psycheros/anchors/ with metadata in the anchor_images SQLite table. Used as style/character references by the generate_image tool.

MethodPathDescription
GET/api/gallery/imagesList all gallery images with pagination (?offset=N&limit=N, default 24)

Scans .psycheros/generated-images/ and .psycheros/chat-attachments/ directories, cross-references with the messages table for metadata (prompt, generator, description for generated images; upload date for all). Returns JSON with { totalSize, generatedCount, userCount, total, hasMore, images[] }. Anchor images are excluded (managed in their own tab). View-only — no delete endpoint.

MethodPathDescription
POST/api/chat-attachmentsUpload image attachment for chat (multipart: attachment file; max 10MB)
GET/chat-attachments/:filenameServe chat attachment image file

Attachments are stored in .psycheros/chat-attachments/. The chat request body includes an optional attachmentId field; if provided and captioning is configured, the attachment is auto-captioned via the configured vision model and prefixed to the user message as [USER_IMAGE: /chat-attachments/filename | Caption: description]. If captioning fails or is not configured, falls back to [USER_IMAGE: /chat-attachments/filename].

MethodPathDescription
GET/generated-images/:filenameServe a generated image file
GET/anchors/:filenameServe an anchor image file
MethodPathDescription
GET/api/tools-settingsGet all tools metadata, categories, current overrides, and custom tool names
POST/api/tools-settingsSave tool overrides and hot-reload registry ({ "toolOverrides": { "shell": true, ... } })
POST/api/custom-tools/uploadUpload a custom tool .js file (multipart/form-data, field tool, max 100KB); writes to custom-tools/ and hot-reloads registry

Settings stored in .psycheros/tools-settings.json. Shape: { "toolOverrides": Record<string, boolean> }. When this file exists, overrides take precedence over PSYCHEROS_TOOLS env var.

The custom tools upload endpoint accepts a multipart/form-data request with a tool field containing the .js file. On success, the file is written to custom-tools/<filename> and the custom tool registry is reloaded. Returns { "success": true, "toolName": "..." } or { "success": false, "error": "..." }.

MethodPathDescription
POST/api/mcp/syncManually trigger MCP sync
MethodPathDescription
GET/fragments/adminAdmin hub with tab navigation
GET/fragments/admin/diagnosticsDiagnostics dashboard HTML fragment
GET/fragments/admin/logsLog viewer HTML fragment
GET/fragments/admin/jobsScheduled jobs dashboard HTML fragment
GET/fragments/admin/actionsActions panel HTML fragment
GET/fragments/settings/connectionsExternal connections hub (Channels, Home, Web Search tabs)
GET/fragments/settings/connections/discordDiscord connection settings fragment
GET/fragments/settings/connections/homeHome automation settings fragment
GET/fragments/settings/visionVision settings hub (Generators, Anchors, Gallery tabs)
GET/fragments/settings/vision/generatorsGenerators tab content (HTMX fragment)
GET/fragments/settings/vision/anchorsAnchors tab content (HTMX fragment)
GET/fragments/settings/vision/galleryGallery tab content (HTMX fragment, server-rendered)
GET/fragments/settings/vision/image-gen/newNew image generator config fragment
GET/fragments/settings/vision/image-gen/:idEdit image generator config fragment
GET/fragments/settings/toolsTools settings UI fragment
GET/fragments/settings/saSituational Awareness settings fragment
GET/fragments/settings/vaultData Vault management fragment
GET/fragments/settings/vault/:idVault document detail/edit fragment
GET/fragments/settings/entity-coreEntity Core hub with tab navigation
GET/fragments/settings/entity-core/overviewEntity Core overview tab (ping-based connection status, graph stats, extraction pipeline health, sync)
GET/fragments/settings/entity-core/llmEntity Core LLM settings tab
GET/fragments/settings/entity-core/graphKnowledge Graph visualization tab
GET/fragments/settings/entity-core/maintenanceEntity Core maintenance tab (consolidation, batch populate, embed)
GET/fragments/settings/entity-core/snapshotsSnapshot browser tab
GET/fragments/entity-core/snapshots/:idSnapshot preview fragment
GET/fragments/settings/memoriesMemories tabbed view fragment
GET/fragments/settings/memories/search?q=Search memories across all granularities (uses entity-core memory_search)
GET/fragments/settings/memories/:granularityMemory file list fragment (daily/weekly/monthly/yearly/significant). Query params: offset (pagination), before, after (date range, YYYY-MM-DD)
GET/fragments/settings/memories/:granularity/:dateMemory editor fragment
GET/api/admin/diagnosticsJSON diagnostics snapshot (all subsystems)
GET/api/admin/logsJSON log entries with filtering (?level=, ?component=, ?limit=, ?since=)
GET/api/admin/logs/entriesHTML partial of log entries (same query params as above)
GET/api/admin/jobsJSON scheduled jobs status
GET/api/admin/jobs/rowsHTML partial of job table rows
POST/api/admin/jobs/:id/triggerManually trigger a scheduled job
POST/api/admin/actions/batch-populateRun batch-populate-graph script ({ days, granularity, dryRun, verbose })
POST/api/admin/actions/add-instance-suffixAdd instance suffix to old memory files ({ instanceId, apply, scopes })
MethodPathDescription
GET/api/pulsesList all pulses
POST/api/pulsesCreate a new pulse (JSON body)
GET/api/pulses/:idGet single pulse
PUT/api/pulses/:idUpdate a pulse
DELETE/api/pulses/:idDelete a pulse
POST/api/pulses/:id/triggerManual trigger
POST/api/pulses/:id/stopAbort a running Pulse
GET/api/pulses/running/:conversationIdGet pulse ID running for a conversation
POST/api/webhook/pulse/:idWebhook trigger (Bearer token auth)
GET/api/pulses/runsList pulse runs (paginated, filterable by ?pulseId=, ?status=)
GET/api/pulses/:id/runsRuns for a specific pulse
GET/api/pulses/runs/:runIdSingle run details
GET/fragments/settings/pulseMain tabbed Pulse view (Prompts + Execution Log)
GET/fragments/settings/pulse/newNew Pulse editor
GET/fragments/settings/pulse/:id/editEdit Pulse editor
GET/fragments/settings/pulse/listPrompt list partial (for HTMX reload)
GET/fragments/settings/pulse/logExecution log partial (paginated)
FilePurpose
src/server/routes.tsAll API endpoint handlers
src/server/admin-routes.tsAdmin panel route handlers
src/server/admin-templates.tsAdmin panel HTML rendering
src/server/diagnostics.tsDiagnostics snapshot aggregation
src/server/logger.tsLog capture ring buffer
src/server/sse.tsSSE encoding utilities
src/server/broadcaster.tsPersistent SSE channel (EventBroadcaster)
src/server/state-changes.tsUnified state mutations
src/server/ui-updates.tsReactive DOM updates
src/server/templates.tsHTML rendering for fragments
src/tools/tools-settings.tsTool settings types, categories, persistence
src/tools/custom-loader.tsDynamic custom tool loader
src/pulse/engine.tsPulse scheduling and execution engine
src/pulse/routes.tsPulse CRUD and trigger API handlers
src/pulse/templates.tsPulse settings UI rendering
src/llm/discord-settings.tsDiscord settings type, persistence, token masking
src/llm/home-settings.tsHome automation settings type, persistence
src/tools/control-device.tsHome automation tool (Shelly Plug local HTTP API)
src/llm/lovense-settings.tsLovense settings type, persistence, LAN/Game Mode config
src/llm/buttplug-settings.tsUniversal toy control settings type, persistence, WebSocket URL config
src/tools/control-lovense.tsLovense device control tool (state-based patterns, speed, presets)
src/tools/control-buttplug.tsUniversal toy control tool (control_toy, vibration/rotation/position/oscillate/constrict, pattern engine)
src/llm/image-gen-settings.tsImage generator + captioning config type, persistence, API key masking
src/tools/generate-image.tsImage generation tool (OpenRouter, Gemini), auto-captioning
src/tools/describe-image.tsImage captioning tool (Gemini, OpenRouter), shared caption logic