|
|
@@ -8,6 +8,7 @@ for a reader who wants to understand the design before changing it.
|
|
|
- [Thread sessions and the frontier](#thread-sessions-and-the-frontier)
|
|
|
- [Realtime resume](#realtime-resume)
|
|
|
- [Configuration resolution](#configuration-resolution)
|
|
|
+- [Per-room toolsets](#per-room-toolsets)
|
|
|
- [One send path, two callers](#one-send-path-two-callers)
|
|
|
|
|
|
## Thread sessions and the frontier
|
|
|
@@ -230,6 +231,44 @@ differently is exactly the drift risk this design usually avoids; the containmen
|
|
|
that they converge on one type, and the only place that fills it differently is the
|
|
|
one place where no better information exists.
|
|
|
|
|
|
+## Per-room toolsets
|
|
|
+
|
|
|
+### Why the hook exists at all
|
|
|
+
|
|
|
+Hermes has no per-chat tool policy of its own. The adapter hook
|
|
|
+`toolsets_for_source(source)` is the only door: the gateway asks the adapter,
|
|
|
+per turn, which toolsets to enable. The webhook adapter already uses it for
|
|
|
+per-route tool lists, which is the precedent this follows.
|
|
|
+
|
|
|
+### Replacement, not subtraction
|
|
|
+
|
|
|
+The hook's contract is that a returned list *replaces* `platform_toolsets` for
|
|
|
+that turn — the gateway copies the override into the platform's entry and
|
|
|
+resolves it through the same `_get_platform_tools` path. Subtraction would need
|
|
|
+a second decision ("minus these, from what?"), and a room entry that removed
|
|
|
+`terminal` would otherwise silently keep everything else. Replacement makes the
|
|
|
+entry self-contained: what is written is what the room gets. The cost is that a
|
|
|
+user must list every toolset the room keeps, including `chatto-platform` if the
|
|
|
+agent should keep its Chatto tools — which is why README says so in the tool
|
|
|
+documentation and in the variable table rather than leaving it to be discovered.
|
|
|
+
|
|
|
+An unlisted room returns `None`, the hook's "no opinion" answer, so a config
|
|
|
+with no entries changes nothing.
|
|
|
+
|
|
|
+### Keyed on the room, validated at startup
|
|
|
+
|
|
|
+The entry key is `chat_id`, which for this adapter is the room ID the realtime
|
|
|
+event carried — not model input, so it cannot be talked around. A thread turn
|
|
|
+keeps the room as `chat_id` and carries the thread separately, so one entry
|
|
|
+covers a room's threads without a second lookup.
|
|
|
+
|
|
|
+The entry *syntax* is validated at startup because a malformed entry would
|
|
|
+otherwise be skipped, leaving a room the operator meant to restrict on the
|
|
|
+default toolsets — the one failure direction that is invisible in logs and
|
|
|
+dangerous. The toolset *names* are deliberately not validated here: Hermes drops
|
|
|
+unknown ones when it resolves the list, so a typo yields fewer tools, which is
|
|
|
+the failure direction that hides nothing.
|
|
|
+
|
|
|
## One send path, two callers
|
|
|
|
|
|
A user cannot tell whether the agent replied on its own or through a tool, so the
|