improve(email): extract body preview func and remove thread_id from dispatcher prompt

linuztx committed Mar 15, 2026 at 22:22 UTC 1aa1190de12e0fb863669661b72da7ced047a2d2
3 files changed +16 -8
plugins/_email_integration/helpers/dispatcher.py
+10 -2
@@ -22,6 +22,8 @@ CTX_EMAIL_REFERENCES = "email_references"
22 # Transient — consumed per-reply, not persisted
23 CTX_EMAIL_ATTACHMENTS = "_email_response_attachments"
24
25 +BODY_PREVIEW_MAX_CHARS: int = 2000
26 +
27 DispatchAction = Literal["new_chat", "continue_chat", "intervene_soft", "intervene_hard"]
28
29
@@ -58,14 +60,20 @@ def build_chat_summary(context_id: str, data: dict) -> dict:
60 # Dispatcher prompt builders
61 # ------------------------------------------------------------------
62
63 +def truncate_body(body: str) -> str:
64 + if len(body) <= BODY_PREVIEW_MAX_CHARS:
65 + return body
66 + return body[:BODY_PREVIEW_MAX_CHARS] + "... (truncated)"
67 +
68 +
69 def format_chats_list(existing_chats: list[dict]) -> str:
70 if not existing_chats:
71 return "No existing chats for this handler."
72 sections = []
73 for c in existing_chats[:20]:
74 header = (
67 - f"- context_id={c['context_id']} thread_id={c.get('thread_id', '')} "
68 - f"sender={c.get('sender', '')} subject={c.get('subject', '')}"
75 + f"- context_id={c['context_id']}"
76 + f" sender={c.get('sender', '')} subject={c.get('subject', '')}"
77 )
78 preview = c.get("history_preview", "")
79 if preview:
plugins/_email_integration/helpers/handler.py
+1 -1
@@ -182,7 +182,7 @@ async def _call_dispatcher(
182 msg: InboundMessage,
183 existing_chats: list[dict],
184 ) -> disp.DispatchDecision:
185 - body_preview = msg.body[:2000] if len(msg.body) > 2000 else msg.body
185 + body_preview = disp.truncate_body(msg.body)
186 chats_text = disp.format_chats_list(existing_chats)
187
188 prompt = agent.read_prompt(
plugins/_email_integration/prompts/fw.email.dispatcher_system.md
+5 -5
@@ -1,19 +1,19 @@
1 You route inbound emails to agent chats.
2 -You receive: the new email (sender, subject, body) and a list of existing chats for this email handler.
2 +You receive: the new email (sender, subject, body) and a list of existing chats with conversation history.
3
4 Rules:
5 -- If the email subject contains a thread ID marker [a0-XXXX] AND a matching chat exists, reply with CONTINUE and that chat's context_id
6 -- If no thread ID but the email content clearly relates to an existing chat (same topic, same sender), reply with CONTINUE and the best matching context_id
5 +- If the email content clearly relates to an existing chat (same topic, same sender), reply with CONTINUE and that chat's context_id
6 - If the email is a status question or low-priority follow-up on a running chat, reply with INTERVENE_SOFT and the context_id — the agent will receive it after current step
7 - If the email is urgent and requires immediate attention on a running chat, reply with INTERVENE_HARD and the context_id
8 - Otherwise reply with NEW_CHAT
9
10 +Use conversation history to determine topic relevance when matching emails to chats.
11 +
12 Respond with EXACTLY one line in this format:
13 ACTION context_id reason
14
15 Examples:
16 NEW_CHAT _ new request from user
16 -CONTINUE ctx_abc123 thread ID matches
17 -CONTINUE ctx_def456 same sender discussing AWS deployment
17 +CONTINUE ctx_abc123 same sender discussing AWS deployment
18 INTERVENE_SOFT ctx_abc123 user asking for status update
19 INTERVENE_HARD ctx_abc123 urgent correction needed