Catalog PyPI
PACKAGE EXPLORERView in registry

agents-relay

PyPI

HTTP and Telegram relay to agents-harness runner.loop (stdlib only)

agentsclicoding-assistantgatewayharnesshttprelaytelegram
Versions collected1
Direct dependencies0From release 0.1.0
Last observed20 Oct, 23:28 UTC

README

Version 0.1.0 documentation

agents-relay

Version 0.1.0 Python 3.10+ PyPI License

Stdlib HTTP and Telegram relay in front of agents-harness runner.loop.
One subprocess per turn. Trailer parsing for session metadata. No identity store, no traces, no writes under ~/.agents. Approval decisions and downloaded files live in the relay state dir (AGENTS_RELAY_STATE, default ~/.agents-relay).


Quickstart

pip install agents-relay

Needs runner.loop on PATH (LOOP_CMD, default python -m runner.loop). That comes from agents-harness 0.1.0 or newer (approvals, --detached-session, and the {user} approval substitution need it).

[!TIP] 🤖 Agent-Driven Setup: Give your coding agent this repo (clone or URL), then tell it to "install agents-relay and configure it to relay between your chat interface and agents-harness."


Architecture

ComponentResponsibility
HTTP AdapterServes /v1/turn and /v1/inject endpoints with secret header validation
Telegram AdapterLong-poll bot updates with real-time thinking status edits, parallel jobs, and Approve/Deny callbacks
Loop ClientSpawns buffered runner.loop subprocess per turn with trailer parsing and repeatable --attach
Outbound SendDirect Telegram push via agents-relay send for reminders and notifications
Approval Gateagents-relay approve asks an allowlisted chat and blocks on a decision file
  • Subprocess Isolation: One runner.loop process per request. No in-process LLM logic.
  • No harness state: No identity storage, no traces, no writes under ~/.agents. Relay files (approvals, inbox) stay in AGENTS_RELAY_STATE.
  • Streaming Status: Throttled progress streaming and real-time status edits during long-running tool rounds.
  • Zero Bloat: Pure Python standard library (http.server, urllib.request, subprocess).

Capabilities & Roadmap

Core Capabilities (Implemented)

  • HTTP Turn Endpoints (/v1/turn, /v1/inject): Buffered turn execution with secret header validation.
  • Telegram Long-Poll Gateway: Bot API updates with real-time thinking status message editing.
  • Direct Outbound CLI (send, inject, approve): Host-initiated push messages, simulated turns, and Telegram Approve/Deny for mutating tools.
  • Parallel Telegram jobs: Updates are dispatched off the poll thread. Per-chat cap (default 3) with a queue. /jobs, /stop, /stop <id> kill the loop process group.
  • Long replies: Split into several Telegram messages at paragraph boundaries with balanced HTML. No silent 4096 cut.
  • Attachments: Telegram photos and documents, and /v1/turn attachments, are passed to the loop as --attach.
  • Mobile Formatting: Automatic Markdown table conversion to Telegram-readable bullet lists.
  • Trailer Parsing: Extracts session, user ID, alias, and return code from harness stdout trailers.
  • Subprocess Isolation: One runner.loop process per request. No in-process LLM state.
  • Zero Bloat Runtime: Pure Python standard library only.

Planned (Roadmap)

  • SSE Token Streaming (/v1/stream): Direct server-sent events for client web UIs.
  • A2A Board Mailbox Proxy (/v1/a2a/mail, /v1/a2a/peers): Peer-to-peer agent relay for board instances.
  • Inbound Webhook Hub (/v1/webhook/{source}): Direct ingress for CI/CD and deployment alerts.
  • Multi-Channel Adapters: Signal / Discord gateway adapters alongside Telegram.

Commands

Machine-readable catalog: python -m agents_relay --help-json (do not scrape --help).

