A local-first support agent for founders and maintainers who answer users in Telegram.
It lets Codex or Claude search your Telegram support history, website/docs, manual support notes, and optional repo evidence. It can answer support analytics questions and draft evidence-backed replies, but it only posts to Telegram after explicit operator confirmation.
No hosted helpdesk. No SaaS support inbox. Telegram sessions, SQLite metadata, retrieval indexes, drafts, and confirmation records stay on your machine.
Search Telegram support history, local docs, and repo evidence. Draft a reply. Post only after explicit confirmation.
Clipped with codex-clip-idle.
This is for people who already run support inside Telegram:
- solo founders answering users directly
- maintainers of developer tools
- small SaaS teams without a hosted helpdesk
- support engineers who need local searchable context
- projects where support data should stay on the operator's machine
- Syncs a configured Telegram support chat into a local profile.
- Crawls website/blog/docs seeds for support knowledge.
- Builds local hybrid search with SQLite FTS5 + sqlite-vec.
- Uses local embeddings for semantic retrieval.
- Searches live repository evidence for product/API/debugging questions.
- Creates evidence-backed reply drafts.
- Requires explicit confirmation before posting to Telegram.
- Works from Codex, Claude, or the
tg-supportCLI.
This project is not designed to autonomously answer users.
It is an operator-assist workflow: the agent can search, summarize, and draft replies, but posting requires an explicit confirmation. This keeps the risky action — writing to Telegram — behind a deterministic local CLI boundary.
For Codex, add the plugin marketplace and install the plugin:
codex plugin marketplace add igorrendulic/tg-customer-support-plugin
codex plugin add telegram-support-agent@tg-customer-support-pluginAfter install, run the agent setup flow:
$telegram-support-agent setupSetup asks four questions:
- Telegram channel, for example
my-support-chat. - Website, for example
https://example.com. - Repository and branch, for example
https://github.com/owner/projectandproduction. If you leave the branch blank, it defaults tomain. - Operator identities, for example
founderhandle,supportlead. These are the support operators whose replies should be treated as official answers rather than user or community messages.
Next, setup tells you to create Telegram API credentials:
- Go to
https://my.telegram.org. - Open API development tools.
- Create an app.
- Copy the API ID and API hash back into the setup flow.
The API hash is stored locally under ~/.tg-support and is not printed back in normal output.
After credentials are saved, the agent logs in to Telegram, syncs support history, crawls the configured website, clones the configured repository for read-only evidence.
Once indexing finishes, ask normal support questions:
$telegram-support-agent stats
$telegram-support-agent "What could operators improve in their answers?"
$telegram-support-agent "answer latest user message"
$telegram-support-agent "answer user somehandle_or_display_name"For local development, clone the repo and install the package with dev and retrieval dependencies:
git clone <repo-url>
cd tg-support-plugin
python3 -m venv .venv
.venv/bin/pip install -e ".[retrieval,dev]"Add Telegram and browser-rendering adapters when you need real Telegram login or Playwright crawling:
.venv/bin/pip install -e ".[telegram,render,retrieval,dev]"Create a local profile with one Telegram chat. Website or blog seeds are optional:
scripts/tg-support --profile default setup \
--chat my-support-chatOptionally add website or blog seeds for public support resources:
scripts/tg-support --profile default setup \
--chat my-support-chat \
--seed https://example.com/blogOptionally add one or more operator identities so Support Exchanges can distinguish configured support answers from peer/community replies:
scripts/tg-support --profile default setup \
--chat my-support-chat \
--operator firstoperator \
--operator secondoperatorOptionally add a GitHub repository and branch for code-grounded behavior or debugging answers. The branch defaults to main when omitted. This uses your existing local git or gh authentication; do not paste GitHub credentials into the support workflow.
scripts/tg-support --profile default setup \
--chat my-support-chat \
--seed https://example.com/blog \
--repository owner/projectThen build the local corpus:
scripts/tg-support --profile default credentials --api-id 123456
scripts/tg-support --profile default login
scripts/tg-support --profile default sync
scripts/tg-support --profile default crawl
scripts/tg-support --profile default index
scripts/tg-support --profile default statuscrawl follows same-scope links two levels deep by default. Use --depth 0 to crawl only configured seed URLs.
index creates source-linked documents, Support Exchanges, an FTS5 exact-term index, and a 384-dimensional sqlite-vec vector index for BAAI/bge-small-en-v1.5. Support Exchanges separate requester text, configured operator replies, peer/community replies, and unanswered questions so adjacent chat messages are not treated as one author's document. If the retrieval dependencies, embedding model, or local SQLite extension loading are not available, the command returns JSON with ok: false, the SQLite version when relevant, and next_action instead of silently falling back to weaker search.
Ask questions or prepare a reply draft:
scripts/tg-support --profile default search "password reset issues"
scripts/tg-support --profile default repo-evidence "account transfer api"
scripts/tg-support --profile default stats active-users
scripts/tg-support --profile default draft-context --user alice
scripts/tg-support --profile default draft-create --message-id 123 --text "Thanks, try the reset link here..."Repository Evidence is live and branch-specific rather than indexed. Use it for product-behavior, capability, API-behavior, or debugging questions. If the checkout cannot refresh, the CLI returns a stale warning so the agent can tell the operator that cited code may be outdated.
draft-context returns evidence sufficiency metadata with the evidence bundle. When evidence supports a direct answer, the agent should draft the direct reply. When evidence is missing, weak, conflicting, or needs private/account-specific details, the agent should offer both a cautious evidence-limited answer and a DM follow-up asking for the missing information. DM follow-up wording is not Manual Knowledge and is not evidence.
When evidence includes a Support Exchange, configured operator replies can support direct answers. Peer/community replies and unanswered exchanges are context unless corroborated by Manual Knowledge, Repository Evidence, web evidence, or another authoritative source.
Save dated support knowledge through Codex after reviewing the parsed fields, or directly through the CLI after the operator has confirmed the note:
scripts/tg-support --profile default knowledge-add \
--text "Account transfers were discontinued. Users must register a new email address." \
--effective-date 2026-04-02 \
--caveats "Old email addresses are quarantined until further notice."
scripts/tg-support --profile default indexActive manual knowledge can appear in search or draft evidence ahead of older Telegram and web sources. If returned JSON includes conflicts, show the manual note and the competing evidence to the operator before answering or drafting.
Posting is intentionally a separate confirmed action. Show the operator the exact draft, target, and evidence first, then use the generated post or cancel token:
scripts/tg-support --profile default confirm <post_or_cancel_token>Local profile data lives outside the source tree by default:
~/.tg-support/profiles/<profile>/
That profile directory contains the profile config, optional repository checkout state, Telegram API credentials, Telegram session file, SQLite database, and rebuildable indexes. Treat it as sensitive local state.
Set TG_SUPPORT_HOME to move profile data elsewhere.
Existing local profiles created with an older embedding model must be recreated or edited before use. The CLI intentionally rejects unsupported embedding_model values instead of mixing incompatible vector dimensions in the same profile.
flowchart LR
TG[Telegram Support Chat] --> SYNC[tg-support sync]
WEB[Website / Blog / Docs] --> CRAWL[tg-support crawl]
NOTES[Manual Knowledge Notes] --> DB[(SQLite Profile DB)]
SYNC --> DB
CRAWL --> DB
DB --> FTS[SQLite FTS5]
DB --> VEC[sqlite-vec]
REPO[Local GitHub Repo Checkout] --> EVIDENCE[Live Repo Evidence]
FTS --> CLI[tg-support CLI]
VEC --> CLI
EVIDENCE --> CLI
CLI --> CODEX[Codex Skill]
CLI --> CLAUDE[Claude Guidance]
CODEX --> DRAFT[Evidence-backed Draft]
CLAUDE --> DRAFT
DRAFT --> CONFIRM[Operator Confirmation Token]
CONFIRM --> POST[Post to Telegram]
The Codex skill lives in skills/telegram-support/. It uses the same scripts/tg-support commands as the CLI examples above and treats JSON CLI output as the source of truth for evidence, conflicts, draft IDs, and confirmation tokens.
Claude companion guidance is in agents/claude.md and docs/claude-usage.md. Claude should use the same local CLI and must not post directly or infer confirmation from casual approval.
The key safety boundary is deliberate: agent prompts can retrieve evidence and draft text, but only deterministic CLI code can consume a confirmation token and write to Telegram.
SQLite is the durable local metadata store. The SQLite Hybrid Search Index is a rebuildable projection linked back to Telegram messages, crawled pages, and Manual Knowledge Notes: FTS5 recovers exact product and policy terms, sqlite-vec handles vector candidates with local BAAI/bge-small-en-v1.5 embeddings, and answers cite source records instead of relying on agent memory.
Install dev dependencies:
python3 -m venv .venv
.venv/bin/pip install -e ".[retrieval,dev]"Run the test suite:
.venv/bin/pytestRun lint checks:
uv run --with ruff ruff check .Useful project files:
tg_support/cli.pydefines the command boundary.tg_support/storage/schema.pydefines the local SQLite shape.tg_support/support/drafting.pyandtg_support/support/posting.pyown the draft and confirmation flow.skills/telegram-support/SKILL.mddefines the Codex operator workflow.docs/solutions/captures durable architecture and workflow learnings.CONCEPTS.mddefines project vocabulary.
See CONTRIBUTING.md for contribution guidelines.