Skip to content

Repository files navigation

MultiAgency Contributor Task-Routing Bot

A Telegram bot that runs MultiAgency's live task board:

  • Contributors onboard with /start, pick their roles (video editing, writing, design, amplification, research, community), and get notified the moment a matching task goes live.
  • Admins post tasks with /newtask — a guided flow that captures a full spec (deadline, references, specs, assets, definition of done) so no task goes out vague. The bot broadcasts each task only to contributors with the matching role.
  • Claiming is first-come-first-served up to the slot limit, with live slot counters edited into every broadcast message — no over-claiming. Contributors see the complete standard before they claim.
  • Submissions come back through /submit (link or file) and land with every admin as pending review, with Accept / Request changes buttons. Nothing counts as done until an admin accepts it.
  • Track record: every contributor builds a history (accepted tasks, change requests, acceptance rate) visible via /profile (their own) and /contributors (admin roster).
  • Tiers (optional): contributors climb 🌱 New → ⭐ Proven → 🏆 Core as work gets accepted; tasks can be reserved for higher tiers. Toggle with /tiers on|off.
  • Amplification: accepted work gets a Route for amplification button — one tap creates a new task for the post-maker role and broadcasts it.
  • AI agent (optional): with a NEAR AI Cloud key, an agent watches the coordination group, reasons about what work is worth creating (via Claude), and drafts complete task briefs for an admin to approve, edit, or discard. It proposes; humans decide. See Agentic layer.

Built with python-telegram-bot v21 (async) and SQLite. The core bot needs only a bot token; the AI agent additionally uses NEAR AI Cloud (an OpenAI-compatible endpoint) with Claude as the reasoning model.

Project layout

File What it does
bot.py All handlers and wiring — run this
db.py SQLite schema and queries (atomic claim logic lives here)
messages.py Every bot-facing message, in MultiAgency's voice
config.py Roles list, env loading, validation, agent settings
agent.py The AI agent: NEAR AI Cloud + Claude reasoning and drafting

Setup

1. Create the bot — talk to @BotFather on Telegram, /newbot, and copy the token.

2. Get admin IDs — each admin messages @userinfobot and notes the numeric ID it replies with.

3. Configure — copy .env.example to .env and fill it in:

BOT_TOKEN=123456:ABC-your-token-here
ADMIN_IDS=123456789,987654321

4. Install and run (Python 3.11+):

python -m venv .venv
# Windows:            .venv\Scripts\activate
# macOS/Linux:        source .venv/bin/activate
pip install -r requirements.txt
python bot.py

The bot uses long polling — no webhook, domain, or open port required. The SQLite database (multiagency.db) is created automatically on first run.

5. Smoke-test it — from your own Telegram account: /start, pick a role, then (as an admin) /newtask and post a task for that role. You should receive the offer with a Claim button.

Changing the roles list

Edit the ROLES dict in config.py. Keys are stored in the database (keep them short, no :), labels are what contributors see. Adding or removing roles is safe for existing data.

Commands

Contributors: /start join · /roles change roles · /mytasks claimed tasks · /submit hand in work · /profile track record and tier · /cancel back out of any flow · /help

Admins: /newtask post a task · /draft <idea> have the AI agent draft a task for you · /tasks status board (open / fully claimed / closed / done, with claim and review counts) · /contributors roster with track records · /tiers on|off toggle tier gating · /close <id> stop new claims · /onboard (in a group the bot is in) post a registration pitch with a button that deep-links members into the bot's DM. Reviewing, amplification, and approving agent proposals all happen via buttons on the messages the bot sends you.

All other commands only respond in the bot's DM, so adding the bot to a group won't create noise there.

Posting a structured task (admins)

/newtask walks you through ten steps; the task cannot be broadcast until the required ones are filled:

