Mycroft: Rebuilding Morgan Stanley's AI Tools (And Finding a Hidden Bug)

Rebuilding two of Morgan Stanley's published AI assistant tools from public material alone, Tanmay Kulkarni develops a three-question specification check and uses it to catch a missing write guard in his own repository.

6:18 video5 min readWatch on YouTube

One sentence from a Morgan Stanley press release describes what its AI meeting assistant does: summarize key points, create an email for an advisor to edit and send at their discretion, and save a note into Salesforce. Three verbs in a row, and one of them carries ten extra words attached. That difference is easy to read straight past, and catching it turned into a specification check worth applying to any project built from someone else's design description.

Rebuilding two published tools from public material only

Morgan Stanley built two AI tools for its financial advisors: one that searches the firm's research library, and one that sits in on client meetings and writes them up afterward. The rebuild here uses only what the firm has actually published, since Morgan Stanley reports strong results, 98% of advisor teams adopted the first tool, but does not publish how either tool works internally. That is normal for a bank, but it means every line of the rebuilt code has to trace back to a specific published sentence rather than to any inside knowledge of the real implementation.

A three-question card for catching design collapse

The core method here is a simple three-question check that can run on anything built from somebody else's specification. First, what does the source treat as two different things? Second, are they still two different things in the code? Third, is there a line that fails if someone accidentally makes them one? The whole point is catching one specific failure: two genuinely different ideas in the source material that quietly collapsed into a single idea during implementation.

Finding the real difference in Morgan Stanley's own wording

Applying question one to the press release means looking closely at the verbs. The tool "creates an email for an advisor to edit and send at their discretion." The advisor decides; nothing happens without them. But the tool also "saves a note into Salesforce," with no qualifier attached, nobody to wait for. That note is the only output confirmed finished rather than pending a human decision, and it is bounded to internal filing that no client ever sees. Morgan Stanley states this distinction plainly in its own sentence, right in the open.

Where the first draft got it wrong

Applying question two revealed that the original design did not preserve this distinction. It described both outputs as one thing: a draft waiting on the advisor's decision. That was correct for the email and wrong for the note, since it treated a finished, autonomous action as if it were sitting in a pending state. The mistake was caught on review, checking the design back against the source material, and fixed before anything was finalized. Part of why it nearly slipped through is that the working summary used the word "drafts," while Morgan Stanley's actual word is "creates." Draft sounds unfinished; creates does not. The paraphrase was easier to read correctly than the original source, which is exactly the kind of trap careful rereading does not catch, since rereading is the same instrument pointed at the same sentence by someone who has already decided what it says.

Locking the difference in with a test

Question three produced what became a favorite line in the whole repository: an assertion that the email status is not equal to the Salesforce note status. That line does not check that the email is waiting or that the note is saved; other tests already cover that. It only asserts that those two values can never become the same thing. If someone tidies the file next year and accidentally collapses that distinction, the test suite catches it immediately, rather than relying on a reviewer who might be tired at four in the afternoon.

Turning the same check on his own repository

The second pass ran the identical three questions against a different codebase entirely: the project's own repository. Both pipelines in that repository end the same way, and both are supposed to carry a test that fails if a function with a dangerous name exists, such as send, finalize, submit, or dispatch. The debrief side of the code also checks for a function called write. The assistant side does not. Same guard, two different word lists, and four internal documents described it as a single guard. Running the full word list against all four modules found no matches; nothing is currently broken. But the coverage is narrower than assumed: two of the four modules are guarded, and two happen to be fine only by accident. Add a write function to the debrief side, and a test would fail immediately. Add the identical function to the assistant side, and everything would still pass.

Being honest about what the finding actually proves

By the card's own standard, this counts as a real finding: a difference held up by nothing but memory is worth writing a line of code for before it costs anything. But it is worth being precise that this is an argument about risk rather than a demonstrated failure, since nothing is currently broken and there is no failure to show. The check also has a known limit: it reads the module's own list of guarded names, so it works partly because of how imports happen to be structured in this particular codebase. The full test suite covers two pipelines, twelve modules, and twenty-nine tests, all running on made-up data with nothing of Morgan Stanley's in it, and the write gap on the assistant side is left open on purpose, deliberately unfixed at the time of recording.

Key takeaways

  • A three-question check, what's different in the source, is it still different in the code, and is there a line that fails if it collapses, catches design mismatches from published specifications.
  • Morgan Stanley's own wording distinguishes a human-edited, pending email from an autonomously saved, finished Salesforce note, a distinction the first draft missed.
  • The word "draft" in a working summary was easier to misread than Morgan Stanley's actual word, "creates," showing how paraphrasing can smooth over an important distinction.
  • A not-equal assertion test that only checks two states can never collapse into one is a lightweight, durable way to lock in a design distinction.
  • Running the same three-question check on your own repository found a missing write guard on one module that a matching module already had, despite documentation describing them as identical.
  • A finding with no demonstrated failure is still worth acting on if it depends only on human memory to hold up.

Who this is for

This is for developers and researchers working in the Mycroft Financial AI framework, or anyone rebuilding a system from a public specification who wants a concrete method for catching quietly collapsed distinctions before they become real bugs. It is part of Humanitarians AI Fellows' ongoing work on the Mycroft project.

Chapters

  1. 0:00Rebuilding Morgan Stanley’s research searcher and meeting assistant
  2. 0:40The three-question specification card to prevent design collapse
  3. 1:15Finding the difference: Autonomous Salesforce notes vs. human-edited emails
  4. 2:10The typo in the paraphrase: How "draft" hid a finished action
  5. 2:50Writing the "not equal" assertion test to lock in the difference
  6. 3:40Turning the check on my own repository: Finding the missing write-guard test
  7. 4:30Outro: Why an explicit test is better than relying on human memory
