teleo-codex/ops/pipeline-v2/telegram/agent_runner.py
m3taversal 7bfce6b706 commit telegram bot module from VPS — 20 files never previously in repo
Pulled from /opt/teleo-eval/telegram/ on VPS. Includes:
- bot.py (92K), kb_retrieval.py, kb_tools.py (agentic retrieval)
- retrieval.py (RRF merge, query decomposition, entity traversal)
- response.py (system prompt builder, response parser)
- agent_config.py, agent_runner.py (multi-agent template unit support)
- approval_stages.py, approvals.py, digest.py (approval workflow)
- eval_checks.py, eval.py (response quality checks)
- output_gate.py, x_publisher.py, x_client.py, x_search.py (X pipeline)
- market_data.py, worktree_lock.py (utilities)
- rio.yaml, theseus.yaml (agent configs)

These files were deployed to VPS but never committed to the repo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:02:32 +02:00

118 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""Agent runner — entry point for running a Teleo Telegram agent.
Usage:
python3 agent_runner.py --agent rio
python3 agent_runner.py --agent theseus
python3 agent_runner.py --agent rio --validate
Systemd template unit: teleo-agent@.service
ExecStart=/usr/bin/python3 /opt/teleo-eval/telegram/agent_runner.py --agent %i
Each agent runs as a separate process for fault isolation.
Template unit means `systemctl start teleo-agent@rio` and
`systemctl start teleo-agent@theseus` are independent services
with separate log streams (journalctl -u teleo-agent@rio).
Epimetheus owns this module.
"""
import argparse
import sys
import os
from pathlib import Path
AGENTS_DIR = Path(__file__).parent / "agents"
def find_config(agent_name: str) -> Path:
"""Resolve agent name to config file path."""
config_path = AGENTS_DIR / f"{agent_name}.yaml"
if not config_path.exists():
print(f"ERROR: Config not found: {config_path}", file=sys.stderr)
print(f"Available agents: {', '.join(p.stem for p in AGENTS_DIR.glob('*.yaml'))}", file=sys.stderr)
sys.exit(1)
return config_path
def validate(agent_name: str) -> bool:
"""Validate agent config and runtime dependencies. Returns True if valid."""
config_path = find_config(agent_name)
# Add telegram dir to path for agent_config import
sys.path.insert(0, str(Path(__file__).parent))
from agent_config import validate_agent_config
try:
warnings = validate_agent_config(str(config_path))
if warnings:
for w in warnings:
print(f" WARNING: {w}", file=sys.stderr)
print(f" Config OK: {agent_name} ({config_path})")
return True
except ValueError as e:
print(f" FAILED: {e}", file=sys.stderr)
return False
def run(agent_name: str):
"""Run the agent bot process."""
config_path = find_config(agent_name)
# Validate before running (fail fast)
if not validate(agent_name):
sys.exit(1)
# Set sys.argv so bot.py's main() picks up the config
sys.argv = ["bot.py", "--config", str(config_path)]
# Import and run bot — this blocks until the bot exits
sys.path.insert(0, str(Path(__file__).parent))
import bot
bot.main()
def list_agents():
"""List available agent configs."""
configs = sorted(AGENTS_DIR.glob("*.yaml"))
if not configs:
print("No agent configs found in", AGENTS_DIR)
return
print("Available agents:")
for p in configs:
# Quick parse to get agent name from YAML
name = p.stem
try:
import yaml
with open(p) as f:
data = yaml.safe_load(f)
domain = data.get("domain", "unknown")
print(f" {name:12s} domain={domain}")
except Exception:
print(f" {name:12s} (config parse error)")
def main():
parser = argparse.ArgumentParser(
description="Run a Teleo Telegram agent",
epilog="Systemd: teleo-agent@.service uses --agent %%i"
)
parser.add_argument("--agent", help="Agent name (e.g., rio, theseus)")
parser.add_argument("--validate", action="store_true", help="Validate config and exit")
parser.add_argument("--list", action="store_true", help="List available agents")
args = parser.parse_args()
if args.list:
list_agents()
return
if not args.agent:
parser.error("--agent is required (or use --list)")
if args.validate:
ok = validate(args.agent)
sys.exit(0 if ok else 1)
run(args.agent)
if __name__ == "__main__":
main()