# Field Required
1 Title
2 Role ✅ (buttons)
3 Reward
4 Claim slots
5 Deadline
6 Description — what's needed
7 Reference/inspiration links optional (Skip button)
8 Specs — format, dimensions, tone, brand elements optional (Skip)
9 Assets provided — raw materials, logos optional (Skip)
10 Definition of done — the acceptance checklist

If tiers are on, one extra step asks who can claim (open to all / ⭐ Proven+ / 🏆 Core only). You then see the task exactly as contributors will and confirm with Post it. Contributors receive the complete spec in the broadcast and again in their claim confirmation, and reviews are held against the definition of done.

Review gate & track record

Submitting never completes a task. Every submission arrives as pending review; only an admin's Accept marks it complete (and the task flips to done once every slot has accepted work). Request changes sends your feedback to the contributor verbatim and reopens their claim so they can resubmit against the same task.

Each accept/change-request builds the contributor's record — accepted count, change requests, acceptance rate — computed live from history (nothing to maintain). Contributors see theirs with /profile; admins see everyone with /contributors.

Tiers (quality-gated access)

Contributors climb tiers as work gets accepted:

Tier Default threshold
🌱 New 0 accepted
⭐ Proven 3 accepted
🏆 Core 10 accepted
  • Toggle at runtime: /tiers on / /tiers off (admin, no redeploy needed; stored in the database). When off, every task is open to anyone with the matching role and the tier step is skipped in /newtask.
  • Thresholds: set env vars TIER_PROVEN_AT / TIER_CORE_AT, or edit the TIERS list in config.py (names, count, and thresholds are all yours to change).
  • Tier-restricted tasks are only broadcast to eligible contributors, and the claim button double-checks eligibility — someone below the tier gets a friendly note showing exactly how many accepted tasks away they are.

Agentic layer (AI-drafted tasks)

The agent turns the bot from a manual routing tool into an agentic coordination system: it watches the coordination group, reasons about what work is worth doing, and drafts structured briefs — but never routes anything itself. Every draft is proposed to an admin who approves, edits, or discards it. All reasoning runs through Claude on NEAR AI Cloud.

Configure it

Add to your .env (the bot runs fine without these — the agent just stays off):

# Your NEAR AI Cloud key — get one at https://cloud.near.ai
NEAR_AI_API_KEY=sk-...

# The coordination group the agent watches (a negative chat id).
COORD_GROUP_ID=-1001234567890

Finding the group id: add the bot to your coordination group, send any message there, and the bot logs the chat id — or forward a group message to @userinfobot. Optional overrides:

Variable Default Meaning
NEAR_AI_MODEL anthropic/claude-sonnet-4-5 The Claude model NEAR AI Cloud exposes (see its /models list)
NEAR_AI_BASE_URL https://cloud-api.near.ai/v1 OpenAI-compatible endpoint
AGENT_OBSERVE_EVERY 12 Group messages to accrue before it considers proposing
AGENT_MIN_INTERVAL_MIN 45 It never proposes more often than this — keeps it non-spammy

On startup the log line tells you the agent's state (Agent enabled … / Agent disabled …). Each admin who wants to use the agent should have started the bot in DM at least once.

How it surfaces work

  1. Observe. The agent reads messages in the coordination group and buffers them. Once AGENT_OBSERVE_EVERY fresh messages have landed and the rate-limit window has passed, it asks Claude whether the recent chatter is a genuine signal that work should be commissioned — a builder shipping something, a launch, an explicit "we should make something on this." Banter and vague ideas are deliberately ignored; it errs toward silence.
  2. Draft. When it decides something's worth doing, Claude drafts a complete brief in the same structured format /newtask produces — title, role, suggested reward, deadline, description, references, specs, and a concrete definition of done.
  3. Propose. The agent posts the draft into the group with ✅ Approve & route, ✏️ Edit, and 🗑 Discard buttons, plus a one-line reason it thinks it's worth doing. Nothing has reached contributors yet.
  4. Human approves. An admin taps:
    • Approve → the draft becomes a real task and broadcasts to matching contributors through the normal flow (role routing, slots, review gate).
    • Edit → the admin replies in plain language ("make it 2 slots, raise the reward to 40 USDC, tighten the deadline") and Claude revises the draft in place; approve when it's right.
    • Discard → gone, no noise.

