CedarCopilot wants to merge 0 commits into staging from fix/orchestrator-no-draft-on-internal-events
Live on prod, no production signal yet
Libra has verdicts on 0 of 2 tracked behaviors on prod; 2 are still being checked. Libra checks hourly for 3 days after each deploy.
Two related regressions in the on-event orchestrator's drafting decision, both traced with production data.
1. External CRM sync events draft anyway. handleExecuteExternalCrm.ts builds a task prompt that ends with an explicit "Do NOT draft emails... this is an internal data sync only" instruction, but the orchestrator's own system prompt (on-event-orchestrator-agent.ts) has zero awareness of this case , its general drafting instructions ("call run-subagent with @subagents/drafter... when a DRAFT NOW rule applies") compete against, and win over, a single trailing sentence in a large CRM-activity data dump.
Weekly data across 3 Pirros accounts (external_crm-sourced runs that produced a successful draft):
| Week | Total ext_crm runs | Spawned a draft |
|---|---|---|
| 08-03 | 1,088 | 0 |
| 08-10 | 431 | 0 |
| 08-17 | 1,455 | 0 |
| 08-24 | 840 | 0 |
| 08-31 | 766 | 14 |
| 09-07 | 1,041 | 27 |
| 09-14 (partial) | 621 | 8 |
Zero for four straight weeks, then a clean start the week of Aug 31 , lining up with the feat/drafter-system-agent migration (PR #2624, merged 2026-08-31), which moved drafting from inline logic into a decoupled orchestrator + dispatched-subagent design.
2. Automated/calendar-notification events used as a pretext to draft something else. A Google Calendar RSVP notification (<email>, crm_events.is_significant = false) triggered the orchestrator, which correctly identified the sender two tool calls earlier, then dispatched the drafter anyway to write an unrelated, already-drafted meeting recap.
Both incidents produced the identical reasoning string in agent_tool_calls: "A recap email is needed... per the post-meeting email resource" , reasoning from the broader conversation history (a meeting happened recently) rather than the event that actually triggered the run.
apps/server/src/mastra/agents/on-event-orchestrator-agent.ts , prompt-only change (no tool-access changes, per explicit request):
[⚙ NOT SIGNIFICANT] rule: even when the playbook has explicit instructions for the event type, a not-significant/automated event must never be the reason to draft anything , not a reply to it, and not something else that looks overdue.<no_marketing_draft_rule> to explicitly forbid using an automated/marketing event as a pretext to draft something unrelated that "looks overdue."<internal_sync_no_draft_rule> section that names the exact failure mode observed in production (the "recap... per the post-meeting email resource" rationalization) and states directly: if the task says internal-sync-only, never call run-subagent(@subagents/drafter), for any reason.This is the shared orchestrator system prompt , it applies to every account's event-triggered runs, not just Pirros. It only adds constraints (narrows when drafting happens); it does not change any tool wiring or access.
Watch agent_tool_calls for external_crm-sourced runs and [⚙ NOT SIGNIFICANT]-flagged events going forward , run-subagent/run-post-event-executor should no longer appear as a child of either, across all accounts, not just Pirros.
🤖 Generated with Claude Code
https://claude.ai/code/session_01PuWr5XobqBY5mbUvSZjwxy
This prompt-only change strengthens the orchestrator’s drafting restrictions for automated, not-significant, and internal CRM-sync events.
The PR is not yet safe to merge because internal CRM-sync executions retain a reachable draft-capable notifier path.
The new internal-sync rule blocks the dedicated drafter but does not
Libra has not measured any production surfaces for this change yet.