← Back to Blog
Building in Public

Three Integrations Walk Into a Bar

christian crumlish•
A robot building a cathedral, suggesting large-scale integration work assembled stone by stone.
“What’ll it be?”

Three Integrations Walk Into a Bar

September 28

Sunday afternoon at 4:14 PM, I opened my laptop expecting a straightforward router completion task. The gameplan looked clean: finish three integration routers (Slack, Notion, Calendar), apply the patterns we’d proven with GitHub on Saturday, maybe six hours of systematic work.

By midnight, we’d completed all three routers. But the path there involved discovering that every single assumption in the gameplan was wrong, that each integration existed in a completely different state, and that “reality check before assumptions” isn’t just methodology theater — it’s how you avoid building the wrong thing efficiently.

This is the story of what happens when you actually look before you leap, even when you think you already know what you’ll find.

The gameplan that wasn’t

The Chief Architect’s initial gameplan made perfect sense based on GitHub issue #199’s description: “Integration routers 14–20% complete.” We’d just finished the GitHub router Saturday night — 121% complete with systematic verification. Apply the same pattern to three more routers. Simple multiplication.

The gameplan laid out five parts:

  • Phase −1: Infrastructure reality check
  • Phase 0: Comprehensive router audit
  • Phases 1–3: Router completion for Slack, Notion, Calendar
  • Phases 4–5: Service migration and testing
  • Phase 6: Documentation and locking

But then I asked six questions that changed everything:

  1. Did I review the gameplan template first? No.
  2. Do we need Phase −1? Perhaps.
  3. Did I review the issue description? No.
  4. Are those bash examples verified or guesses? Guesses.
  5. Am I conveying necessary context? Incomplete.
  6. Are my assumptions grounded in reality? Partial.

“We need to be more rigorous,” I told the Lead Developer. “Not wing it.”

Phase −1 exists for exactly this reason: to verify infrastructure matches your assumptions before you build on top of them. (Also, so I stop and actually read the plan instead of passing it along passively and then griping about wrong assumptions.)

We added it to the gameplan and deployed the Code agent to investigate.

What came back was nothing like what we expected.

Integration #1: The one that was ready

Slack looked straightforward at first. The Code agent found:

  • Complete directory at services/integrations/slack/
  • Sophisticated spatial intelligence system (6 files, 20+ components)
  • SlackClient with core methods
  • Pattern matching GitHub’s successful implementation

Status: GREEN — Ready for router work.

This was exactly what we expected. One down, two to go.

Integration #2: The mysterious adapter

Notion was different. The Code agent found:

  • MCP adapter at services/integrations/mcp/notion_adapter.py
  • 637 lines of implementation
  • But… wait, MCP pattern? That’s not what the gameplan assumed

The original scope expected traditional client/agent patterns like GitHub and Slack. But Notion used Model Context Protocol adapters — a different architectural approach entirely. Not incomplete. Just different.

I knew we had started layering inMCP support before we started adding spatial intelligence, so it looked like different integrations had each inherited one of these partial solutions.

The question became: should we wrap the MCP adapter with a router, or acknowledge it as a different pattern? The architecture was sound, just unexpected.

Status: YELLOW — Architecture decision needed.

Integration #3: The one that didn’t exist

Calendar revealed the real problem. The Code agent searched everywhere:

  • No services/integrations/calendar/ directory
  • No calendar client or agent
  • No spatial calendar files
  • Nothing matching the expected pattern

Status: RED — Integration appears completely missing.

The scope estimate jumped immediately. If we had to build an entire Calendar integration from scratch, we weren’t looking at 16 hours of router work. We were looking at potentially 40+ hours including OAuth implementation, API integration, spatial adapter creation, and everything else.

Note: I happened to know we had successfully integrated Google Calendar a while back, but clearly we had done it outside of the expected channels, to the extent that my agent was reporting not being able to find it.

At 6:43 PM, I reported back to the Chief Architect: our three “similar routers” were actually three completely different architectural challenges. The gameplan assumptions had collided with reality.

