Young's Mind
Tech

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)

  1. agent_app.py .backup/.backup2/.backup3/.before_fix/.fixed.backup sprawl + 11 more backup files elsewhere; no git β€” regression auditing is guesswork.
  2. dispatch_tracker.track_dispatch_state() references dt.task_ref column NOT in CREATE TABLE β†’ silent except Exception: pass every cycle (L150–162) β€” ghost stuck-states never auto-resolve.
  3. SESSION_MAX_TURNS=1000 resets history mid-conversation.
  4. get_messages(limit=50) + history-20: = two independent truncation layers.
  5. chat_messages table populated but unread by the serving path (schema drift).
  6. Failed tool calls end as final user-visible "(max turns reached)" β€” error state lost.
  7. TG thread routing missing (message_thread_id ignored) β€” reply-to-thread loops.

4. Ranked fix plan (effort Γ— impact)

#ChangeEffortImpact
1Inject memory plane every turn: top-N durable + retrieve_facts(user text) + last 3 episodic summaries before run_agent_loop (~30 lines; API exists)SHIGH β€” kills restart amnesia
2Record episodic summary after every completed turn (record_episode in post-response path)SHIGH β€” feeds #1
3Summarize-on-eviction: compact session summary β†’ memory_episodic at cap/age/turns wipes; restore = summary + last-20 rawMHIGH
4Gateway: include message_thread_id in session id (chat{id}-topic{thread})SMED-HIGH β€” removes topic-collide reply-loops
5Empty-reply dedupe: replace canned "Done. Ask me anything…" with last-known-state replySMED β€” the visible repetition killer
6Fleet shared-memory bus: assistant replies β†’ memory_episodic (agent+chat); prompt includes last 5 cross-agent events per chatMMED β€” teammates stop contradicting
7Inbound dedupe: hash (chat_id, text, Β±10s) at gateway; skip repeatsSMED
8Widen window: history-50: + raise DB reload limit for group chatsXSMED
9Fix dispatch_tracker.task_ref schema (add column or drop query)XSLOW-MED
10Convert ~/.solos/core to a git repo; retire backup sprawl; single reply-normalize pointSLOW-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.

Copyright Β© 2026