SolOS Architecture Review (from the actual code, not symptoms)
SolOS Architecture Review (from the actual code, not symptoms)
1. Architecture map (verified)
Telegram gateway services/telegram-gateway/gateway_loop.py (PTB, bots.json)
β per-agent FastAPI A2A servers core/agent_app.py (ports 8300β8307)
β run_agent_loop core/agent_loop.py (tier-fallback provider chain)
state: in-process sessions dict + data/solos.db (sessions/messages)
Memory plane: core/memory.py β 4-layer (durable / LTM via Redis+Qdrant / episodic / short-term),
tables LIVE in solos.db β but see Β§2A
Audit: event_bus.py, dispatch_tracker.py, action_log.py
A2A: a2a/a2a_dispatch.py; Registry :8432/:8433; CostGov :8430
Cron/autopilot: auto_pilot.py, autonomous*.py, central_cron.py
Tools: agents/tools/memory_tool.py (store_fact/retrieve β the ONLY live memory caller)
2. Diagnosis β why agents "miss information and repeat"
A. Memory plane is orphaned from the serving path (biggest). core/memory.py is fully built, but grep across agent_app.py / run_*.py / telegram-gateway finds zero per-turn memory injection. Only agent-initiated memory_tool.py touches it. persona_loader injects persona but no durable/episodic memory β agents relearn per restart.
B. In-process session dict is the real context of record. Silent wipes at: 3-session cap (evicts oldest, agent_app.py ~L320), 120-min age cap, 1000-turn cap (L353β355). DB restore reloads only last 50 messages. Long conversations β context degrades to last-50 at best, blank at worst β repeated greetings/status.
C. Thin windows. Agent loop sends only history-20: (agent_loop.py). Group chats store 200+ messages; model sees 20 β "missing information".
D. Per-agent isolation. No cross-agent/fleet memory in prompts; messages table is keyed by session_id without agent filter β agents contradict / repeat teammates.
E. No summarization on eviction. Context discarded raw instead of compacted into memory_episodic.
Repetition amplifiers: dispatch_tracker auto-check-ins pollute sessions with identical "AUTO CHECK-IN" nags (3Γ/15min per stuck dispatch); prompt_factory fixed template lines; gateway _extract_reply substitutes canned "Done. Ask me anythingβ¦" for empty replies. No inbound-message dedupe (hash+window) anywhere; no message_thread_id in gateway session ids β all TG topics in a group collapse into ONE session.
3. Bugs / hygiene (verified)
- agent_app.py .backup/.backup2/.backup3/.before_fix/.fixed.backup sprawl + 11 more backup files elsewhere; no git β regression auditing is guesswork.
- dispatch_tracker.track_dispatch_state() references dt.task_ref column NOT in
CREATE TABLE β silent
except Exception: passevery cycle (L150β162) β ghost stuck-states never auto-resolve. - SESSION_MAX_TURNS=1000 resets history mid-conversation.
- get_messages(limit=50) + history-20: = two independent truncation layers.
- chat_messages table populated but unread by the serving path (schema drift).
- Failed tool calls end as final user-visible "(max turns reached)" β error state lost.
- TG thread routing missing (message_thread_id ignored) β reply-to-thread loops.
4. Ranked fix plan (effort Γ impact)
| # | Change | Effort | Impact |
|---|---|---|---|
| 1 | Inject memory plane every turn: top-N durable + retrieve_facts(user text) + last 3 episodic summaries before run_agent_loop (~30 lines; API exists) | S | HIGH β kills restart amnesia |
| 2 | Record episodic summary after every completed turn (record_episode in post-response path) | S | HIGH β feeds #1 |
| 3 | Summarize-on-eviction: compact session summary β memory_episodic at cap/age/turns wipes; restore = summary + last-20 raw | M | HIGH |
| 4 | Gateway: include message_thread_id in session id (chat{id}-topic{thread}) | S | MED-HIGH β removes topic-collide reply-loops |
| 5 | Empty-reply dedupe: replace canned "Done. Ask me anythingβ¦" with last-known-state reply | S | MED β the visible repetition killer |
| 6 | Fleet shared-memory bus: assistant replies β memory_episodic (agent+chat); prompt includes last 5 cross-agent events per chat | M | MED β teammates stop contradicting |
| 7 | Inbound dedupe: hash (chat_id, text, Β±10s) at gateway; skip repeats | S | MED |
| 8 | Widen window: history-50: + raise DB reload limit for group chats | XS | MED |
| 9 | Fix dispatch_tracker.task_ref schema (add column or drop query) | XS | LOW-MED |
| 10 | Convert ~/.solos/core to a git repo; retire backup sprawl; single reply-normalize point | S | LOW-MED |
Implement order: #1+#2 β #8 (quick win) β #3 β #4+#5+#7 β #6 β hygiene.
Provenance
Read-only ssh reads of core/agent_app.py, agent_loop.py, session_manager, dispatch_tracker, prompt_factory, gateway_loop; counts from data/solos.db (one super-group session = 206 msgs). No server files were modified.
Anthropic Agents study (7 sources β adoption plan for SolOS)
Requested by: Young (2026-09-15): study with Echo, register to vault, Min publishes to docs.youngle.au. Tracker task-3c4000d6 (done). All sources fetched in full (curl+strip; web_extract 403-truncated). One source turned out to be a metadata error β flagged below.
OpenCode vs SolOS vs Hermes β Architecture Study
Directive under test (Young): "OpenCode has everything we need; integrate SolOS into it and optimise their existing architecture."