The discovery that changed everything

So I disputed the claim about the Calendar integration being missing entirely, reminding the team:

“We have OAuth working (somewhere). I personally verified the Calendar connection works. The integration was built September 19–22.”

So… if the Calendar integration existed and worked, where was it?

Phase −1B launched: find the Calendar integration that OAuth proved must exist somewhere. The Code agent searched git history for those dates, checked every possible location, looked for any OAuth-related code.

At 8:35 PM, the discovery came through:

Complete Google Calendar integration found at services/mcp/consumer/google_calendar_adapter.py

Not missing. Not incomplete. Actually 85% complete with:

  • OAuth 2.0 working since September 6
  • Full feature set (events, meetings, free time)
  • Spatial intelligence via BaseSpatialAdapter
  • Circuit breaker resilience pattern
  • CLI testing interface
  • 499 lines of solid implementation

The Calendar integration wasn’t missing. It was just somewhere unexpected, using the MCP pattern we’d just discovered with Notion.

When assumptions meet architecture

At 8:36 PM, the picture finally clarified:

All three integrations use MCP pattern.

Not three traditional routers like GitHub. Three lightweight router wrappers around existing MCP adapters:

  • Slack: Has traditional spatial pattern, needs router wrapper
  • Notion: MCP adapter exists, needs router wrapper
  • Calendar: MCP adapter 85% complete, needs router wrapper

The MCP integration had been more complete than we had realized!

The original 32–56 hour estimate collapsed to about 12 hours. We weren’t building routers from scratch. We were wrapping proven adapters with the router pattern for QueryRouter access.

The gameplan got its third major revision. But this time, the revision made the work simpler rather than more complex. Understanding actual architecture beats assuming expected patterns.

The evening sprint

With clarity came momentum. Between 8:48 PM and midnight, systematic work produced:

Phase 0: MCP architecture investigation complete

  • Pattern documented
  • Adapter inventory verified
  • Design approach confirmed

Phase 1: CalendarIntegrationRouter complete

  • 8 methods implemented
  • Feature flag control added
  • 285 lines, following proven pattern

Phase 2: NotionIntegrationRouter complete

  • 23 methods implemented
  • Full spatial interface
  • 637 lines, comprehensive coverage

Phase 3: SlackIntegrationRouter complete

  • 20 methods implemented
  • Dual-component architecture (SlackSpatialAdapter + SlackClient)
  • 850+ lines, most complex but cleanest

By 11:23 PM, all three routers existed, tested, and verified. Cursor had independently cross-validated each one. The infrastructure was ready.

But implementation and migration are different challenges. Six services still imported adapters directly, bypassing the routers entirely. Monday morning would bring the real test: could these routers actually replace the direct imports without breaking anything?

The layers of discovery

Sunday demonstrated something crucial about complex systems work: assumptions fail in layers.

Layer 1: “Three similar routers” → Actually three different architectures

Layer 2: “14–20% complete” → States ranging from ready to seemingly missing

Layer 3: “Need to build” → Actually need to wrap existing work

Layer 4: “Missing integration” → Hidden in unexpected location

Each discovery changed the scope, the approach, the estimate. But each also brought us closer to reality. Phase −1 didn’t delay the work — it prevented us from building the wrong solution efficiently.

The methodology held. When the gameplan met reality, we revised the gameplan rather than forcing reality to match our assumptions. Investigation revealed architecture. Architecture informed approach. Approach determined scope.

The questions that matter

Sunday’s success came from asking simple questions before assuming we knew the answers:

  • Where is this code actually located?
  • What pattern does it actually use?
  • What state is it actually in?
  • What do we actually need to build?

Not “what should be there” but “what is there.” Not “how should it work” but “how does it work.” The gap between expectation and reality is where projects go wrong.

By midnight Sunday, we had three complete routers, ready for Monday’s migration work. The investigation had taken longer than expected. The discoveries had revised the scope three times. But we’d built the right thing.

Monday morning would test whether we’d built it right.

← Back to BlogAlso available on Medium