diff --git a/agent-office/app/agents/stock.py b/agent-office/app/agents/stock.py
index d6de585..c59bd4a 100644
--- a/agent-office/app/agents/stock.py
+++ b/agent-office/app/agents/stock.py
@@ -48,7 +48,9 @@ class StockAgent(BaseAgent):
})
if not tg_result.get("ok"):
- add_log(self.agent_id, "Telegram send failed", "warning", task_id)
+ desc = tg_result.get("description") or "unknown"
+ code = tg_result.get("error_code")
+ add_log(self.agent_id, f"Telegram send failed: [{code}] {desc}", "warning", task_id)
if self._ws_manager:
await self._ws_manager.send_notification(
self.agent_id, "telegram_failed", task_id, "텔레그램 전송 실패"
diff --git a/agent-office/app/telegram/formatter.py b/agent-office/app/telegram/formatter.py
index 0fc9b4e..4345a24 100644
--- a/agent-office/app/telegram/formatter.py
+++ b/agent-office/app/telegram/formatter.py
@@ -1,4 +1,5 @@
"""에이전트 메시지 포맷팅."""
+from html import escape as _h
from typing import Literal, Optional
from .agent_registry import get_agent_meta
@@ -23,9 +24,14 @@ def format_agent_message(
) -> str:
meta = get_agent_meta(agent_id)
icon = KIND_ICONS.get(kind, "")
- header = f"{icon} [{meta['emoji']} {meta['display_name']}] {title}"
+ header = f"{icon} [{_h(meta['emoji'])} {_h(meta['display_name'])}] {_h(title)}"
- lines = [header, "━" * 20, body]
+ # Telegram 단일 메시지 4096자 제한 대응 (헤더/푸터 여유 512자 확보)
+ safe_body = _h(body)
+ if len(safe_body) > 3500:
+ safe_body = safe_body[:3500] + "\n…(생략)"
+
+ lines = [header, "━" * 20, safe_body]
if metadata:
footer_parts = []
@@ -38,6 +44,6 @@ def format_agent_message(
footer_parts.append(f"🤖 {metadata['model']}")
if footer_parts:
lines.append("")
- lines.append(f"{' · '.join(footer_parts)}")
+ lines.append(f"{_h(' · '.join(footer_parts))}")
return "\n".join(lines)
diff --git a/agent-office/app/telegram/messaging.py b/agent-office/app/telegram/messaging.py
index 7d13636..75dfb4d 100644
--- a/agent-office/app/telegram/messaging.py
+++ b/agent-office/app/telegram/messaging.py
@@ -20,9 +20,12 @@ async def send_raw(text: str, reply_markup: Optional[dict] = None) -> dict:
if reply_markup:
payload["reply_markup"] = reply_markup
result = await api_call("sendMessage", payload)
+ ok = result.get("ok", False)
return {
- "ok": result.get("ok", False),
- "message_id": result.get("result", {}).get("message_id") if result.get("ok") else None,
+ "ok": ok,
+ "message_id": result.get("result", {}).get("message_id") if ok else None,
+ "description": result.get("description") if not ok else None,
+ "error_code": result.get("error_code") if not ok else None,
}