Full transcript(auto-generated, with timestamps)

Rebuilding Morgan Stanley’s research searcher and meeting assistant

[0:00]One sentence from a Morgan Stanley press release. After the meeting, it summarizes key points, creates an email for an advisor to edit and send at their discretion, and saves a note into Salesforce. Three verbs in a row. One of them has 10 extra words attached. That's the whole difference, and I read straight past it. Hi, this is Tanmay Kulkarni, in for Humanitarian's AI. Morgan Stanley built two AI tools for its financial advisors. One searches the firm's research library. The other sits in on client meetings and writes them up. I built a working version of both using only what the firm has published. Along the way, I picked up one check

The three-question specification card to prevent design collapse

[0:40]That's worth more to me than anything else in that repository. I'm going to run it twice, once on Morgan Stanley's material, once on my own code. It finds something both times. Here's the check. Three questions, and you can run them on anything you've built from somebody else's spec. First, what does the source treat as two different things? Second, are they still two different things in the code? Third, is there a line that fails if someone makes them one? It catches one specific thing, two ideas in your source that quietly became one idea in your build. Keep the card in mind. It comes back. Pass one. Morgan Stanley is

Finding the difference: Autonomous Salesforce notes vs. human-edited emails

[1:16]Specific about results. 98% of advisor teams adopted the first tool. What they don't publish is how any of it works. Normal for a bank. It just means every line I wrote had to trace back to a published sentence. Question one. What does the source treat as two different things? Look at the verbs. It creates an email for an advisor to edit and send at their discretion. The advisor decides. Nothing happens without them. And it saves a note into Salesforce. No qualifier. Nobody to wait for. That's the only one of its outputs confirmed finished rather than waiting. The only time either tool writes into the firm's own records without an advisor deciding. And it's bounded. Internal filing. Nothing the client ever sees. And credit where it's due, it's right there in their own sentence in the open. Question two, were they still two different things in my code? Not in my first pass. My original design described both

The typo in the paraphrase: How "draft" hid a finished action

[2:10]Outputs as one thing, a draft waiting on the advisor's decision. Right about the email, wrong about the note. It took a finished action and filed it under waiting for a human. I caught it on review, checking the design back against the source and fixed it before any of it was final. That's the process working, but it's worth being precise about why it so nearly didn't. Morgan Stanley stated that distinction plainly. Three verbs in a row summarizes, creates, saves. Two of them just happen. The middle one carries 10 extra words. The verbs are parallel, so it reads as one list of things the tool does. The asymmetry isn't in the grammar at all. It's a qualifier hanging off the middle

Writing the "not equal" assertion test to lock in the difference

[2:51]Item. And here's the part that should worry you. The summary I first worked from said drafts. Morgan Stanley never says drafts, their word is creates. Draft sounds unfinished, creates does not. So the paraphrase was easier to read correctly than the original. Careful reading is good at finding what you skipped. It's much weaker on what you read and filed in the wrong place because rereading is the same instrument pointed at the same sentence by someone who's already decided what it says. Question three, and this is my favorite line in the repository. It says the email status is not equal to the sales first note status. That's the whole line. Look at what it doesn't do. It doesn't check the email is waiting or that the note is saved, other tests do that. It only asserts those two values can never become the same thing. So if somebody tidies this file next year and

Turning the check on my own repository: Finding the missing write-guard test

[3:40]Collapses them, the suite catches it, not a reviewer who might be tired at 4:00 in the afternoon. The suite, pass one done. Pass two, same three questions. New subject, my own repository. This is the part I didn't plan. Getting ready to make this video, I turned the card on my own code, expecting to walk you through a clean example. Both pipelines end the same way, and both carry a test that fails if a function with a dangerous name exists. Send, finalize, submit dispatch. The debrief side also checks for right. The assistant side doesn't. Same guard, two different word lists, and four of my own documents describe it as one. That's questions one and two answered in about a minute by a card I wrote for something else entirely. Now, let me be careful because this would be easy to oversell. I ran the full word list against all

Outro: Why an explicit test is better than relying on human memory

[4:30]Four modules. No matches, not one. The code is correct today. What's narrower is the coverage. Two of those modules are guarded and two happen to be fine. Add a right function to the debrief side, and a test fails immediately. Add the identical one to the assistant side, and everything passes. So, question three. Is there a line that fails if someone makes them one? On the assistant side, no. And the fix is one word. Add right to that list, and both halves are guarded the same way, which raises a fair question. And I'd rather answer it honestly than tidily. If nothing's broken, is this really a finding? By the card's own standard, yes. A difference held up by nothing but memory is worth a line of code before it costs you anything. But that's an argument about risk. I can't show you a failure because there isn't one. And the check has its own limit. It reads the module's own list of names, so it

Works partly because of how I happen to import things. Airtight is a stronger word than I've earned. So, your turn, same card, your name on it. Question one, what does the source treat as two different things? Open the spec, the docs, the ticket, and write the pairs down. Two states, two outputs, two permission levels. Question two, are they still two different things in the code? Question three, is there a line that fails if someone makes them one? If there isn't, that's the line to write today. Mine took 9 seconds. It's all on disk. Two pipelines, 12 modules, 29 tests. I ran them for this video. All 29 pass. It runs on made-up data. Nothing of Morgan Stanley's in it. And the write gap is still open as I record this on purpose. A check is more convincing when you can watch it catch something nobody tidied away first. This is Tanmay Kulkarni in for Humanitarian's AI. Go run the three questions on your own build.

More from Mycroft Financial AI

Humanitarians AI Lyrical Literacy Project