Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

feat(chat): inject user CHAT_AGENT.md at every chat entrypoint

merged#2502CedarCopilot

CedarCopilot wants to merge 0 commits into staging from feat/wire-chat-agent-md

Live on prod, no production signal yetTimeline and evidence
  1. Opened
    Aug 15, 2026, 4:57 PM
  2. Merged
    Aug 15, 2026, 6:19 PM
  3. Live on prod
    Aug 15, 2026, 6:19 PM
  4. Observed 3 days
    Aug 15, 2026, 6:19 PM
  5. Pipelines steady after this deploy
    Aug 15, 2026, 6:19 PM
  6. Unobserved

    Live on prod, no production signal yet

    Aug 18, 2026, 6:11 PM

Behaviors Libra is checking

Every chat entrypoint, including in-app chat, headless Slack/iMessage/SMS chats, and Slack approval acceptance, applies the user’s `CHAT_AGENT.md` instructions to the agent prompt.Degradedlow confidence

Strict CloudWatch fallback found 1 prod failure log lines for [run-chat-agent-sdk] query() failed (Claude Code process aborted by user) in the last 24h while checking /routes, /playbooks/chat_agent.md, /imessage/sms, executionprompt, buildchatorgrulecontext.

prod, checked Aug 18, 2026, 6:11 PM
Chat remains available when no organization or `CHAT_AGENT.md` exists, the document is blank, or reading it fails; document-read failures are logged without blocking the turn.Degradedlow confidence

Strict CloudWatch fallback found 2 prod failure log lines for [UpdateExternalCrmWorkflow] Driver update failed (User is not connected to HubSpot) in the last 24h while checking builduserchatinstructionsblock, chat_agent, [chat-org-rules] failed to load chat_agent.md.

prod, checked Aug 18, 2026, 6:11 PM
User `CHAT_AGENT.md` content is wrapped as `<user_chat_instructions>` and placed before skills, connection rules, organization rules, and approval prompts so it has highest dynamic-context priority.Degradedlow confidence

Strict CloudWatch fallback found 1 prod failure log lines for [run-chat-agent-sdk] query() failed (Claude Code process aborted by user) in the last 24h while checking dynamiccontext, buildchatorgrulecontext, fullprompt, chat_agent, <user_chat_instructions>.

prod, checked Aug 18, 2026, 5:45 PM

Libra has verdicts on 0 of 3 tracked behaviors on prod; 3 are still being checked. Libra has 3 low-confidence degraded verdicts it is still confirming. Libra checks hourly for 3 days after each deploy.

What

The per-user user/playbooks/CHAT_AGENT.md doc (seeded by seedPlaybookFiles) had no consumers , nothing read it into any chat agent, so user-authored chat instructions were silently dormant.

Adds a single shared helper and ingests it at every chat entrypoint.

The helper

buildUserChatInstructionsBlock(orgId, userId) in chat-org-rules.ts (the module already shared by every chat surface). Reads CHAT_AGENT.md via the existing readDocument service and returns a <user_chat_instructions> block, or '' when the doc is missing/empty/whitespace (or orgId is null). Non-fatal (try/catch, log-and-continue) , a chat turn is never blocked. Single source of truth; no duplicated read logic.

Coverage (every chat entrypoint)

EntrypointIngested via
In-app chat , Agent-SDK harness (direct-Anthropic query())chat-workflow.ts (top of dynamicContextexecutionPrompt)
In-app chat , Mastra chatAgent.stream() fallbacksame executionPrompt (shared assembly)
Slack botshared buildChatOrgRuleContext (first section)
iMessage botshared buildChatOrgRuleContext
SMS botshared buildChatOrgRuleContext
Understudy-gateway variants of the abovesame executionPrompt , covered transitively

Placed first in each surface's dynamic context so it's the top of what the model reads.

Out of scope (verified): WhatsApp is notify-only (no chat-agent handler); roadmap chat runs a distinct roadmapAgent; the event-execution agent already reads playbooks separately.

Why now

Enables per-user chat customization generally, and specifically makes an engagement wiki-review flow (authored into a user's CHAT_AGENT.md) reachable from in-app chat and the headless surfaces.

Verification

pnpm --filter @zero/server run types → 0 errors in the two touched files (chat-org-rules.ts, chat-workflow.ts); the 9 build errors are pre-existing and unrelated.

🤖 Generated with Claude Code

Greptile Summary

The PR adds a shared reader for each user's CHAT_AGENT.md and prepends its contents to in-app and standard Slack, SMS, and iMessage chat prompts.

  • Adds best-effort, user-and-org-scoped document loading with structured error logging.
  • Reuses the resulting instruction block across both in-app agent paths and the shared headless bot context.
  • Leaves the separate Slack approval agent invocation outside the new instruction-loading path.

Confidence Score: 4/5

The Slack approval continuation should ingest CHAT_AGENT.md before merging so accepted actions do not bypass the user's configured chat behavior.

Standard in-app and bot prompts receive the new block, but the independent Slack agent_prompt operation still invokes the chat agent using only its preamble and approval text.

Files Needing Attention: apps/server/src/mastra/workflows/chat/chat-org-rules.ts and apps/server/src/mastra/operations/operation-registry.ts

Important Files Changed

FilenameOverview
apps/server/src/mastra/workflows/chat/chat-org-rules.tsAdds the scoped CHAT_AGENT.md reader and standard headless injection, but this shared composition is not used by the Slack approval agent invocation.
apps/server/src/mastra/workflows/chat/chat-workflow.tsPrepends the instruction block to the executionPrompt shared by the in-app Agent SDK and Mastra paths.

Flowchart

rendering diagram…
Show production surfaces and changed-file mapping

Production surfaces

Libra has not measured any production surfaces for this change yet.

Changed files → surfaces

  • apps/server/src/mastra/operations/operation-registry.tsno production surface mapped
  • apps/server/src/mastra/workflows/chat/chat-org-rules.tsno production surface mapped
  • apps/server/src/mastra/workflows/chat/chat-workflow.tsno production surface mapped