Skip to content

Submitting a Deal via Slack

Slack is the fastest way to hand Memosa a new deal. You upload your documents into a channel where the bot lives, tell it the deal name, and run a single command to generate the memo. The bot keeps each deal in its own Slack thread, so you can run several deals in parallel without crossing wires.

If you would rather work entirely in the browser, the Canvas web app offers the same intake flow — see Submitting a Deal via Web Chat.

The bot only responds in an explicit allow-list of channels. Every incoming mention and file upload is checked against the channel name before anything else happens; events in any other channel are ignored silently (you will not get a reply, and no work is queued).

EnvironmentBot handleLive channels
Production@memobot#memosa-main, #initiative-memosa
Staging@memosa-staging#memosa-dev

If you mention the bot in a channel it is not configured for, it sends you a private (ephemeral) note listing the channels where it is available, so only you see it and the channel stays quiet.

Drag your deal documents into a channel message, or attach them the usual Slack way. You can upload one file or many at once. The three input types Memosa understands are:

  • PDF — the offering memorandum / deal summary (the sponsor’s narrative).
  • Excel — the underwriting model (.xlsx, .xls, .xlsm).
  • CoStar — CoStar market or comparables exports (these arrive as PDFs and are auto-detected as CoStar even when the filename never says “CoStar”).

A PDF and an Excel model are the two required inputs; CoStar exports are optional extras that sharpen the market analysis. For the full breakdown of what each file type contributes, see What to Upload.

Slack fires a separate upload event for every file, even when you select several and drop them together. To avoid the bot reacting to each one individually (and posting a wall of “got your file” messages), the file handler buffers incoming uploads for a short window and then processes them as one batch.

The debounce window is 3 seconds . Every new file you add inside that window resets the timer, so a quick multi-file drop is always collected into a single batch. Once the window closes with no new files, the bot fetches all the buffered files from Slack in parallel, validates each one, and hands the valid set to the intake pipeline together.

After the batch is processed, the bot replies in the thread with a single message listing every file it accepted, for example:

✅ Received 3 files: OM - 151 Avenue A.pdf, Underwriting Model.xlsx, Sales Comp Report.pdf

Each file is validated on the way in. If a file’s content does not match its extension (a renamed file, a corrupt upload), or if it is empty, an unsupported type, or still mid-classification on Slack’s side, the bot calls it out by name with the reason and the rest of the batch still proceeds. A typical rejection reads:

⚠️ Some uploads were rejected because the file content does not match its extension: • notes.pdf — …

If you have not already named the deal, the bot prompts you for a deal name and any context you want to add. The deal name matters: it is what your namespace and the eventual memo are keyed to, so use the name you want to see on the finished document.

You set the name simply by replying in the thread. An empty or whitespace-only name is refused — a deal must have a real name before generation can run.

Once both required files (PDF + Excel) and a deal name are present, the bot tells you it is ready:

✅ All required documents and information are now present. You can now generate your Memosa memo by saying @memobot generate

Run the command in the thread:

@memobot generate

(On staging, use @memosa-staging generate.) The bot validates readiness one more time, enqueues the analysis job, and the deal moves into processing. From here, watch the thread for progress and the final memo link.

If you run generate before the deal is ready, the bot tells you exactly what is missing — upload the remaining files, set the deal name, or wait for an in-flight run to finish — rather than starting an incomplete memo.

A few details are worth knowing because they explain the bot’s behavior:

  • Each deal is one thread. When you upload a file that is not already part of an active memo thread, the bot maps it to the most recent active thread in the channel, or — as a last resort — opens a fresh thread and tells you to continue there. Keep a deal’s files and your generate command in the same thread.
  • Large files are handled patiently. The bot downloads each file from Slack with progressive timeouts and automatic retries, so a big underwriting workbook that takes a while to transfer will still come through.
  • Duplicate uploads are deduplicated. Re-uploading the same file (same Slack file ID) will not create a second copy; the most recent PDF or Excel replaces the prior one of that type, and duplicate CoStar reports are skipped.
You see / doWhat it means
No reply at all after an uploadYou are in a channel the bot does not watch. Move to a live channel (see the table above).
”I couldn’t find an active memo thread for this upload”The upload could not be tied to a thread. Upload inside an existing memo thread, or mention the bot with your files to start one.
A single file was rejected but others went throughThat file failed validation (wrong content for its extension, empty, or unsupported). Fix and re-upload just that file.
generate says the deal is not readyA required file or the deal name is missing, or a run is already in progress. The error message names the gap.
  • src/slack/handlers/file_handler.py — file_shared event handling, the 3-second debounce buffer (FILE_BATCH_DEBOUNCE_SECS), per-file validation, batch assembly, and thread/auto-thread resolution.
  • src/slack/handlers/base_handler.pyis_channel_allowed() (channel-name allow-list check) and the ephemeral “wrong channel” notice.
  • src/slack/handlers/mention_handler.py — app_mention handling and the allowed-channel guard on mentions.
  • src/slack/handlers/command_handlers.py — the generate command handler and its readiness checks / error codes.
  • src/services/intake_coordinator.py — batch collection, file classification, deal-name setting, readiness gating, and the consolidated “Received N files” / “ready to generate” replies.
  • src/utils/file_classifier.py — classification of uploads into pdf / excel / costar.
  • CLAUDE.md — production vs staging Slack apps and channel isolation (#memosa-main + #initiative-memosa vs #memosa-dev).