docs: add matrix direct-agent prototype design
This commit is contained in:
parent
b08a5e3d96
commit
1fdb5bf303
1 changed files with 243 additions and 0 deletions
|
|
@ -0,0 +1,243 @@
|
||||||
|
# Matrix Direct-Agent Prototype Design
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Ship a working Matrix prototype that talks to the real Lambda agent instead of `MockPlatformClient`, while preserving the current Matrix adapter logic and keeping the code expandable toward future platform versions.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This design is for a Matrix-only prototype delivered from this repository on a dedicated branch. It is not a `main` branch rollout and it is not a separate prototype repo.
|
||||||
|
|
||||||
|
The design assumes a minimal companion fork of `platform/agent` may be used, but changes there must stay as small as possible.
|
||||||
|
|
||||||
|
## Constraints
|
||||||
|
|
||||||
|
- Preserve the current Matrix transport logic as much as possible.
|
||||||
|
- Keep `core/` unaware of platform immaturity.
|
||||||
|
- Avoid broad changes to platform repos.
|
||||||
|
- Prefer one narrow patch to `platform/agent` over changes to both `platform/agent` and `platform/agent_api`.
|
||||||
|
- Keep the backend boundary reusable for future Telegram or other surfaces.
|
||||||
|
- Do not pretend unsupported platform capabilities are real.
|
||||||
|
|
||||||
|
## Live Platform Findings
|
||||||
|
|
||||||
|
Based on the live repo analysis performed on April 7, 2026:
|
||||||
|
|
||||||
|
- `platform/master` is not yet a usable consumer-facing backend for surfaces.
|
||||||
|
- `platform/agent` exposes a working WebSocket endpoint for prompt/response exchange.
|
||||||
|
- `platform/agent_api` documents and implements text-oriented WebSocket messaging, but the bot does not need to depend on that package directly.
|
||||||
|
- `platform/agent` currently hardcodes a single shared backend memory thread via `thread_id = "default"`, which would cause all chats to share context.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The prototype remains in this repo and introduces a new real backend path behind the existing SDK boundary.
|
||||||
|
|
||||||
|
### New files
|
||||||
|
|
||||||
|
- `sdk/real.py`
|
||||||
|
- Exports `RealPlatformClient`
|
||||||
|
- Implements the existing `PlatformClient` contract from `sdk/interface.py`
|
||||||
|
- Composes the lower-level prototype pieces
|
||||||
|
|
||||||
|
- `sdk/agent_session.py`
|
||||||
|
- Owns direct WebSocket communication with the real agent
|
||||||
|
- Manages connection lifecycle, request/response handling, and thread identity
|
||||||
|
|
||||||
|
- `sdk/prototype_state.py`
|
||||||
|
- Owns local prototype-only state
|
||||||
|
- Stores user mapping, local settings, and lightweight metadata needed until a real control plane exists
|
||||||
|
|
||||||
|
### Responsibility split
|
||||||
|
|
||||||
|
- Matrix adapter remains transport-specific only.
|
||||||
|
- `core/` continues to depend only on `PlatformClient`.
|
||||||
|
- `RealPlatformClient` acts as the anti-corruption layer between the current bot contract and the platform’s incomplete shape.
|
||||||
|
- Local control-plane behavior remains explicit and replaceable later.
|
||||||
|
|
||||||
|
## Message and Identity Model
|
||||||
|
|
||||||
|
Each Matrix chat gets a stable backend session identity.
|
||||||
|
|
||||||
|
### Surface identity
|
||||||
|
|
||||||
|
- Surface: `matrix`
|
||||||
|
- Surface user id: Matrix MXID, for example `@alice:example.org`
|
||||||
|
- Surface chat id: logical chat id from `ChatManager`, for example `C1`
|
||||||
|
- Surface ref: Matrix room id
|
||||||
|
|
||||||
|
### Backend thread identity
|
||||||
|
|
||||||
|
Use a deterministic thread key:
|
||||||
|
|
||||||
|
`matrix:{matrix_user_id}:{chat_id}`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
`matrix:@alice:example.org:C1`
|
||||||
|
|
||||||
|
### Mapping rules
|
||||||
|
|
||||||
|
- One Matrix logical chat maps to one backend memory thread.
|
||||||
|
- `!new` creates a fresh logical chat and therefore a fresh backend thread.
|
||||||
|
- `!rename` only changes display metadata and does not change backend identity.
|
||||||
|
- `!archive` stops active use of the thread in the surface, but does not need to delete backend memory in v1.
|
||||||
|
|
||||||
|
## Runtime Flow
|
||||||
|
|
||||||
|
### Normal message flow
|
||||||
|
|
||||||
|
1. Matrix event arrives in an existing room.
|
||||||
|
2. Existing Matrix routing resolves room to logical `chat_id`.
|
||||||
|
3. `core/handlers/message.py` calls `platform.send_message(...)`.
|
||||||
|
4. `RealPlatformClient` derives the backend thread key from `(platform, user_id, chat_id)`.
|
||||||
|
5. `AgentSessionClient` sends the prompt to the agent WebSocket using that thread key.
|
||||||
|
6. The reply is converted into the existing `MessageResponse` or `MessageChunk` contract.
|
||||||
|
7. Matrix sends the final text back to the room.
|
||||||
|
|
||||||
|
### Settings flow
|
||||||
|
|
||||||
|
For v1, settings remain local:
|
||||||
|
|
||||||
|
- `get_settings()` reads from local prototype state
|
||||||
|
- `update_settings()` writes to local prototype state
|
||||||
|
|
||||||
|
This is intentional. The prototype must not claim settings are backed by the real platform when no such platform API exists yet.
|
||||||
|
|
||||||
|
## Feature Matrix
|
||||||
|
|
||||||
|
### Real in v1
|
||||||
|
|
||||||
|
- `!start`
|
||||||
|
- Plain text messaging with the real agent
|
||||||
|
- Matrix chat lifecycle already implemented in this repo:
|
||||||
|
- `!new`
|
||||||
|
- `!chats`
|
||||||
|
- `!rename`
|
||||||
|
- `!archive`
|
||||||
|
- Per-chat conversation memory, provided the agent accepts dynamic thread identity
|
||||||
|
|
||||||
|
### Local in v1
|
||||||
|
|
||||||
|
- `!settings`
|
||||||
|
- `!skills`
|
||||||
|
- `!soul`
|
||||||
|
- `!safety`
|
||||||
|
- `!status`
|
||||||
|
- user registration and local user mapping
|
||||||
|
|
||||||
|
### Deferred
|
||||||
|
|
||||||
|
- Attachments and file upload to the agent
|
||||||
|
- Voice input to the agent
|
||||||
|
- Image input to the agent
|
||||||
|
- Long-running task callbacks and webhook-style async completion
|
||||||
|
- Real control-plane integration through `platform/master`
|
||||||
|
|
||||||
|
## Minimal Upstream Change
|
||||||
|
|
||||||
|
To avoid shared memory across all conversations, make one narrow change in the forked `platform/agent` repo:
|
||||||
|
|
||||||
|
- stop hardcoding `thread_id = "default"`
|
||||||
|
- derive thread identity from WebSocket connection context
|
||||||
|
|
||||||
|
### Preferred mechanism
|
||||||
|
|
||||||
|
Read `thread_id` from WebSocket query parameters rather than changing the message payload format.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
`ws://host:port/agent_ws/?thread_id=matrix:@alice:example.org:C1`
|
||||||
|
|
||||||
|
This is preferred because:
|
||||||
|
|
||||||
|
- it limits the platform patch to one repo
|
||||||
|
- it avoids changing both server and SDK protocol shape
|
||||||
|
- it keeps the client message body text-only
|
||||||
|
- it makes session identity explicit and easy to reason about
|
||||||
|
|
||||||
|
## Why Not Use `platform/agent_api` Directly
|
||||||
|
|
||||||
|
The bot should not depend on their client package for the prototype.
|
||||||
|
|
||||||
|
Reasons:
|
||||||
|
|
||||||
|
- the bot already has its own internal integration boundary in `sdk/interface.py`
|
||||||
|
- a tiny local WebSocket client is enough for this protocol
|
||||||
|
- avoiding a dependency on `platform/agent_api` keeps rebasing simpler
|
||||||
|
- if upstream stabilizes later, the bot can adopt their SDK without affecting Matrix handlers
|
||||||
|
|
||||||
|
## Repo Strategy
|
||||||
|
|
||||||
|
### This repo
|
||||||
|
|
||||||
|
Owns:
|
||||||
|
|
||||||
|
- Matrix surface logic
|
||||||
|
- SDK compatibility layer
|
||||||
|
- local prototype state
|
||||||
|
- backend selection and wiring
|
||||||
|
|
||||||
|
### Forked `platform/agent`
|
||||||
|
|
||||||
|
Owns only:
|
||||||
|
|
||||||
|
- minimal thread identity patch required for per-chat memory
|
||||||
|
|
||||||
|
### Explicitly not doing
|
||||||
|
|
||||||
|
- no separate prototype repo
|
||||||
|
- no changes to `platform/master` for v1
|
||||||
|
- no unnecessary changes to `platform/agent_api`
|
||||||
|
|
||||||
|
## Migration Path
|
||||||
|
|
||||||
|
This design is intentionally expandable.
|
||||||
|
|
||||||
|
When the platform develops further:
|
||||||
|
|
||||||
|
- `sdk/prototype_state.py` can be replaced or reduced by a real `MasterClient`
|
||||||
|
- `sdk/agent_session.py` can remain the direct session transport if still relevant
|
||||||
|
- `RealPlatformClient` can continue to present the stable bot-facing interface
|
||||||
|
- Telegram or another surface can reuse the same backend components without rethinking the integration model
|
||||||
|
|
||||||
|
## Risks
|
||||||
|
|
||||||
|
### Risk: hidden platform assumptions leak upward
|
||||||
|
|
||||||
|
Mitigation:
|
||||||
|
- keep all direct-agent logic below `RealPlatformClient`
|
||||||
|
- avoid changing `core/` contracts for prototype convenience
|
||||||
|
|
||||||
|
### Risk: settings semantics drift from future platform reality
|
||||||
|
|
||||||
|
Mitigation:
|
||||||
|
- make local settings behavior explicit in code and docs
|
||||||
|
- keep settings isolated in `sdk/prototype_state.py`
|
||||||
|
|
||||||
|
### Risk: upstream `agent` fork diverges
|
||||||
|
|
||||||
|
Mitigation:
|
||||||
|
- keep the patch minimal and narrowly scoped to thread identity
|
||||||
|
|
||||||
|
### Risk: thread identity source is unstable
|
||||||
|
|
||||||
|
Mitigation:
|
||||||
|
- derive thread key from existing stable bot-side identities: platform, surface user id, logical chat id
|
||||||
|
|
||||||
|
## Testing Strategy
|
||||||
|
|
||||||
|
- Unit tests for `sdk/agent_session.py` request/response behavior
|
||||||
|
- Unit tests for `sdk/prototype_state.py` local settings and user mapping
|
||||||
|
- Unit tests for `sdk/real.py` contract compliance with `PlatformClient`
|
||||||
|
- Matrix integration tests confirming:
|
||||||
|
- existing commands still work
|
||||||
|
- different logical chats map to different backend thread keys
|
||||||
|
- rename does not change thread identity
|
||||||
|
- archive stops reuse from the surface perspective
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
- Matrix can talk to the real agent without rewriting the Matrix adapter architecture
|
||||||
|
- Chats do not share backend memory accidentally
|
||||||
|
- Unsupported platform capabilities remain local or deferred rather than being faked as “real”
|
||||||
|
- The backend boundary remains suitable for later Telegram or other surfaces
|
||||||
Loading…
Add table
Add a link
Reference in a new issue