I build AI products that ship — voice bots and agents in production.
I'm Tâm — Product Builder @ BIVA, in Hanoi, Vietnam. Callbots that handle real customer calls for Vietnamese transport operators, and agentic booking systems that process transactions end to end. I came to it from competitive programming, and I care less about which model is underneath than about whether the product works for the person on the other end of the call. The site itself — blog, CV, and a public API — is one monorepo prerendered to the edge, and the code lives on GitHub.
What this repo ships
This site. A TanStack Start app prerendered to static HTML and served from Cloudflare Pages, with a Pages Function proxying the API and machine-readable indexes shipped next to the pages.
Posts and short-form notes. Markdown is compiled at build time into a JSON index that both the blog and this homepage read, so there is no database in the request path.
A CV that is one source of data rendered three ways: a styled web page, a print stylesheet, and a JSON payload for machine clients.
A Hono worker on Cloudflare Workers: health checks, token-authenticated card-description streaming, form submissions backed by D1, per-route rate limiting, and a published OpenAPI document.
A clap-based command line wrapper around the data-processing crates — CSV parsing, field normalisation, deduplication, and Markdown rendering from one binary.
RFC 4180 CSV parsing compiled to WebAssembly. Handles quoted fields, embedded commas and newlines, and escaped quotes, returning a JSON 2D array.
CommonMark to HTML via pulldown-cmark, with slugged heading anchors, used to turn the repo's Markdown content into pages at build time.
Text diffing and block alignment on top of the `similar` crate, exposed to JavaScript with the same operation codes the TypeScript side already used.
Reads EXIF metadata — camera settings, timestamps, and optional GPS — straight out of an image buffer in the browser, so photo bytes never leave the tab.
The messy-input layer: regex-backed normalisation of dates, licences, numeric parameters, free text, and compute figures into one canonical shape.
Merges records from several sources into one deduplicated set in WebAssembly, keeping the Rust structs field-for-field identical to their TypeScript counterparts.
Small shared helpers — regex escaping and slug generation — kept in Rust so the WebAssembly and native builds cannot drift apart.
The smoke test for the toolchain: one exported function that proves wasm-pack, the workspace, and the JS bindings still build end to end.
Areas of Expertise
Agents
top skillAgentic application development, end to end — the move from competitive programming into agents that take real actions for real users rather than demos.
Multi-agent Systems
top skillListed among the owner's top skills alongside agents and agent booking: several agents cooperating to carry one task through to completion.
Agent Booking
top skillBooking systems that process transactions end to end, with verify-gated completion: fail-closed admission control, so the bot never confirms what it cannot guarantee.
Voice AI and Callbots
productionDesigned and deployed callbots for Vietnamese intercity bus operators — booking, routing and customer service, handling real customer calls in production.
Conversation Design
full loopOwning the whole loop for a production callbot: conversation design first, then iteration driven by what real call transcripts show.
Prompt Architecture
versionedPrompts treated as product surfaces — versioned, tested and observable — rather than strings pasted into a client and forgotten.
Evaluation Frameworks
disciplineEvaluation as a product discipline: structured audit frameworks that lint, simulate, refine, then capture the lessons for the next iteration.
Machine-readable, on purpose
This site exposes a public API and machine-readable discovery files alongside the pages.