CommandPurpose
agents-relay serveHTTP /v1/turn, /v1/inject (and /v1/alert, /webhook/alert). Telegram long-poll if TELEGRAM_BOT_TOKEN is set
agents-relay serve --no-telegramHTTP only
agents-relay send --user <chat_id> --text "..."One outbound Telegram message (--chat-id alias). Allowlist + token from env
agents-relay inject --user <chat_id> --text "..."Same inbound handler as poll (thinking edits + final). JSON on stdout. Allowlist + token from env
agents-relay approve --user <chat_id> --timeout 300Read a tool-approval JSON object on stdin. Send Approve/Deny. Exit 0 approved, 1 denied, 2 timeout or unavailable. One JSON line on stdout: {"note":"..."}

Telegram chats can send /jobs, /stop, and /stop <id> while serve is polling. /stop kills that chat's runner.loop process group (the loop and child tools that stayed in the group).


Environment

VariableDescription
LOOP_CMDLoop argv (default python -m runner.loop)
LOOP_PROVIDERProvider name passed through (default echo)
RELAY_SECRETShared secret (GATEWAY_SECRET fallback). Empty = no auth
TELEGRAM_BOT_TOKENEnables poll + send
TELEGRAM_ALLOWED_CHAT_IDSComma-separated numeric IDs. Empty refuses the Telegram adapter unless AGENTS_RELAY_ALLOW_ANYONE=1
AGENTS_RELAY_ALLOW_ANYONE1 opts in to an empty allowlist. Logs a loud warning. Anyone who can message the bot can run turns and approve tools
AGENTS_RELAY_STATERelay files (default ~/.agents-relay). Approvals: $AGENTS_RELAY_STATE/approvals/<id>.json. Inbox: .../inbox/
AGENTS_RELAY_APPROVERChat id used by approve when --user is missing or not numeric (HTTP turns often pass anonymous)
AGENTS_RELAY_ATTACH_DIROnly local /v1/turn attachment paths under this directory are accepted (default: the relay state dir)
AGENTS_RELAY_MAX_JOBSGlobal cap on parallel Telegram turns (default 8)
AGENTS_RELAY_MAX_JOBS_PER_CHATParallel turns per chat before extra messages queue (default 3, queue cap 20)
AGENTS_RELAY_WAIT_TEXTTelegram placeholder while a turn runs (default One moment …). Status and fallback lines are English
RELAY_HOST / RELAY_PORTBind (default 127.0.0.1:8787; GATEWAY_HOST / GATEWAY_PORT fallbacks)
TELEGRAM_POLL_TIMEOUTLong-poll seconds, clamped 1–50 (default 50)

POST /v1/turn accepts attachments: a list of {"path": "/abs/file", "mime": "image/png"} or {"url": "https://...", "mime": "..."}. A local path must already exist and must resolve inside AGENTS_RELAY_ATTACH_DIR (default: the relay state dir). Paths outside that directory are rejected with HTTP 400. url must be http or https and is downloaded into the relay inbox (20 MB cap). When mime is set, the saved file extension matches it (image/jpeg → .jpg) so the harness can infer the type. Each file is passed to the loop as --attach. Photos and documents from Telegram take the same --attach path. The loop --user for a Telegram turn is the numeric chat id so AGENTS_APPROVAL_CMD can substitute {user}.

approve --user may be a non-numeric turn id (HTTP defaults to anonymous). Then the prompt goes to AGENTS_RELAY_APPROVER, or to the only entry in TELEGRAM_ALLOWED_CHAT_IDS when that list has exactly one chat. Otherwise approve exits 2 and prints {"note":"..."}. A numeric --user is used as given.

approve and serve must share AGENTS_RELAY_STATE on the same host. The poll loop answers callback_query and writes the decision. Only allowlisted user ids can press Approve or Deny. In a private chat that id is the chat id. In a group, list both the group chat id and the approving user id.

HTTP secret headers supported: X-Relay-Secret, Relay-Secret, X-Gateway-Secret, Gateway-Secret.


Constraints

  • Python 3.10+, standard library only.
  • Does not import harness internals. Strictly spawns LOOP_CMD per turn.
  • Klanker / host agents own identity and traces. This process is strictly I/O.

Tests

pytest

or via standard library:

python -m unittest discover -s tests -p "test_*.py"

License

MIT. See LICENSE.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.06 Oct 20260

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
lolaplex/agents-relay

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 23:28 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:eeacc2901c1dfa974556e610bd0ba7ea1c35360f91b858186efd357e1ebb6ccc