docs(memory-provider): threading contract names spawn_context_thread and the sidecar/config primitives

The developer guide showed the exact bare threading.Thread pattern the previous
commits removed from six in-tree providers; an external plugin copying it loses
the profile ContextVar under multiplex. Point it at
agent.memory_provider.spawn_context_thread and the canonical JSON/config writers.
This commit is contained in:
teknium1
2026-09-12 20:36:15 -07:00
committed by Teknium
parent d364473620
commit d32350fcc5
@@ -297,9 +297,11 @@ hooks:
## Threading Contract
**`sync_turn()` MUST be non-blocking.** If your backend has latency (API calls, LLM processing), run the work in a daemon thread:
**`sync_turn()` MUST be non-blocking.** If your backend has latency (API calls, LLM processing), run the work in a daemon thread — spawned with `agent.memory_provider.spawn_context_thread`, never a bare `threading.Thread`. Profile isolation (the active `HERMES_HOME`, the per-turn secret scope) lives in `contextvars`, and a plain thread starts with an empty context: under multiplexed profiles it would silently write into the *default* profile's store, and `get_secret()` fails closed there.
```python
from agent.memory_provider import spawn_context_thread
def sync_turn(self, user_content, assistant_content, *, session_id="", messages=None):
def _sync():
try:
@@ -309,10 +311,12 @@ def sync_turn(self, user_content, assistant_content, *, session_id="", messages=
if self._sync_thread and self._sync_thread.is_alive():
self._sync_thread.join(timeout=5.0)
self._sync_thread = threading.Thread(target=_sync, daemon=True)
self._sync_thread = spawn_context_thread(_sync, name="myprovider-sync")
self._sync_thread.start()
```
The same applies to prefetch and writer threads. Small JSON config sidecars (`$HERMES_HOME/<provider>.json`) are read with `utils.read_json_or_empty` and written with `utils.atomic_json_write`; anything under `config.yaml` goes through `hermes_cli.config.save_config(..., merge_existing=True)`.
`messages` is optional OpenAI-style conversation context as of the completed
turn. When present, it includes user/assistant messages, assistant tool calls,
and tool result messages. Providers that do not need raw turn context can omit