Integration

Cleaning Up Multi-Agent Output for Telegram

February 5, 2026

The multi-agent pipeline was built for the web UI first. Telegram was an afterthought, and it showed.

When a specialist finished its work and the parent relayed the response, the Telegram message included raw system markers, delegation syntax, and formatting artefacts that made sense in a structured web renderer but looked like garbage in a plain text chat. You'd see things like [SUBAGENT:start|3|Researcher] and internal status lines mixed in with the actual answer. It was like reading someone's work notes instead of their final report.

Leaky plumbing

Engineers have a term for this: a leaky abstraction. The orchestration layer's internal protocol was bleeding through to the user-facing output because nothing was cleaning it up on the way out. The web UI handled these markers fine - it parsed them into interactive components like sub-conversation panels and agent labels. But Telegram doesn't have a parser. It just shows text. And text full of system markers is useless to a human.

The fix: one output, multiple formats

The solution follows what's called the adapter pattern. Think of it like a power plug adapter: the orchestration layer produces one standard output format (the universal plug), and each delivery channel has its own adapter that converts it to what that channel understands.

The web UI is a rich client - it takes the structured markers and turns them into clickable panels, agent badges, and timing displays. Telegram is a thin client - its adapter strips all orchestration markers and delivers clean prose only. A future API channel might return raw structured data. Each adapter handles its own transformation, and the orchestration layer doesn't need to know or care about any of them. This keeps things cleanly separated - the part that runs agents doesn't need to think about how the output gets displayed.

Typing indicators as a heartbeat

The other change: the Telegram bot now sends periodic typing indicators during delegation. When the parent hands off work to a specialist and waits for the response, Telegram shows "typing..." every few seconds.

Previously there was no feedback during delegation. You'd send a message, wait 10-15 seconds in silence, and then get a response. From the user's perspective, it looked exactly the same as the bot crashing.

This is an application of what's called the heartbeat pattern - a regular signal that doesn't carry any data but tells the other side "I'm still alive and working." Same idea as a progress spinner in a web app, or a keep-alive ping on a WebSocket connection. It doesn't speed anything up, but the psychological difference is huge. The user knows work is happening instead of wondering if their message disappeared into the void.

The principle

Different delivery channels need different output treatments for the same underlying data. The orchestration layer produces one canonical form (structured text with embedded markers). Each delivery channel transforms that into what makes sense for its context. The web UI enriches it. Telegram simplifies it. Neither changes how the orchestration works. This is the same separation between "what the system does" and "how it presents itself" that every well-structured application should have.