Repository navigation
feat(zendesk): draft the known answers before the digest posts - #80
Merged
Merged
Conversation
…he ticket Zendesk writes a messaging chat into the ticket only when the chat ends, and a chat that starts while the ticket has an assignee is never ended. Until then the customer's newest message is readable by the assignee alone. The digest now sweeps unsolved Twitter DM tickets for an open chat, lists them on their own line, and leaves them unrecorded so they are reported again once the message lands. note_reply refuses draft, reply and english on such a ticket rather than act on a conversation missing its newest message.
The digest now writes a private draft note on each ticket it reports that nobody has answered yet, when support already knows the answer: - a police or legal data request gets the standard reply, word for word - an abuse report is composed from a standing brief, in the reporter's language: we can block the ID from Session-operated communities, no more - anything else reuses a `claude: draft` brief that went out unamended as a first reply on the same house-answer group, when Claude judges it fully answers the ticket and holds no expired or ticket-specific fact Those briefs are cached beside the dedup state and topped up from `tags:claude-sent` each run. A draft is only ever sent by a human's `claude: reply N`; a `claude: draft` after it starts over instead of amending wording nobody approved. The digest lists the drafted tickets.
- Only tickets placed in DRAFT_GROUPS get an unprompted draft. - Placement runs before the abuse standing brief, so a police request classified as an abuse report still gets the fixed legal text. - Any error while drafting is reported per ticket and survived, so the digest always posts. - The brief backfill reads the 180-day window past the 1000-result cap, and the scan only moves on when every search page and comment read succeeded. - A ticket with a private note from a person is left alone.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Before posting, the weekday digest writes a private draft note on each reported ticket that nobody has answered or picked up yet, when support already knows the answer. The note is the one
claude: draftwrites, so a human checks it and sends it withclaude: reply N, or writesclaude: draft <brief>, which starts over rather than amending the unreviewed draft. Nothing is sent to a customer without a human.Three sources, in order:
law-enforcement-requests): the standard reply inSTANDARD_REPLIES, word for word, untranslated.abuse_reportcategory): composed from the standing brief inSTANDING_BRIEFS, in the reporter's language. We can block the reported ID from Session-operated communities, and that is all. No placement call needed.claude: draftbrief that went out unamended as a ticket's first reply, on the same house-answer group. Claude picks the one that fully answers the ticket, or none, and rejects briefs that name another ticket, promise an action, or carry a fact that may have expired (a pending release, an ETA).Why past briefs: over September and October the note flow sent 504 replies,
reply 1467 times, and 262 tickets went straightdraft > reply. Briefs within a group repeat nearly word for word. The house answers stay a shape-only precedent, as before: they are not a fact source.The briefs are cached in
known_briefs.jsonbeside the dedup state, topped up fromtags:claude-senteach run and dropped after 180 days. The first run backfills about 450 tickets. Drafting is bounded to 20 minutes, highest priority first, stops after three failures and never fails the digest. A 📝 line in the digest lists the drafted tickets.Also carries e7b0665 (live chats that keep a customer's message off the ticket), which this builds on and which was not pushed on its own.
Deploy
Needs
ZENDESK_HOUSE_ANSWERSin/etc/session-ops/zendesk.env; without it the digest logs that drafting was skipped and posts as before.Tested
uv run python -m unittest discover -s tests/zendesk -t .: 502 passzendesk-triage --window-hours 120 --dry-run --known-briefs <tmp>against the live account: 343 briefs cached from 443 sent tickets, 3 of 10 tickets drafted, nothing written