Event Service¶
The event service is an asyncio-based pub/sub runtime for agent workflows.
What It Does¶
- Listens to Telegram bot updates (long polling)
- Emits cron-style interval and calendar-based schedule events
- Projects source-specific events into normalized
workflow.requestevents - Writes events to stdout and/or JSONL for traceability
- Optionally spawns headless Claude Code sessions for autonomous review
Event Flow¶
- Source emits event (
telegram.message,cron.tick) - Event bus routes by wildcard patterns
- Projectors transform source events into
workflow.request - Sinks write events to stdout and/or JSONL
Running¶
Default (Telegram + built-in daily/weekly schedules):
openfin tools service
Custom schedule:
openfin tools service --schedule weekly_review=mon@06:00/America/Chicago
With audit log:
openfin tools service --event-log logs/events.jsonl
Autonomous Review Mode¶
When --ai is enabled, the service spawns a headless Claude Code session to execute the full weekly review workflow (Phases 2-5) without human intervention. The agent scores rubrics, records evidence, writes annotations, and finalizes the report, then sends results via Telegram.
How It Works¶
- A
workflow.requestevent fires (from cron schedule or Telegram/reviewcommand) WeeklyReviewOrchestratorruns Phase 1: gathers portfolio, market, macro, news, and search data (or returns a cached report if one exists for today and is less than 60 minutes old)- The orchestrator persists:
{DATE}.json— full structured report{DATE}.md— compact overview (~80 lines){DATE}_symbols/{SYMBOL}.md— data-only scoring packet per symbol (thesis, news, search, market, position)- A headless Claude Code session is spawned with:
- System prompt (via
--append-system-prompt): role identity + SOP instructions + rubric scoring instructions (docs/agent/weekly-review-scoring-prompt.md) - User prompt: run ID, compact overview data, and a step-by-step checklist
- Tool restriction (
--allowedTools Bash,Read): agent can only runopenfincommands and read files - Permission bypass (
--permission-mode bypassPermissions): no interactive prompts - The agent reads each
{SYMBOL}.mdscoring packet on demand, scores rubrics, records evidence, annotates the executive summary, and finalizes - Agent output is formatted and sent to the configured Telegram chat
Prompt Architecture¶
The autonomous prompt is split into two layers to minimize context usage:
| Layer | Content | Size |
|---|---|---|
| System prompt | Agent role, behavioral constraints, full SOP, rubric scoring instructions | ~250 lines (stable across runs) |
| User prompt | Run ID, overview markdown, step checklist | ~100 lines (run-specific) |
Scoring rubric definitions (anchors, weights, considerations) are in the system prompt rather than in per-symbol data files. This prevents rubric instructions from leaking into agent output that gets forwarded to Telegram. Per-symbol data packets (~30-50 lines each) are read on demand from disk.
The Telegram /ask command uses a separate tracked system prompt in agent/telegram-ask-prompt.md.
Running Autonomous Mode¶
openfin tools service --ai --event-log logs/events.jsonl
On-demand via Telegram: send /review to the bot.
Requirements¶
TELEGRAM_BOT_TOKENandTELEGRAM_CHAT_IDmust be set (env var or~/.openfin/credentials.toml)--airequires theclaudeCLI binary on PATH (install vianpm install -g @anthropic-ai/claude-code)
Options¶
| Flag | Description |
|---|---|
--telegram-token |
Bot token (falls back to TELEGRAM_BOT_TOKEN) |
--telegram-poll-timeout |
Poll timeout in seconds |
--chat-id |
Telegram chat ID for sending messages |
--allowed-users |
Comma-separated Telegram user IDs allowed to send commands |
--cron NAME=INTERVAL |
Repeatable interval trigger (e.g. brief=30m) |
--schedule NAME=DAY@HH:MM[/TZ] |
Repeatable calendar trigger (e.g. weekly_review=mon@06:00/America/Chicago) |
--event-log <path> |
JSONL trace output path |
--quiet |
Disable stdout event stream |
--ai / --no-ai |
Enable AI review mode |
--claude-path |
Path to Claude Code binary (default: claude) |
Full help:
openfin tools service --help