contenox
Browse docs/

The MVP: Telegram and GitHub bots on one chain engine

contenox/mvp was the proof that “Co-Pilots” and “Bots” were the same problem wearing two faces. One Go service split into a standalone runtime — the model-orchestration and task-engine kernel, already published as its own container image and Go module — and a gateway layered on top carrying everything MVP-specific: users and JWT auth, a Postgres-backed job queue with lease-based dispatch, a Vald-backed RAG pipeline over uploaded documents, and two live bridges out to the world. A React admin dashboard, proxied through the same gateway, let an operator upload documents, wire up bots, and watch jobs move.

The two bridges shared everything except the wire format on either end. A Telegram poller ticked against every registered bot frontend, called getUpdates, and turned each message into a job keyed to a per-chat-per-user subject; the job’s payload carried a chain ID assigned to that frontend, so processing it meant loading that chain, replaying the subject’s stored chat history through it, and sending the model’s reply straight back over the Bot API. Independently, a GitHub worker polled every connected repo’s open PRs, diffed new comments against what was already stored for that PR, and turned each new human comment into its own job — while a brand-new PR, or a comment containing /review, additionally queued a full-diff code-review job. Both landed on bot records carrying their own TaskChainID, ran through the identical envService.Execute call, and posted back through PostComment with a small “Generated by contenox” footer. Same lease-based Postgres queue, same chain-execution call, two unrelated integrations plugged into it — and neither needed an inbound webhook: both bridges ran outbound-only, polling on a tick, deployable behind a firewall with nothing but a bot token or a PAT in the environment.

Running it meant standing up the full shape: two Postgres databases (one behind the extracted runtime, one for the gateway’s own bots, jobs, users and chat history), NATS for pubsub, Valkey for KV state, a gRPC tokenizer microservice, Vald for the document vector index, and model routing to Ollama, vLLM, OpenAI, or Gemini through a pluggable provider library. The chains themselves were already the same shape they are today — named tasks, typed handlers, branching transitions on operators like > and equals, hook calls and model-execution steps chained together and addressed by ID — running a moderation classifier ahead of the model call on every turn, Telegram and GitHub alike.

What it proved

  • One dispatch substrate, two unrelated bridges, zero forked logic. The same lease-based job queue and the same chain-execution call drove a real-time Telegram chat and a fully autonomous GitHub PR watcher — the only bot-specific code was turning an external event into a job and a job’s result into a reply.
  • A GitHub bot that behaved like a careful reviewer, not a spam account. It diffed comments against stored per-PR history before acting, ran a full-diff code review automatically on every new PR, and let a human retrigger one explicitly with /review — all polling-based, no webhook required.
  • The chain format was already the shipped shape. Named tasks, typed handlers, branching operators, hook calls, and model-execution steps composed into an addressable chain by ID — the same vocabulary the runtime’s chains use today.
  • The core was already being extracted. The runtime this MVP ran alongside wasn’t vendored code — it was a separately versioned dependency (github.com/contenox/runtime, tagged v0.0.51) that the gateway imported like any third-party library, months before that split became the deliberate architecture pivot.

The review that reviewed itself

The GitHub bot’s own implementation arrived as a pull request. Posting /review on that pull request triggered the platform to launch a code-review bot against the code that created it: minutes later the bot had posted an analysis of its own implementation — naming the components, describing the architecture, and flagging issues in the change that had just introduced it.

A pull request comment reading /review, answered minutes later by contenox-bot with a structured analysis of the GitHub Code Review Processor — the very feature that pull request introduced

It was the loudest thing this project ever did. The question it raised in public — whether software can eventually develop and maintain itself — is still open, and the answer this codebase eventually settled on is the one contenox ships today: not autonomy, but bounded autonomy a human signs.

Where this lives now

The chain format this MVP ran is the one contenox executes today. And its two bridges — an external surface catching events on one side, driving a chain on the other — became the shape of contenox mcp add and contenox tools add for tools, and contenox acp for an external driver running a chain over a protocol instead of a bot token.

Esc to close