CopilotKit / CopilotKit/outpost
Orphaned-reply handling is Teams-only
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7
- Forks
- 3
- Avg merge
- 7d 16h
- Merged PRs (30d)
- 15
Description
InboundHandler.handleReply has a fallback: when a reply arrives and no ticket matches its thread, it creates a ticket and persists the message — but never answers it. The reasoning is that dropping a customer's words is worse than filing an oddly-titled ticket a human can pick up.
That reasoning is written as a general principle. In practice only one platform reaches it.
| Platform | Behaviour on an untracked reply |
|---|---|
| Teams | reaches the fallback — ticket filed, no AI answer |
| Discord | events/message-create.ts returns early when no ticket matches — message dropped |
| Slack | events/message.ts pre-filters untracked replies — message dropped |
| GitHub | webhooks/issue-comment.ts returns when no ticket matches — comment dropped. Never uses InboundHandler at all |
honours the principle, but implements it locally in postmark/route.ts rather than through the shared handler |
So a customer message that arrives without a matching ticket is preserved on Teams and email, and silently discarded on Discord, Slack and GitHub.
Why it matters
The discard cases are not hypothetical. Any thread that predates Outpost's deployment in a channel has no ticket, so every reply in it is dropped. Same for a thread whose ticket was deleted, and for a reply that arrives before its own thread-create event.
Nobody notices, because dropping is silent by construction — there is no error, no ticket, and no log the team watches.
The decision
Three defensible answers, and it is a product call:
- Unify on preserve. Remove the pre-filters so every platform files the ticket. Costs: some noise from threads Outpost was never meant to see, and each ticket is titled with a mid-conversation fragment.
- Unify on drop. Remove the fallback and accept that an untracked reply is not ours. Simpler, and arguably correct if channels are deliberately scoped — but it loses real customer messages.
- Keep the split deliberately, on the grounds that Teams and email are lower-volume and higher-value than a public Discord. That is a legitimate position; it just needs to be stated rather than inherited from whoever wrote each pre-filter first.
The current comment in platforms/inbound.ts documents which platforms reach the branch, so the code is at least honest. This issue is about picking one.
Related: #174 (human-presence gate) touches the same code path and may change what "should we answer this" means.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with platforms/inbound.ts and trace InboundHandler.handleReply alongside events/message-create.ts, events/message.ts, webhooks/issue-comment.ts, and postmark/route.ts. First resolve which untracked-reply behavior is intended, considering related issue #174; done means the chosen policy is implemented consistently and covered for each listed platform.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100