This page describes the local Agent/Memory service on port 8787. If you received a public Base URL and personal API key, use the shared inference API guide instead. See the documentation index and deployment guide for the full project entry points.
| Interface | Authentication / scope | Chat behavior |
|---|---|---|
| Shared inference (local gateway default 8788, public HTTPS via tunnel) | Personal Bearer key; no user/session headers required | Text inference, streaming, usage, inference metadata; no durable memory or tool execution |
| Local Agent (default 8787, this page) | User/session headers identify scope but are not public authentication; native tools have a separate owner token | Non-streaming chat, scoped memory and governed tools; benchmark metadata |
The identical /v1/chat/completions path does not make these two service contracts interchangeable.
ModelHarbor listens on http://127.0.0.1:8787 by default. Phase one is local-only and does not
provide TLS or general user authentication. Native account tools separately require an owner token.
Chat and memory operations require explicit user and Session scope.
Errors use:
{"error":{"code":"ERROR_CODE","message":"Human-readable explanation."}}Process liveness. It does not contact dependencies.
{"status":"ok"}Checks the compiled Hypha contract, Ollama availability, configured model, and Plasmod health.
Returns HTTP 200 when ready and 503 otherwise.
{
"status": "ready",
"dependencies": {
"ollama": "ready",
"plasmod": "ready",
"hyphaContract": "ready"
}
}Returns the active provider-neutral model record:
{
"object": "list",
"data": [
{
"id": "qwen3.5:9b-128k",
"object": "model",
"owned_by": "local",
"context_window": 131072,
"alias": "local-default"
}
]
}Required headers:
Content-Type: application/jsonX-User-ID: <local user identifier>X-Session-ID: <conversation identifier>
Request:
{
"model": "local-default",
"stream": false,
"messages": [
{"role": "system", "content": "Answer concisely."},
{"role": "user", "content": "What preferences do you remember?"}
]
}Supported roles are system, user, and assistant. stream: true returns HTTP 400 with
STREAMING_UNSUPPORTED in phase one.
Before generation, ModelHarbor queries Plasmod using the supplied user and Session scope. After a
successful Ollama response, it persists the completed interaction as a strict Plasmod Dynamic Event
v0.4. If that write fails, the request returns 503; the service does not report a durable success.
Response:
{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1788494400,
"model": "qwen3.5:9b-128k",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": "..."},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 100,
"completion_tokens": 20,
"total_tokens": 120
},
"benchmark": {
"queueWaitMs": 0.2,
"memoryQueryMs": 4.1,
"inferenceMs": 1280.5,
"memoryWriteMs": 3.7,
"totalMs": 1288.5,
"memoryHits": 2,
"promptCharacters": 942,
"contextBudgetCharacters": 360000,
"contextTruncated": false,
"persisted": true
}
}persisted describes the companion benchmark Artifact. The completed interaction Memory remains
the success boundary for the Chat request; a metrics-only write failure does not discard a valid
model response.
Uses the same scope headers as Chat.
{"query":"preferred response style"}The response contains extracted text plus a scope-validated projection of Plasmod's structured evidence. Unfiltered upstream graph/trace payloads are deliberately not forwarded:
{"memories":["The user prefers concise answers."],"evidence":{}}Optional fields on POST /v1/chat/completions:
| Field | Values / default | Meaning |
|---|---|---|
memory_mode |
session (default), user, off |
Recall in this session, across the same user workspace, or no recall. |
memory_write |
boolean, default true |
Set false for read-only experimental probes; no interaction or benchmark write. |
tool_mode |
off (default), public, local |
No tools; time/public search; or time/private Apple tools. |
search_query |
string, max 500 chars | Explicitly approved public query; the model cannot change it before external search. |
local tools additionally require X-Local-Tool-Token and the owner X-User-ID.
Unauthorized requests return 403 LOCAL_TOOLS_FORBIDDEN before inference. The token is never
returned by an API. benchmark.toolTrace contains Hypha execution events, and
benchmark.memoryEvidence contains scope-validated recall evidence for local analysis, including
scope_filtered_count. Identities that cannot be verified are excluded.
Returns tool names, modes and configuration status; no account contents or credentials.
The default search entry includes provider: "exa_mcp" and status: "configured_free_no_key".
This is not a live health check. Optional Ollama search reports configured only with a key;
disabled/key-missing search reports not_configured and is not exposed to the model.
The bundled UI uses these same-origin endpoints. They are stable backend boundaries for future gateways; clients should not call Plasmod directly.
Requires X-User-ID. Returns sessions derived from canonical Plasmod Memory records in that user
workspace.
Requires both scope headers. Returns ordered conversation turns and any linked per-turn benchmark Artifact.
Requires both scope headers. Returns canonical Plasmod Memory records for the selected Session.
Returns the configured model and context window, KV-cache manager/type, live admission snapshot, dependency health, and aggregate Plasmod metrics. It does not expose internal dependency URLs.
| Status | Meaning |
|---|---|
200 |
Completed; Chat persists its interaction unless memory_write: false |
400 |
Invalid JSON, scope, messages, query, or unsupported streaming |
403 |
Native tools requested without the correct owner and token |
404 |
Unknown route |
413 |
Request body exceeds 2 MiB |
422 |
Tool loop exceeded its step, call, or context budget |
429 |
Five-request queue or five-user admission boundary reached |
503 |
Ollama, model, or Plasmod unavailable |
One inference runs at a time. Requests are admitted FIFO, with five total admitted requests and no more than five distinct admitted users.