From ce95ac267a559f4c8c007c7c136ae4c18691986f Mon Sep 17 00:00:00 2001 From: cyber-ayi <259769279+cyber-ayi@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:56:13 -0700 Subject: [PATCH 1/2] =?UTF-8?q?docs(exploration):=20gateway=20selection=20?= =?UTF-8?q?=E2=80=94=20MVP=20=3D=20direct=20two-way=20Discord?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second exploration note + converges the salient-push channel gate. - exploration/gateway-selection.md — evaluates the operator<->agent channel: direct discord.py / LangBot / AstrBot / NoneBot2 / OpenClaw / ntfy. Clarifies the two senses of "gateway" (IM channel vs LLM API proxy — different layers). Decisive criterion = agent-initiated salient push; transport-not-brain. - MVP decision (operator): the channel is **direct, thin Discord (discord.py), two-way**. The dyad is 1 operator / 1 agent / 1 platform, so multi-platform gateway frameworks solve a non-MVP problem; agent-initiated push is native and fully controlled via discord.py; Python co-locates with the L3 cognition layer. Frameworks deferred — LangBot is the front-runner if/when multi-platform or an ops/WebUI control plane is actually needed. - ROADMAP — converge the `salient push: ntfy vs Discord` gate to this; add the note to Open explorations. Session-Id: 019e8d56-605a-7b45-8ef0-21ee576aa7a9 Agent: cc-rc-bot Co-authored-by: cyber-ayi <259769279+cyber-ayi@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) --- ROADMAP.md | 3 +- exploration/gateway-selection.md | 93 ++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 exploration/gateway-selection.md diff --git a/ROADMAP.md b/ROADMAP.md index 32a0231..262eab4 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -80,7 +80,7 @@ Each downstream task carries its own small decision-gate. None block T1. | harness **runtime**: OpenClaw vs ElizaOS vs Hermes | T2 / T5 | candidates listed in `harness/README.md`, unchosen | | **IPC transport** TS↔Python (how JSON crosses the seam) | T5 | explicitly deferred by ADR-0006 | | Melvor **act path**: mod API vs CDP / headless-Chromium | T2 | `TASKS.md` requires choose-and-justify | -| **salient push** channel: ntfy vs Discord | T3 | both named in `TASKS.md` | +| **salient push** channel: ntfy vs Discord | T3 | **converging → MVP: direct Discord (discord.py), two-way**; multi-platform frameworks (LangBot) deferred. See `exploration/gateway-selection.md` | ## Open explorations (pre-decision) @@ -89,6 +89,7 @@ Evaluations still in motion live in `exploration/` and resolve into ADRs. | Note | Status | About | |---|---|---| | `exploration/substrate-selection.md` | converging | the substrate ladder beyond Melvor; Stardew Valley as a strong M0 candidate (native dual-control via co-op) | +| `exploration/gateway-selection.md` | converging | operator↔agent channel; MVP = direct two-way Discord (`discord.py`); frameworks deferred | ## Governance / ops track (parallel to the product) diff --git a/exploration/gateway-selection.md b/exploration/gateway-selection.md new file mode 100644 index 0000000..1d34569 --- /dev/null +++ b/exploration/gateway-selection.md @@ -0,0 +1,93 @@ +--- +topic: gateway-selection +status: converging +date: 2026-06-03 +related-adrs: [adr-0006] +resolves-to: +--- + +# Gateway selection — the operator↔agent async channel + +> Status: **converging**. The MVP channel is decided (direct Discord, two-way); +> the multi-platform *framework* choice is deferred. Resolves into an ADR. + +## Question + +What carries the **dyad's async channel** — operator ↔ agent, including the +agent's **self-initiated salient push** — for Milestone 0, and later? + +## First: two different things are both called "gateway" + +| Sense | Examples | Relevance | +|---|---|---| +| **IM / message gateway** — operator↔agent chat | OpenClaw, AstrBot, LangBot, NoneBot2, direct discord.py | **this note** | +| **LLM API gateway** — provider proxy / routing | LiteLLM, Bifrost, Kong | a *different* layer — future cloud/local **model routing** (ADR-0006 rule 6), not the dyad channel | + +Don't conflate them. This note is the IM channel. + +## Criteria + +| Criterion | Why | +|---|---| +| Async + **Discord** | the dyad's stated channel (operator acts async via Discord) | +| **Agent-initiated push** | agent self-judges salience and *pushes* — most bots are reply-only; this is the decisive, unusual requirement (T3/T5) | +| Self-host + local model | the record is private (ADR-0005) — keep the channel self-hosted | +| **Transport, not brain** | L3 cognition is the custom IP; the channel must not impose its own agent/LLM loop | +| 1:1 dyad | single operator, single agent, single platform — multi-platform/multi-user is *not* an MVP need | +| Python co-location | L3 is Python (ADR-0006); a Python channel shares its process domain | + +## Options & evaluation + +| Option | Type / lang | Discord | Transport-not-brain | Agent push | Self-host | Ops cost | Fit | +|---|---|---|---|---|---|---|---| +| **direct discord.py** | thin lib / Python | ✓ | **✓ purest** (you own it) | **✓ native** (`channel.send` anytime) | ✓ | **low for 1 platform** | **MVP** | +| **LangBot** | IM↔backend **bridge** / Python, Apache-2.0 | ✓ (10+) | ✓ (designed to front your backend) | event-driven, supports outbound | ✓ Ollama | medium | best *framework* when multi-platform is needed | +| **AstrBot** | agentic IM infra / Python, 33k★ | ✓ | △ wants to be the agent (own LLM/persona/RAG) | needs a plugin to emit | ✓ | lowest (WebUI+Docker) | ops-heavy turnkey; overkill at 1:1 | +| **NoneBot2** | low-level bot **framework** / Python | ✓ | ✓ you control all | ✓ framework-level | ✓ | high (write it all) | if direct discord.py outgrows itself | +| **OpenClaw** | full agent app / TS+Electron | ✓ (+ many) | △ bundles its own runtime | runtime-coupled | ✓ | high (Electron/sandboxes) | its real strength is the browser/CDP harness, not a pure channel | +| **ntfy** | one-way push service | ✗ (no chat) | ✓ | ✓ push-only | ✓ | minimal | only if the channel were one-way | + +## Sub-decision: one-way vs two-way → **two-way** + +The `salient push: ntfy vs Discord` gate (ROADMAP) reduces to this. The dyad form +— *operator can also act / converse async* — needs **two-way**, so the minimal +one-way pusher (ntfy) is out for MVP. The channel is **Discord, two-way**. + +## Current lean / MVP decision + +**MVP = a direct, thin Discord bot (discord.py), two-way.** Operator DMs/channels +the agent; the agent replies *and* pushes when it self-judges an entry salient. + +Why direct over a framework, for MVP: + +- The dyad is **1 operator / 1 agent / 1 platform** — the multi-platform gateways' + main value (many platforms, many users, a WebUI control plane) solves a problem + the MVP doesn't have. +- **Agent-initiated push** — the decisive requirement — is trivial and fully under + our control with `discord.py` (`channel.send()` / DM anytime); a framework only + adds indirection between the drive layer and the wire. +- **Transport-not-brain** is purest with a direct lib: zero framework cognition to + fight the custom L3. +- Python `discord.py` **co-locates with the Python L3** (ADR-0006). +- Cost is small for a single platform. + +**Deferred (not MVP):** adopt a framework when multi-platform reach or an ops/WebUI +control plane is actually needed. **LangBot** is the front-runner then — it is +explicitly an *IM↔your-backend bridge* (transport-not-brain), Apache-2.0, event- +driven, 10+ platforms, and even lists openclaw/hermes as pluggable backends. + +## Open items + +- Agent-push via `discord.py` is a known capability (low risk) — no spike needed; + a smoke test in T3/T5 suffices. +- Formalize the MVP channel decision as an ADR (channel = direct Discord, two-way; + frameworks deferred) and set this note `resolved`. +- Revisit the framework choice (LangBot) only when multi-platform/ops is real. +- Keep the IM gateway distinct from the future **LLM API gateway** (model routing). + +## Sources + +- [AstrBot](https://github.com/AstrBotDevs/AstrBot); [LangBot](https://github.com/langbot-app/LangBot); [LangBot site](https://langbot.app/en) +- [OpenClaw vs Hermes comparison](https://innfactory.ai/en/blog/openclaw-vs-hermes-agent-comparison/); [OpenClaw browser harness](https://openclawlaunch.com/guides/openclaw-browser-harness) +- [7 open-source frameworks for AI bots on messaging platforms (2026)](https://aibotbuilder.hashnode.dev/7-open-source-frameworks-for-deploying-ai-bots-to-messaging-platforms-in-2026) +- LLM API gateways (different layer): [open-source LLM gateways self-hosted 2026](https://www.getmaxim.ai/articles/5-best-open-source-llm-gateways-for-self-hosted-deployments-in-2026/) From 1a404f3cab4a1cf0a9bcabd89d22e5b134f386dd Mon Sep 17 00:00:00 2001 From: cyber-ayi <259769279+cyber-ayi@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:32:49 -0700 Subject: [PATCH 2/2] docs(exploration): MVP comms tool = AstrBot over Discord (operator direction) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revises the gateway note toward AstrBot (was: direct discord.py). - AstrBot is the MVP communication tool, two-way over Discord: message I/O + WebUI ops console + Docker + a ready proactive-send pipeline + multi-platform headroom. Both decisive capabilities confirmed — agent-initiated push (event+ scheduler send pipeline; astrbot_plugin_proactive_chat precedent) and custom backend (OpenAI-compatible provider + plugin framework, Python, co-locates w/ L3). - Discipline recorded: transport-not-brain. AstrBot ships its own LLM/persona/RAG; L3 must stay the brain. Preferred integration = a thin plugin bridge that bypasses AstrBot's LLM pipeline; alternative = L3 as an OpenAI-compatible provider with AstrBot's session/persona disabled. discord.py kept as the thin fallback. - One open spike before committing T3/T5: pick the integration path and confirm AstrBot's context layer can be fully bypassed so L3 is the sole brain. - ROADMAP — channel gate + Open explorations updated to AstrBot. Session-Id: 019e8d56-605a-7b45-8ef0-21ee576aa7a9 Agent: cc-rc-bot Co-authored-by: cyber-ayi <259769279+cyber-ayi@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) --- ROADMAP.md | 4 +- exploration/gateway-selection.md | 69 ++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 262eab4..045c643 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -80,7 +80,7 @@ Each downstream task carries its own small decision-gate. None block T1. | harness **runtime**: OpenClaw vs ElizaOS vs Hermes | T2 / T5 | candidates listed in `harness/README.md`, unchosen | | **IPC transport** TS↔Python (how JSON crosses the seam) | T5 | explicitly deferred by ADR-0006 | | Melvor **act path**: mod API vs CDP / headless-Chromium | T2 | `TASKS.md` requires choose-and-justify | -| **salient push** channel: ntfy vs Discord | T3 | **converging → MVP: direct Discord (discord.py), two-way**; multi-platform frameworks (LangBot) deferred. See `exploration/gateway-selection.md` | +| **salient push** channel: ntfy vs Discord | T3 | **converging → MVP: AstrBot over Discord, two-way** (transport-not-brain; `discord.py` fallback). See `exploration/gateway-selection.md` | ## Open explorations (pre-decision) @@ -89,7 +89,7 @@ Evaluations still in motion live in `exploration/` and resolve into ADRs. | Note | Status | About | |---|---|---| | `exploration/substrate-selection.md` | converging | the substrate ladder beyond Melvor; Stardew Valley as a strong M0 candidate (native dual-control via co-op) | -| `exploration/gateway-selection.md` | converging | operator↔agent channel; MVP = direct two-way Discord (`discord.py`); frameworks deferred | +| `exploration/gateway-selection.md` | converging | operator↔agent channel; MVP = AstrBot over Discord, two-way (transport-not-brain; `discord.py` fallback) | ## Governance / ops track (parallel to the product) diff --git a/exploration/gateway-selection.md b/exploration/gateway-selection.md index 1d34569..6c3b8be 100644 --- a/exploration/gateway-selection.md +++ b/exploration/gateway-selection.md @@ -8,8 +8,9 @@ resolves-to: # Gateway selection — the operator↔agent async channel -> Status: **converging**. The MVP channel is decided (direct Discord, two-way); -> the multi-platform *framework* choice is deferred. Resolves into an ADR. +> Status: **converging**. MVP comms tool = **AstrBot** over Discord, two-way +> (operator direction), used transport-not-brain. One open spike: the L3 +> integration path. Resolves into an ADR. ## Question @@ -40,9 +41,9 @@ Don't conflate them. This note is the IM channel. | Option | Type / lang | Discord | Transport-not-brain | Agent push | Self-host | Ops cost | Fit | |---|---|---|---|---|---|---|---| -| **direct discord.py** | thin lib / Python | ✓ | **✓ purest** (you own it) | **✓ native** (`channel.send` anytime) | ✓ | **low for 1 platform** | **MVP** | +| **direct discord.py** | thin lib / Python | ✓ | **✓ purest** (you own it) | **✓ native** (`channel.send` anytime) | ✓ | **low for 1 platform** | fallback — thinnest if AstrBot is too heavy | | **LangBot** | IM↔backend **bridge** / Python, Apache-2.0 | ✓ (10+) | ✓ (designed to front your backend) | event-driven, supports outbound | ✓ Ollama | medium | best *framework* when multi-platform is needed | -| **AstrBot** | agentic IM infra / Python, 33k★ | ✓ | △ wants to be the agent (own LLM/persona/RAG) | needs a plugin to emit | ✓ | lowest (WebUI+Docker) | ops-heavy turnkey; overkill at 1:1 | +| **AstrBot** | agentic IM infra / Python, 33k★ | ✓ | △ has own LLM/persona/RAG — must bypass via plugin so L3 stays the brain | **✓ via plugin** (event+scheduler send pipeline; `astrbot_plugin_proactive_chat` precedent) | ✓ Ollama/LM Studio | lowest (WebUI+Docker) | **MVP (operator choice)** — WebUI console + multi-platform-ready | | **NoneBot2** | low-level bot **framework** / Python | ✓ | ✓ you control all | ✓ framework-level | ✓ | high (write it all) | if direct discord.py outgrows itself | | **OpenClaw** | full agent app / TS+Electron | ✓ (+ many) | △ bundles its own runtime | runtime-coupled | ✓ | high (Electron/sandboxes) | its real strength is the browser/CDP harness, not a pure channel | | **ntfy** | one-way push service | ✗ (no chat) | ✓ | ✓ push-only | ✓ | minimal | only if the channel were one-way | @@ -55,34 +56,44 @@ one-way pusher (ntfy) is out for MVP. The channel is **Discord, two-way**. ## Current lean / MVP decision -**MVP = a direct, thin Discord bot (discord.py), two-way.** Operator DMs/channels -the agent; the agent replies *and* pushes when it self-judges an entry salient. - -Why direct over a framework, for MVP: - -- The dyad is **1 operator / 1 agent / 1 platform** — the multi-platform gateways' - main value (many platforms, many users, a WebUI control plane) solves a problem - the MVP doesn't have. -- **Agent-initiated push** — the decisive requirement — is trivial and fully under - our control with `discord.py` (`channel.send()` / DM anytime); a framework only - adds indirection between the drive layer and the wire. -- **Transport-not-brain** is purest with a direct lib: zero framework cognition to - fight the custom L3. -- Python `discord.py` **co-locates with the Python L3** (ADR-0006). -- Cost is small for a single platform. - -**Deferred (not MVP):** adopt a framework when multi-platform reach or an ops/WebUI -control plane is actually needed. **LangBot** is the front-runner then — it is -explicitly an *IM↔your-backend bridge* (transport-not-brain), Apache-2.0, event- -driven, 10+ platforms, and even lists openclaw/hermes as pluggable backends. +**MVP = AstrBot as the communication tool** (operator direction), two-way over +Discord. AstrBot provides the message I/O, a WebUI ops console, Docker deploy, and +a ready proactive-send pipeline; the operator gets a real control plane and +multi-platform headroom from day one. + +Both decisive capabilities are confirmed: +- **Agent-initiated salient push** — AstrBot's event+scheduler send pipeline + supports bot-initiated messages (the `astrbot_plugin_proactive_chat` plugin is a + working precedent). The L3 calls this to push when it judges an entry salient. +- **Custom backend** — AstrBot takes a custom LLM provider via an OpenAI-compatible + interface, and a plugin framework for bespoke logic. Python — co-locates with the + Python L3 (ADR-0006). + +**The discipline that makes this work — transport-not-brain.** AstrBot ships its own +LLM loop, persona, RAG, and context-compression; the project's **L3 must stay the +brain**. Integrate so AstrBot's cognition is bypassed, not stacked on top of L3: + +- **Preferred — plugin bridge:** a thin AstrBot plugin forwards inbound operator + messages to L3 and uses the send API for L3's outbound/proactive pushes. AstrBot's + LLM pipeline is bypassed entirely; it is pure I/O + ops console. +- **Alternative — provider:** wrap L3 behind an OpenAI-compatible endpoint and + register it as AstrBot's provider, with AstrBot's own session/persona/context + features **disabled** so L3's memory/identity stays authoritative (else you get + two competing memory layers). + +**Fallback:** if AstrBot proves too heavy or its cognition can't be cleanly bypassed, +drop to a **direct `discord.py`** bot (thinnest, purest transport-not-brain). The +evaluation above stands; only the chosen tool changes. ## Open items -- Agent-push via `discord.py` is a known capability (low risk) — no spike needed; - a smoke test in T3/T5 suffices. -- Formalize the MVP channel decision as an ADR (channel = direct Discord, two-way; - frameworks deferred) and set this note `resolved`. -- Revisit the framework choice (LangBot) only when multi-platform/ops is real. +- **Spike: pick the integration path** (plugin bridge vs provider) and confirm + AstrBot's own context/persona layer can be fully bypassed so L3 is the sole brain. + This is the one real risk — verify before committing T3/T5 to AstrBot. +- Confirm proactive push works end-to-end (L3 → AstrBot send → operator) with a + smoke test in T3/T5. +- Formalize as an ADR once the integration path is validated (channel = AstrBot + over Discord, two-way, transport-not-brain), then set this note `resolved`. - Keep the IM gateway distinct from the future **LLM API gateway** (model routing). ## Sources