Voice AI and backend engineer. I work on the frameworks voice agents run on, and on the failures that only show up on a real phone call.
Fifteen fixes merged upstream β ten into livekit/agents, plus pipecat, jambonz and drachtio.
π Chennai, India Β· 2026 CS graduate Β· open to a first engineering role π Portfolio Β· LinkedIn
In the framework itself
- livekit/agents#7139 β
ConnectionPool.invalidate()closed sockets that were still streaming, and a handshake in flight escaped invalidation entirely and stayed reusable with stale settings. Eleven plugins call it fromupdate_options, so one change to the primitive repaired all of them. Reviewed line by line by a maintainer. - #7054 β found a whole bug class, fixed all fifteen instances across library, examples and tests, and got ruff's
RUF006enabled in their CI so dangling tasks cannot come back.
Provider plugins β the same stale-handshake bug, found by grepping siblings for the shape
- #7132 asyncai Β· #7133 neuphonic Β· #7140 cartesia, where the API version was also sent in a header that disagreed with the body it was built for
Lifecycle and cleanup
- #7023 β an STT connection pool that stayed open after shutdown
- #7012 β per-stream HTTP sessions leaking through a
WeakSet - #7050 β a discarded prewarm task rebuilding a pool after close
- #7341 β LiveAvatar built its own
aiohttpsession instead of the job's shared one, so the session outlived the job that owned it - #7237 β respeecher retired whole connection pools on a model change, leaving idle sockets for the old model open and orphaning a stream's socket in a pool nothing closes
- pipecat#5632 β an STT service rebuilt its config on a settings change, but the running gRPC stream took its config once at open, so a mid-session language change kept transcribing with the old one
- pipecat#5464 β a TTS service wrote model, voice and language only into its websocket init message, so a runtime change was stored, warned about, and silently never sent
SIP and telephony
- jambonz#1585 β a TTS
stream_resumedevent sent to a different hook path than the one it resumed - jambonz#1584 β a call transferred between feature servers re-sent trying, ringing and in-progress statuses the application had already received
- drachtio-srf#240 β proxied responses built their header strip list from the request option, so the wrong headers were stripped and forwarded
Open PRs across livekit/agents, pipecat, litellm and drizzle-orm, plus fixes sent to nine voice-AI vendors' own SDKs β Gnani, Simplismart, Rumik, Respeecher, SonexLabs, Replicate, Supertonic, Maya Research and Cosmo.
pipecat-plugin-health β a nightly check that installs every community Pipecat plugin in the docs against the latest release and against main, so a breaking change shows up before users hit it. It found that 19 of 56 could not be used with pipecat 1.11; seven broke on one renamed name, and each of those now has a fix.
Take a bug fixed in one place, then grep every sibling for the same shape β it is almost never alone. Then verify by mutation: revert the fix and confirm the new test fails. A test that passes both ways has told me nothing.
Most of it started with debugging real calls on my own voice agent: audio arriving out of order, sessions torn down mid-sentence, a connection quietly serving the wrong voice after a settings change.
Atlas β an outbound voice agent on Twilio Media Streams and Deepgram. Barge-in, a call-session state machine, outcome classification, dialling constrained to legal calling hours, and SMS/WhatsApp on one session model. ~31,000 lines, solo.
InvoiceCheck.in β GST invoice verification, live. An 11-point compliance check run before marketplaces reject an invoice, OCR auto-fill, Razorpay pay-per-check.
Python asyncio pytest Β· LiveKit Agents Pipecat jambonz drachtio Β· Twilio Programmable Voice & Media Streams SIP WebRTC Deepgram Β· TypeScript NestJS Next.js Β· Postgres Prisma Redis BullMQ Β· Docker CI/CD