Draft on demand

Admins can also ask directly, in the group or in DM:

/draft a 60s recap video of the Korea meetup
/draft a launch-day thread for the new vault

Claude returns a full structured brief with the same Approve / Edit / Discard controls — fast task creation even when a human starts it.

Amplification suggestions

When you accept a submission, the agent considers (via Claude) whether the work is worth amplifying. If it is, it drafts an amplification task for the post-making role and proposes it for your approval — the same human-owned gate. This is in addition to the manual Route for amplification button, which still works exactly as before.

Guardrails

  • The agent proposes; humans approve. No task reaches contributors without an admin's Approve. Approvals are admin-only and idempotent (a second tap on an already-handled draft is refused).
  • Rate-limited. It won't propose more often than AGENT_MIN_INTERVAL_MIN, and only after enough real activity — it surfaces worthwhile work, not everything.
  • Fails quietly. If NEAR AI Cloud is unreachable or returns something unusable, the agent simply says nothing; the rest of the bot is unaffected.
  • The key never touches the code. It's read from the environment only.

Deployment (keeping it online)

The bot is a single long-running process. Any always-on host works; three good options:

Option A — Railway (easiest)

  1. Push this folder to a GitHub repo (.gitignore already excludes .env and the database).
  2. On railway.app: New Project → Deploy from GitHub repo.
  3. Set start command to python bot.py, and add BOT_TOKEN and ADMIN_IDS as environment variables in the service settings.
  4. Add a volume mounted at /data and set DB_PATH=/data/multiagency.db so the database survives redeploys.

Render, Fly.io, and similar platforms work the same way — it's a background worker (not a web service), so pick that service type where offered.

Option B — any Linux VPS with systemd

# on the server
git clone <your repo> /opt/multiagency-bot && cd /opt/multiagency-bot
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
cp .env.example .env && nano .env   # fill in token + admin IDs

Create /etc/systemd/system/multiagency-bot.service:

[Unit]
Description=MultiAgency Task-Routing Bot
After=network-online.target

[Service]
WorkingDirectory=/opt/multiagency-bot
ExecStart=/opt/multiagency-bot/.venv/bin/python bot.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now multiagency-bot
journalctl -u multiagency-bot -f    # watch the logs

Restart=always brings the bot back automatically if it ever crashes or the server reboots.

Option C — Windows machine (for quick trials only)

python bot.py in a terminal works, but stops when the machine sleeps. Fine for testing; use A or B for production.

Data & backups

Everything lives in one SQLite file (multiagency.db): contributor profiles, tasks (including the spec fields deadline, refs, specs, assets, dod, min_tier), claims, submissions, runtime settings (the tiers switch and the agent's rate-limit timestamp), agent proposals (drafts and their approve/ discard status), and broadcast bookkeeping. Track records are derived from submission history at read time, so there are no counters to corrupt. Databases created before the Quality & Standards or agentic layers are migrated automatically on startup. Back it up by copying the file while the bot is stopped (or use sqlite3 multiagency.db ".backup backup.db" live). If you outgrow SQLite, the query layer is isolated in db.py, so a Postgres migration touches one file.

Error handling notes

  • Claiming a full or closed task → polite "just missed it" message; the broadcast's slot counter is corrected.
  • Double-claiming → "you already have a slot" reminder.
  • Submitting to a task you didn't claim → blocked (only your active claims are offered in /submit).
  • Two admins reviewing the same submission → second one gets "already handled".
  • Contributors who blocked the bot are skipped during broadcasts and logged.
  • Any unexpected exception is logged and the user gets a friendly retry note.

About

MultiAgency: a Telegram task-routing bot with an agentic AI layer (Claude via NEAR AI Cloud) that drafts and proposes contributor tasks for admin approval.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages