Blog

Building a Microsoft Teams chatbot integrated with Rails: lessons from production

Most chatbot tutorials stop at:
“Bot replies to messages”
“Integration successful”
But real systems don’t fail at “hello world”.
They fail when:
  • multiple users interact at the same time
  • data needs to come from real systems
  • workflows depend on reliability
This is what changes when you move from demo → production.
The setup (what we actually built)
We built a chatbot integrated with Microsoft Teams to automate internal workflows.
High-level flow:
Microsoft Teams → Bot Framework → Node.js chatbot → Rails APIs → Response back to Teams

The goal wasn’t just conversation.
👉 It was workflow automation:
  • fetching internal data
  • triggering actions
  • sending reminders
Lesson 1: Chatbot is just an interface, not the system
A common mistake:
Treating chatbot as the main application.
In reality:
👉 chatbot = UI layer
👉 Rails = source of truth
All business logic stayed in Rails:
  • data access
  • validations
  • workflows
The bot only:
  • received input
  • forwarded requests
  • returned responses
Lesson 2: API design matters more than bot logic
Early on, we tried handling too much inside the bot.
That didn’t scale.
What worked:
👉 Clean, purpose-driven Rails APIs
Examples:
  • /tasks/remind
  • /reports/daily_summary
  • /users/status
This made the bot:
  • simpler
  • easier to extend
  • less fragile
Lesson 3: Handle latency carefully
Chat systems are sensitive to delays.
Even 2–3 seconds feels slow.
Issues we faced:
  • slow API responses
  • chained calls
  • blocking operations
Fixes:
  • moved heavy work to background jobs
  • responded quickly with acknowledgement
  • used async updates where needed
Lesson 4: Event-driven > request-response
Not everything should be synchronous.
Example:
User asks:
“Send me daily report”
Instead of:
  • generating instantly (slow)
We:
  • trigger job
  • notify when ready
👉 This improved both:
  • performance
  • user experience
Lesson 5: State management is tricky
Chatbots are conversational.
But backend systems are not.
Problems:
  • multi-step flows
  • partial inputs
  • interrupted conversations
Solution:
  • store minimal state (session/context)
  • avoid complex conversation trees
  • keep flows simple and predictable
Lesson 6: Debugging is harder than web apps
In web apps:
  • you have logs
  • you can reproduce easily
In chatbots:
  • context matters
  • user flow matters
  • timing matters
What helped:
  • structured logging (request → bot → API → response)
  • correlation IDs across services
  • logging user intent + response
Lesson 7: Keep the bot thin
The more logic you add in the bot layer:
👉 the harder it becomes to maintain
What worked best:
  • thin Node.js layer
  • Rails handles logic
  • APIs remain reusable
This also allowed:
👉 same APIs used by web + bot
Lesson 8: Security is often overlooked
Since chatbot connects to internal systems:
You must handle:
  • authentication
  • access control
  • data exposure
We ensured:
  • API-level authentication
  • role-based access
  • limited data responses
What actually made the difference
Not the chatbot.
But:
👉 how well it was integrated into the system
The real value came from:
  • clean APIs
  • async processing
  • clear boundaries
Final thought
Building a chatbot is easy.
Building one that:
  • works reliably
  • integrates with real systems
  • scales with usage
…is a different problem.
And most of it has nothing to do with the chatbot itself.
If you’re planning something similar
Don’t start with:
👉 bot frameworks
Start with:
👉 your backend architecture
Because that’s where things either scale…
or break.