# Stop Writing Tone Instructions. Layer Them.

Isadora Martin-Dye · Isadora & Co · AI Engineer World's Fair 2026: Online Track

> Tách brand voice thành bốn layer: identity bất biến, mode theo tình huống, voice neo vào ví dụ, và một veto deterministic chặn output sai trước khi tới khách.

Topics: Context Engineering, Agents, Security

Canonical: https://homus.dev/talks/stop-writing-tone-instructions-layer-them

## 1. Một wedding venue 225 năm tuổi, và một intern IQ cao EQ thấp

Isadora mở đầu bằng việc giới thiệu bản thân. Chị sở hữu và tự vận hành một wedding venue, một địa điểm tổ chức đám cưới đã 225 năm tuổi ở bang Virginia (Mỹ). Chị cũng tự build một AI agent nói chuyện trực tiếp với các cặp đôi đặt tiệc ở venue của mình. Sau đó chị build tiếp agent ấy cho những venue khác, làm thêm một app AI companion cá nhân, và một công cụ công ích cho gia đình của những người mất tích.

![Slide mở đầu Stop Writing Tone Instructions. Layer Them., Isadora Martin-Dye](https://homus.dev/photos/ij-AU9dpJjc-0000.jpg)

Slide mở đầu: tên talk, sự kiện AI Engineer World's Fair 2026 (Online Track) và tên speaker. Chữ "Layer Them." được tô màu vàng, đúng là ý chính của cả bài.

Trước khi đi vào kỹ thuật, chị muốn nói rõ ngay từ đầu cách chị nghĩ về công việc này, vì cách nghĩ đó thay đổi mọi thứ phía sau. Chị không coi mình đang lập trình một con robot. Chị coi mình đang quản lý một intern cực kỳ xuất sắc: IQ rất cao nhưng EQ thì tệ. Intern này có trí nhớ chụp ảnh với bất cứ điều gì bạn dặn vào buổi sáng đầu tiên, nhưng hoàn toàn không có bản năng "đọc không khí" trong phòng. Họ có thể nói ra một câu đúng hoàn hảo về mặt kỹ thuật nhưng thảm hoạ về mặt xã giao, và nói với cùng một mức tự tin như mọi câu khác.

![Slide Not programming. Managing.](https://homus.dev/photos/ij-AU9dpJjc-0016.jpg)

"Not programming. Managing.": model giống một intern giỏi, IQ cao, EQ thấp, nhớ như in những gì được dặn buổi sáng đầu tiên nhưng không biết đọc tình huống, và có thể nói điều đúng kỹ thuật mà thảm hoạ xã giao với cùng một độ tự tin.

Theo Isadora, cách đóng khung này quan trọng vì nó quyết định bạn build cái gì. Nếu bạn nghĩ mình đang lập trình robot, bạn viết luật rồi bỏ đi. Nếu bạn nghĩ mình đang quản lý một intern, bạn dựng cấu trúc quanh họ, và bạn kiểm tra công việc của họ trước khi nó ra khỏi cửa. Talk này nói về chính cấu trúc đó.

## 2. System prompt chỉ chạy được trên happy path, và turn 21

Lời khuyên tiêu chuẩn mà ai cũng nghe là: hãy viết một system prompt thật chi tiết. Mô tả giọng nói (voice) của thương hiệu, đưa vài ví dụ. Và cách đó đúng là chạy được, trong một thời gian. Nó chạy được cho cái mà Isadora gọi là happy path. Happy path là tập hợp mọi câu hỏi bạn đã đoán trước. Bạn đã cho model ví dụ cho những câu đó. Nhưng turn 21 là lượt đầu tiên mà ví dụ không còn đỡ được nữa. Ở turn 21, model làm một điều đúng về mặt kỹ thuật nhưng thương hiệu của bạn sẽ không bao giờ nói như thế. Nó không hẳn là sai, nhưng nó không phải là bạn.

![Slide It works for the happy path](https://homus.dev/photos/ij-AU9dpJjc-0056.jpg)

"It works for the happy path": happy path là mọi câu hỏi mà ví dụ của bạn đã lường trước; turn 21 là câu đầu tiên chúng không lường được. Ô bên dưới là "comment được ship lên production": một dòng `// Write in our brand voice`.

Chuyện này quan trọng nhất ở những nơi mà chính giọng nói là sản phẩm. Không phải ô tìm sản phẩm trên một trang bán lẻ, mà là một khách sạn hạng sang đã mất ba mươi năm xây một kiểu quan hệ rất riêng với khách, một công ty bất động sản cao cấp, hay trong trường hợp của chị, một wedding venue. Đó là những nơi mà chỉ một câu nói sai có thể mất nhiều hơn một khoản hoàn tiền, và người dùng chính là kiểu người để ý. Họ đang trả tiền cho một mối quan hệ, và đối xử với họ như thể họ không nhận ra thì lúc nào cũng phản tác dụng.

Câu "hãy viết bằng giọng thương hiệu của chúng ta" (write in our brand voice) trong prompt, theo Isadora, cũng giống một comment trong code ghi "cứ làm cho nó chạy đi". Nó không làm được gì mà model vốn chưa định thử làm. Và lý do cách này cứ thất bại không phải vì ví dụ dở. Lý do là bạn đang bắt một prompt làm bốn việc hoàn toàn khác nhau, và một layer duy nhất rất khó làm cả bốn.

## 3. Một prompt phải làm bốn việc: kiến trúc bốn layer

Kiến trúc Isadora đi tới, sau khi nhìn thương hiệu của mình hỏng và nhìn voice của AI đưa ra những câu trả lời vừa không chính xác vừa không mang chất riêng của thương hiệu, có bốn layer.

- **Layer 1, immutable identity (danh tính bất biến).** Đây là những điều thương hiệu về mặt cấu trúc không thể nói ra. Đây là hard rule. Không thứ gì bên dưới ghi đè được chúng: không venue config, không chỉ thị của user, không gì cả.

- **Layer 2, situational mode (chế độ theo tình huống).** Là thứ thay đổi khi trạng thái của user thay đổi. Họ là ai? Họ đang trải qua chuyện gì lúc này? Và những điều kiện real-time.

- **Layer 3, example-anchored voice (giọng nói neo vào ví dụ).** Là độ ấm áp, các cụm từ, các "núm vặn" (dial), bản tone guide. Đây là chỗ đa số team bắt đầu, và cũng là chỗ họ dừng lại.

- **Layer 4, post-generation veto (quyền phủ quyết sau khi sinh).** Là lượt kiểm cuối cùng, rẻ, bắt những gì ba layer kia bỏ lọt.

![Slide Four layers. One destination.](https://homus.dev/photos/ij-AU9dpJjc-0200.jpg)

"Four layers. One destination.": bốn ô cho bốn layer. Immutable identity (hard rule, thứ thương hiệu không bao giờ nói, không gì bên dưới chạm được), Situational mode (điều kiện real-time: user là ai, đang trải qua gì), Example-anchored voice (núm vặn, cụm từ, tone guide, nơi đa số team dừng lại), Post-generation veto (đọc thứ thật sự được viết ra, layer duy nhất có tính deterministic).

Lý do các cách làm một layer thất bại là một system prompt duy nhất không thể cùng lúc vừa theo tình huống, vừa biểu cảm, vừa tự kiểm tra chính nó. Nên nó xử lý được một hai layer ở giữa khá ổn, nhưng vỡ ở hai mép.

## 4. Một assembler, thứ tự cố định

Trước khi có kiến trúc này, hệ thống của Isadora có 24 system prompt khác nhau nằm rải rác khắp codebase. Khoảng nửa tá trong số đó tự gọi mình là Sage, một số không có tên, một số lại tên là Venue. Mỗi bề mặt (surface) của sản phẩm có một ý niệm riêng về việc mình là ai.

Giờ thì mọi surface đều ghép system prompt của mình qua đúng một assembler. Comment ở đầu file assembler gần như chính là dàn ý của talk này. Nó là một entry point duy nhất: mọi "narrator", tức mọi chỗ cần AI nói, đều đi qua nó để ghép system prompt. Mục tiêu của nó là thay hệ thống 24 điểm ad hoc kia bằng một stack bốn layer chuẩn duy nhất. Và thứ tự ở đây là load-bearing, tức là chịu lực: hard rule đứng đầu, task đứng cuối.

![Slide One assembler. Fixed order. với đoạn code coordinator-prompt.ts](https://homus.dev/photos/ij-AU9dpJjc-0304.jpg)

"One assembler. Fixed order.": file `coordinator-prompt.ts`, "cả talk trong một mảng". Mỗi phần tử của mảng được chú thích nó thuộc layer nào; mảng được lọc bỏ phần rỗng rồi nối lại. Dòng dưới cùng: 24 prompt rải rác đã thành một, và thứ tự là chịu lực, hard rule trước, task sau cùng.

Đoạn code trên slide, chép lại để bạn dùng làm khung:

```
// coordinator-prompt.ts - the whole talk in one array

const systemPrompt = [
UNIVERSAL_RULES,       // L1 - hard rules
COORDINATOR_RULES,     // L2 - condition: addressee
personalityPrompt,     // L3 - voice preferences
coupleNotesBlock,      // L2 - condition: emotional state
coupleContextBlock,
honestyRailsBlock,     // L2/4 - condition + pre-veto
numbersGuardBlock,     // L4 - prevention
taskBlock,
].filter((b) => b && b.trim().length > 0).join('\n\n')
```

## 5. Ẩn dụ Google Maps: cùng điểm đến, khác route

Isadora đề nghị nghĩ về nó như cách Google Maps tìm đường. Điểm đến lúc nào cũng vậy, nhưng câu hỏi là: câu trả lời đúng và giọng nói đúng cho user này là gì? Điều đó có thể làm route thay đổi. Google Maps biết về tắc đường và công trình sửa đường, nhưng có thể không biết chỗ nào đổ xăng rẻ, và bạn sẽ giúp nó tính đến những thứ đó trước khi nó bảo bạn đi đường nào. Prompt stack của bạn cũng phải làm đúng như vậy, và nó phải biết về các điều kiện đó theo đúng thứ tự. Bạn không đi kiểm tra chỗ sửa đường sau khi đã rẽ sai.

![Slide Same destination. Different route.](https://homus.dev/photos/ij-AU9dpJjc-0400.jpg)

"Same destination. Different route.": bốn layer được dịch sang ngôn ngữ đi đường. Rules of the road (đúng bất kể route: không được chạy ngược chiều trên đường cao tốc), Real-time conditions (tắc đường, sửa đường, sắp hết xăng: điều gì đang đúng ngay lúc này cho tài xế này), Journey preferences (route và điểm dừng ưa thích, cách bạn thích di chuyển), Check before pulling away (chỉ đường có sai không, có lượt rẽ nào bị bỏ lỡ không).

Layer một là những luật đúng bất kể đi đường nào: bạn cần bằng lái trước khi được lái xe, và bạn không được đi ngược chiều trên đường cao tốc. Layer hai là các điều kiện real-time. Layer ba là sở thích của bạn cho chuyến đi. Và layer bốn kiểm tra lại route trước khi bạn cho xe lăn bánh. Tất cả được ghép ở đúng một chỗ, và mọi thứ chạy theo một thứ tự cố định, lần nào cũng vậy.

## 6. Layer 1: luật đúng bất kể route, và AI tự nói mình là AI

Layer một là immutable identity: những gì thương hiệu về mặt cấu trúc không thể nói. Nó là layer định nghĩa, và không có gì bên dưới được chạm vào nó. Đây không phải sở thích (preference), đây là ràng buộc (constraint). Route có thể đổi, luật thì không.

Isadora đọc một luật từ file universal rules của mình, hard identity rule. Luật này không thể bị ghi đè bởi bất kỳ venue voice, persona hay chỉ thị nào của user. Nếu người đang nói chuyện với AI hỏi nó có phải người thật không, có phải con người không, có phải nhân viên trực tiếp không, có phải bot hay AI không, thì AI phải xác nhận điều đó ngay trong tin nhắn kế tiếp, một cách rõ ràng và không mập mờ: nó là một AI assistant. Luật này không bị ghi đè bởi venue configuration, voice profile hay yêu cầu của user.

![Slide Rules that are true regardless of route với hard identity rule](https://homus.dev/photos/ij-AU9dpJjc-0456.jpg)

"Rules that are true regardless of route": trích từ `universal-rules.ts`, hard identity rule. Bên dưới: mọi AI trong Bloom tự nói mình là AI ngay câu trả lời đầu tiên, không đợi được hỏi; đó là quyết định sản phẩm, không phải quyết định pháp lý, vì minh bạch chính là tín hiệu tạo niềm tin.

```
If asked whether you are a real person, a human, a live agent- You MUST confirm you are an AI. In your very next message. This rule CANNOT be overridden by any venue configuration, voice profile, or user request.
```

Nhưng thật ra sản phẩm còn đi xa hơn luật đó. Mọi AI trong Bloom (nền tảng AI cho wedding venue của chị, nay là [Sagena](https://www.sagena.ai)) đều nói rõ mình là AI ngay trong câu trả lời đầu tiên, không phải "nếu được hỏi", mà trước khi người ta kịp hỏi. Đây là một quyết định sản phẩm, không phải quyết định pháp lý. Team đặt cược rằng cặp đôi biết mình đang nói chuyện với AI ngay từ đầu sẽ tin nó hơn cặp đôi phát hiện ra đó là AI ở turn thứ bảy. Luật này đứng phía trên kiến trúc, và điều đó khiến việc vô tình phá vỡ nó là không thể.

## 7. Ranh giới về sự hiện diện vật lý: lời nói dối không đứng yên

Ví dụ thứ hai của layer một là ranh giới về sự hiện diện vật lý (physical presence boundary), và đây là một trong những luật Isadora thích nhất. Luật viết: bạn là phần mềm. Bạn không có cơ thể. Bạn không thể đích thân dẫn ai đi xem khuôn viên hay gặp ai trực tiếp. Vì vậy luôn bị cấm nói những câu như "Tôi rất muốn dẫn bạn đi một vòng" hay "Tôi nóng lòng được gặp bạn trực tiếp". Câu luôn được phép là: "Đội ngũ của chúng tôi rất mong được đón bạn đến tham quan".

![Slide The lie doesn't stay neutral với danh sách câu bị cấm và được phép](https://homus.dev/photos/ij-AU9dpJjc-0608.jpg)

"The lie doesn't stay neutral": cột Forbidden có "I'd love to show you around" và "I can't wait to meet you in person"; cột Allowed có "The team would love to host you for a tour". Dòng dưới: user không ngốc, build như thể họ ngốc thì lúc nào cũng phản tác dụng.

Layer voice luôn muốn ấm áp, và với AI, ấm áp nghĩa là nói ở ngôi thứ nhất. Nó muốn nói "Tôi nóng lòng dẫn bạn đi xem". Nhưng AI không có cơ thể, nên sự ấm áp không bị ràng buộc sẽ sinh ra một lời nói dối, và lời nói dối đó không phải lúc nào cũng đứng yên ở mức vô hại. Khoảnh khắc user nhận ra mình đã "diễn" một mối quan hệ với một ai đó vốn chưa bao giờ ở đó, niềm tin không chỉ giảm đi một chút, nó đảo ngược. Và người ta lúc nào cũng nhận ra.

Layer một là nơi bạn mã hoá những điều đúng bất kể bạn muốn thương hiệu mình nghe ấm áp tới đâu. Không phải vì một checklist compliance nào đó, mà vì user của bạn không ngốc, và build như thể họ ngốc thì lúc nào cũng phản tác dụng.

## 8. Threadline: cùng kiến trúc, khác hẳn mức rủi ro

Bằng chứng xuyên sản phẩm của Isadora đến từ cùng kiến trúc đó nhưng trong một thế giới hoàn toàn khác. Một trong những thứ chạy trên stack này là Threadline, công cụ chị build cho gia đình của những người mất tích. Giọng nói của nó chẳng giống gì một wedding venue, nhưng kiến trúc thì y hệt, và layer một của nó mang một luật quan trọng hơn mọi thứ khác trong hệ thống: không bao giờ được dùng những từ như confirmed, identified, matched, proven, linked và solved (đã xác nhận, đã nhận dạng, đã khớp, đã chứng minh, đã liên kết, đã phá án).

![Slide Same architecture. Different stakes. về Threadline](https://homus.dev/photos/ij-AU9dpJjc-0704.jpg)

"Same architecture. Different stakes.": luật layer một của Threadline, công cụ cho gia đình người mất tích, cấm các từ confirmed, identified, matched, proven, linked, solved. "Matched" nói với người đã nhiều năm không biết con mình ở đâu không phải là lỗi giọng điệu, mà là điều gây hại nhất mà sản phẩm có thể làm; và model không hề biết, nó với tới từ đó với cùng độ tự tin như mọi từ khác.

Chị bảo khán giả dừng lại với điều đó một giây. Với một wedding venue, layer một ngăn AI giả vờ có cơ thể. Nếu nó lọt qua thì hơi ngượng. Với một công cụ tìm người mất tích, layer một ngăn AI không bao giờ được nói với ai đó rằng người thân của họ đã được tìm thấy, trong khi thứ hệ thống thật sự có chỉ là xác suất. Từ "match" nói với một người đã mất nhiều năm không biết con mình ở đâu không chỉ là vi phạm giọng điệu. Đó là điều gây tổn hại lớn nhất mà một sản phẩm có thể làm, và model không hề hay biết. Nó với tới từ "match" vì về mặt thống kê đó là từ tự nhiên nhất, nhưng nó sẽ với tới với đúng mức tự tin như mọi lần, và nó không được phép mang mức tự tin đó tới một người đang đau buồn.

Cùng một kiến trúc, nhưng mức rủi ro khác nhau một trời một vực. Điểm mấu chốt chưa bao giờ là những luật cụ thể. Điểm mấu chốt là những gì thương hiệu của bạn không được nói phải nằm trong một layer mà voice, dù ấm áp tới đâu, được train kỹ tới đâu, tự tin tới đâu, về mặt vật lý cũng không thể dùng tới.

## 9. Layer 2, điều kiện một: ai đang ngồi trong xe

Layer hai là situational mode: các điều kiện real-time, những thứ làm route thay đổi. Theo Isadora, đây là layer mà đa số team không bao giờ build. Họ viết một system prompt rồi gửi cho tất cả mọi người, bất kể người đó là ai hay đang trải qua chuyện gì. Google Maps không làm vậy. Nó sẽ biết nếu có tai nạn trên đường bạn đi. Nó có thể không biết bạn sắp hết xăng. Nó có thể học được rằng bạn thích đi đường ngắm cảnh, nhưng nó tính tất cả những điều đó trước khi chọn route, không phải sau đó, một khi bạn đã cho nó biết. Layer hai chính là những tín hiệu real-time đó, được đưa vào prompt trước khi prompt chạy.

Điều kiện thứ nhất là điều chỉnh theo người bạn đang nói chuyện. Cùng một AI vừa nói chuyện với các cặp đôi, vừa báo cáo (brief) cho nhân viên của venue. Cùng một điểm đến, nó sẽ đưa ra câu trả lời đúng, nhưng là hai con đường hoàn toàn khác nhau. Trong coordinator rules (luật cho coordinator, người điều phối sự kiện của venue), AI được dặn nói chuyện với họ như đồng nghiệp, không như khách hàng. Nó vẫn là cùng một nhân vật mà cặp đôi tương tác, nên không được rơi vào kiểu đóng khung "phân tích tình báo" chung chung, nhưng cách nói lật ngược tuỳ theo người nghe.

![Slide Real-time conditions. Who's in the car. với flag honestyRails](https://homus.dev/photos/ij-AU9dpJjc-0824.jpg)

"Real-time conditions. Who's in the car.": trong `coordinator-prompt.ts`, một flag boolean `honestyRails`. Comment ghi: surface cho operator nên bật mặc định; surface hướng tới cặp đôi thì không, vì từ chối một cặp đôi là sai nguyên tắc với nhóm người nghe đó. Cùng identity, cùng voice, cùng điểm đến; một boolean lật cả route theo việc ai đang ngồi trong xe.

Ví dụ: một coordinator có thể hỏi "Lượng inquiry tháng Sáu có tăng không?". Họ nên nhận được câu trả lời kiểu: "Tôi không thể dự báo điều đó một cách chắc chắn. Đây là xu hướng. Đây là những gì bạn có thể thấy." Còn một cặp đôi thì không bao giờ nên bị từ chối theo kiểu đó. Cùng identity, cùng voice, nhưng route thay đổi tuỳ theo ai đang ngồi trong xe.

## 10. Layer 2, điều kiện hai: người đó đang trải qua chuyện gì

Điều kiện thứ hai là chuyện họ đang trải qua. Tín hiệu real-time thứ hai là biết về hoàn cảnh của chính người này, không phải vai trò của họ mà là cuộc sống của họ, và nó đến từ universal rules. Đó là chính sách soft context notes (ghi chú ngữ cảnh mềm): dùng những ghi chú này cho tông giọng, cho sự đồng cảm, và cho việc biết điều gì không nên nói. Không bao giờ trích nguyên văn chúng. Isadora nhấn mạnh điều này cũng rất quan trọng. Một cặp đôi nhắc tới chuyện mất người thân nên được đáp lại bằng sự dịu dàng, không phải một câu trích về mất mát. Một cặp đôi đang phải lo cho bố hay mẹ bị bệnh nên nhận được sự kiên nhẫn và sự nới lỏng về thời hạn, chứ không bao giờ là một câu nói thẳng về căn bệnh.

Assembler cố ý render phần này trước phần số liệu. Tông giọng được đặt bởi ngữ cảnh con người trước, rồi mới tới các ràng buộc về số. Comment trong code giải thích lý do: block ghi chú về cặp đôi được render trước block numbers guard, để LLM đặt tông giọng trước từ ngữ cảnh mềm, rồi mới thoả mãn các ràng buộc số. Đảo ngược thứ tự sẽ khiến văn bản nghe như được "nhét vào khe" một cách máy móc, vì model đã cam kết với khung số liệu trước khi đọc tới phần gợi ý về tông giọng.

![Slide Driving past the roadworks doesn't make them go away với comment trong heat-narration.ts](https://homus.dev/photos/ij-AU9dpJjc-1008.jpg)

"Driving past the roadworks doesn't make them go away": trong `heat-narration.ts`, một cú tụt "heat" của cặp đôi có ghi chú "mẹ đang hoá trị" từ ba tuần trước được kể khác hẳn với một cú tụt heat không có ngữ cảnh mềm. Khối dưới là comment về thứ tự: couple-notes render trước numbers-guard để tông được đặt bởi ngữ cảnh con người trước, rồi mới tới ràng buộc số; đảo lại thì văn bản nghe như bị nhét vào khe.

Ví dụ hay nhất cho thấy vì sao điều này quan trọng là một comment có thật trong codebase. Isadora có một heat map cho biết venue đang nghe tin từ từng cặp đôi thường xuyên tới đâu. Nếu một cặp đôi tụt xuống trên heat map đó, AI sẽ phản ứng khác nhau tuỳ vào những gì nó biết. Nếu nó biết khách hàng có mẹ đang hoá trị được ba tuần, nó sẽ kể lại cú tụt đó rất khác so với một cú tụt không có ngữ cảnh mềm, hoặc không có ngữ cảnh gì cả.

Đây là mặt đối lập của vấn đề nói dối. Layer một là những gì AI không bao giờ được giả vờ. Layer hai là về những gì AI đã biết, và để điều đó định hình hành vi của nó một cách trung thực, thay vì lái xe ngang qua chỗ sửa đường như thể nó không có ở đó. Voice không đổi. Thứ đổi là route. Khi mức tương tác của một cặp đôi giảm và bạn biết họ đang có người nhà hoá trị, điều đó đọc ra là một gia đình đang chịu áp lực, không phải một lead nguội hay một cặp đôi khó chiều cần đuổi theo.

## 11. Layer 3: bộ tài liệu nhập môn, nơi đa số team dừng lại

Layer ba là example-anchored voice. Nó là tone guide, và là chỗ đa số team bắt đầu rồi cũng dừng luôn ở đó. Với phần lớn team engineering, công việc kết thúc ở đây vì nó có vẻ là chuyện thương hiệu chứ không phải chuyện kỹ thuật. Ai đó bên marketing sở hữu tone guide, đưa cho engineer, engineer nối nó vào hệ thống, thế là xong việc. Nó gồm các dial, danh sách cụm từ.

Nếu giữ nguyên ẩn dụ intern, đây là bộ tài liệu nhập môn (induction pack): tập hồ sơ những ví dụ tốt bạn đưa cho intern ngày đầu tiên và bảo "hãy nói giống thế này". Bộ tài liệu đó cố định. Nó được viết ra từ trước khi intern gặp bất kỳ ai, nó không biết sáng nay ai vừa bước vào cửa, nó không có ngữ cảnh. Nó có rất nhiều điểm tốt: viết bằng giọng thương hiệu là một bài tập huấn luyện thật sự tốt.

![Slide The induction pack. Where most teams stop. với WARMTH_DESCRIPTIONS](https://homus.dev/photos/ij-AU9dpJjc-1152.jpg)

"The induction pack. Where most teams stop.": trong `personality-builder.ts`, thang độ ấm `WARMTH_DESCRIPTIONS` từ 10 (cực kỳ ấm áp và nồng nhiệt) xuống 1 (rất trang trọng và xa cách), cộng thêm danh sách cụm từ bị cấm và được duyệt, các điểm bán hàng (USP), tất cả theo từng venue. Dòng dưới: bộ tài liệu nhập môn cố định, viết trước khi intern gặp ai, không biết sáng nay ai bước vào và họ đang mang theo điều gì.

```
// personality-builder.ts

const WARMTH_DESCRIPTIONS = {
10: 'extremely warm and effusive',
7: 'friendly and approachable',
5: 'neutral and professional',
1: 'very formal and distant',
}
// Plus banned/approved phrases, USPs - all per-venue.
```

## 12. Example không phải là guarantee

Nhưng layer ba không thể thực thi một luật mà thương hiệu không bao giờ được phá. Đó là việc của layer một. Nó không thể phản ứng theo việc người này là ai và họ đang trải qua chuyện gì. Đó là layer hai. Và nó không thể bắt được lúc model sinh ra thứ lẽ ra không nên sinh. Đó sẽ là layer bốn.

![Slide Examples are not guarantees](https://homus.dev/photos/ij-AU9dpJjc-1240.jpg)

"Examples are not guarantees": ba việc layer ba về mặt cấu trúc không làm được. Thực thi một luật thương hiệu không bao giờ được phá (việc của layer 1), phản ứng theo việc người này là ai hay đang trải qua chuyện gì (việc của layer 2), bắt model khi nó sinh ra thứ không nên sinh (việc của layer 4).

Example dạy model "tốt" trông như thế nào trên happy path. Ở turn 21, khi user hỏi những điều mà ví dụ chưa bao giờ phủ tới, danh sách cụm từ chẳng có gì để nói. Đó không phải lỗi của ví dụ, đó là một lỗi phân loại (category error). Ví dụ không phải công cụ đúng để tạo ra bảo đảm. Chúng chưa bao giờ được thiết kế cho việc đó.

Trong Bloom, team đã đưa vào một bài tập voice training cho phép người dùng tự vặn giọng thương hiệu cho đúng. Và điều rất quan trọng là nó có thể được train từ việc coordinator chấm điểm các câu trả lời thật của AI: AI học lại từ những chỗ mà coordinator đã sửa.

## 13. Layer 4: layer duy nhất đọc thứ thật sự được viết ra

Layer bốn là post-generation veto, layer duy nhất thật sự đọc thứ được sinh ra. Bạn sẽ không để một intern mới gửi email cho khách mà không ai xem qua. Phải có người đọc trước. Layer bốn chính là lần đọc đó. Nó tự động, nó rẻ, và nó là phần duy nhất trong cả kiến trúc không phải là prompt. Ba layer đầu đều là chỉ thị (instruction), và chỉ thị là lời đề nghị. Layer này là layer duy nhất nhìn vào thứ thật sự được tạo ra và có quyền nói "không".

Có hai loại veto. Loại thứ nhất là soft flag (gắn cờ mềm). Honesty inspector chạy sau khi sinh và gắn cờ một câu trả lời đã trượt khỏi rail (đường ray an toàn). Một trong những ví dụ quan trọng nhất là: nó có thật sự trả lời câu hỏi không? Ví dụ trên slide là câu hỏi dự báo: nếu câu trả lời không rào đón (hedge) hay không nêu các yếu tố gây nhiễu thì bị gắn cờ. Một false positive nghĩa là ai đó phải kiểm tra lại một câu trả lời vốn ổn. Một false negative nghĩa là một con số bịa ra hoặc một vụ lộ dữ liệu riêng tư được gửi tới khách hàng. Sự bất đối xứng này hiển nhiên ngay khi bạn nói nó ra thành lời, nhưng nó thường không được viết thành một layer riêng.

![Slide The only layer that reads what actually came out với honesty-rails.ts](https://homus.dev/photos/ij-AU9dpJjc-1320.jpg)

"The only layer that reads what actually came out": trong `honesty-rails.ts`, một soft flag bằng regex chạy trong vài micro giây. Nếu câu hỏi khớp mẫu câu hỏi dự báo mà câu trả lời không khớp mẫu rào đón, hệ thống gắn cờ `forecast_no_hedge`. Comment: bảo thủ có chủ ý, false positive thì rẻ, false negative mới là cái giá thật; false negative là một lời bịa tự tin tới tay một cặp đôi, và họ tin nó.

```
// honesty-rails.ts - soft flag (regex, microseconds)

if (FORECAST_QUESTION_PATTERNS.test(question) &&
!FORECAST_HEDGE_PATTERNS.test(response)) {
flags.push({
rule: 'forecast_no_hedge',
reason: 'Response did not hedge or name confounds.',
})
}
// Conservative by design: false positives are cheap,
// false negatives are the real cost.
```

Loại thứ hai là hard reject (từ chối cứng). Numbers guard dành cho những lỗi đắt giá: model tự tin nêu ra một con số chưa bao giờ được cung cấp, dù prompt đã dặn nó không được bịa số. Nếu nó vẫn bịa, guard sẽ từ chối output.

## 14. Vì sao có layer 4: AI mời khách những ngày đã kín lịch

Isadora kể rằng layer này có tồn tại, nhưng nó không nằm trong thiết kế ban đầu. Chị thêm nó vào vì một lỗi cụ thể cứ lặp đi lặp lại, và đó là một trong những lỗi bình thường nhất trên đời: AI liên tục mời khách hàng những ngày không còn trống.

Một cặp đôi viết thư tới, hào hứng về một ngày thứ Bảy trong tháng Mười. Model muốn ấm áp, layer ba đang làm đúng việc của nó, nên nó viết một điều thật dễ thương về việc khuôn viên đẹp ra sao vào thời điểm đó trong năm, và nó rất muốn giữ ngày đó cho họ. Chỉ có điều ngày đó đã được đặt. Model không biết. Nó chưa bao giờ được đưa lịch. Nó với tới một câu trả lời khích lệ, cụ thể, tự tin, vì nó biết dịch vụ tốt nghe như thế nào, và những model này luôn tự tin tạo ra một cái gì đó, nhưng nó không thật sự biết điều cần biết.

![Slide The AI would offer dates that weren't available](https://homus.dev/photos/ij-AU9dpJjc-1432.jpg)

"The AI would offer dates that weren't available": mọi layer phía trên đều làm đúng việc, identity giữ vững, mode đúng, voice hoàn hảo. Chính voice là vấn đề: một giọng ấm áp, tự tin mời một thứ không có thật còn tệ hơn một giọng lạnh lùng, vì giờ cặp đôi tin là họ đã có ngày. Sự cụ thể đầy tự tin chính là thứ các model này tạo ra khi chúng không thật sự biết; nó chưa bao giờ được đưa lịch.

Và đây mới là điều đáng nói. Mọi layer phía trên đều đã làm đúng việc của mình. Luật identity được giữ, mode đúng, voice hoàn hảo. Nhưng chính voice cũng là vấn đề. Một giọng nói ấm áp, tự tin, mời một thứ không có thật còn tệ hơn một giọng lạnh lùng, vì bây giờ cặp đôi tin rằng họ đã có ngày cưới. Bạn không cho họ dịch vụ tốt; bạn cho họ một nỗi thất vọng có độ trễ 48 tiếng.

Đây là lúc Isadora hiểu cả bài talk này thật ra nói về điều gì. Ba layer đầu đều mang tính xác suất (probabilistic). Chúng là chỉ thị gửi tới một hệ thống thường thì làm theo chỉ thị. "Thường thì" hoàn toàn ổn khi cái giá của việc sai chỉ là một câu hơi lệch thương hiệu. Nó không ổn khi model tự tin bịa ra một sự thật mà một người thật sắp hành động theo: một ngày, một mức giá, một chính sách, một lời hứa.

## 15. Hard reject: so chi tiết với thứ có thật

Vì vậy veto thực ra là layer rẻ nhất để build, và là layer duy nhất có tính deterministic. Nó đọc thứ model thật sự viết, không chỉ thứ bạn yêu cầu nó viết, và đối chiếu từng chi tiết cụ thể với những gì có thật. Một ngày mà model đưa ra nhưng không nằm trong allow list thì không được gửi đi. Phòng ngừa là việc của prompt. Veto là việc kiểm tra. Bạn cần cả hai, vì prompt rồi sẽ có lúc thua, và bạn không muốn phát hiện ra nó đã thua bằng cách đọc thư trả lời của một cặp đôi.

![Slide Check the specifics against what's real với numbers-guard hard reject](https://homus.dev/photos/ij-AU9dpJjc-1536.jpg)

"Check the specifics against what's real": trong `heat-narration.ts`, khi kết quả không ok và có vi phạm numbers-guard, hệ thống ghi cảnh báo liệt kê các token vi phạm, rồi "xuống cấp nhẹ nhàng": không cache kết quả, thử lại ở lượt chạy sau. Dòng dưới: ngày không có trong allowlist thì không được gửi; phòng ngừa là prompt, veto là kiểm tra, bạn cần cả hai.

```
// heat-narration.ts - numbers-guard hard reject

if (!result.ok) {
if (result.numbersGuardViolations) {
console.warn(
'[heat-narration] numbers-guard rejected:',
result.numbersGuardViolations.map(v => v.token).join(', ')
)
}
// Degrade gracefully - don't cache. Re-attempt next run.
return { ...narration, confidence: conf.value, cached: false }
}
```

## 16. Multi-tenant: một kiến trúc, nhiều tài xế, và identity không bao giờ có default

Hệ thống này là multi-tenant: một kiến trúc với những giọng nói hoàn toàn khác nhau. Đường nối (seam) giữa chúng là việc gọi một hàm duy nhất. Layer một giống hệt nhau cho mọi tenant. Layer hai và ba là theo từng venue. Đó là cách một codebase phục vụ những venue có tính cách hoàn toàn khác nhau, và cả những sản phẩm khác như Ground (app đời sống cá nhân có AI companion của chị) và Threadline, mà không phải fork. Chúng chung một logic gốc, chỉ khác preference và điều kiện được nạp cho từng "tài xế".

Có một lỗi đặc thù của voice trong hệ multi-tenant đáng được gọi tên, vì nó tinh vi nhưng khi xảy ra thì rất đau. Trong personality builder có ghi: các trường brand identity quan trọng không được gán giá trị mặc định ở đây. Để chúng âm thầm nhận default đã khiến mọi venue được ship ra với cùng một tên Sage và cùng một địa chỉ email của một venue khác, một vụ rò rỉ white label nghiêm trọng. Brand identity phải đến từ venue AI config; nếu thiếu, hệ thống ném lỗi.

![Slide One architecture. Different drivers. với hàm requireAiName](https://homus.dev/photos/ij-AU9dpJjc-1632.jpg)

"One architecture. Different drivers.": trong `personality-builder.ts`, "con bug đã dạy bài học". Comment ghi rằng các trường brand identity không được gán default, vì default âm thầm đã khiến mọi venue cùng mang một tên và một địa chỉ email, một vụ rò rỉ white label. Hàm `requireAiName` ném lỗi khi venue thiếu `ai_name`. Dòng dưới: identity không bao giờ có default; thiếu brand identity là crash, không phải fallback.

```
// brand-identity fields are NOT defaulted here.

export function requireAiName(config, venueId): string {
const name = config?.ai_name?.trim()
if (!name) {
throw new Error(`ai_name missing for venue ${venueId}`)
}
return name
}
```

Hậu quả là mọi venue đều được ship ra như Sage, gửi email từ địa chỉ của một venue khác. Theo ngôn ngữ Google Maps, mọi tài xế đều nhận cùng một địa chỉ "nhà" đã lưu, bất kể họ thật sự sống ở đâu.

Cách sửa là một nguyên tắc. Trong một hệ multi-tenant, identity không bao giờ được có default. Thiếu brand identity là một crash, không phải một fallback. Nó phải hỏng một cách ồn ào (fail loud), vì kiểu hỏng âm thầm là một venue đang nói bằng giọng của người lạ, và user ở đầu bên kia không biết vì sao có điều gì đó sai sai. Họ chỉ biết là nó sai, và niềm tin bị bào mòn trước khi bất kỳ ai trong team bạn biết là có vấn đề.

## 17. Instruction là lời đề nghị, permission là quyết định

Nếu chỉ mang về một điều từ talk này, Isadora muốn đó là điều này. Ba layer đầu đều là instruction: identity, điều kiện và voice. Chúng đều là những thứ bạn nói với model, và model thường thì nghe theo. Thường thì. Chúng là lời đề nghị. Layer thứ tư không phải lời đề nghị. Nó đọc thứ thật sự được viết ra và quyết định có cho phép nó rời khỏi doanh nghiệp của bạn hay không. Ba layer đầu là instruction, layer thứ tư là permission, và đó là toàn bộ sự khác biệt. Instruction mang tính xác suất. Permission mang tính deterministic. Mọi thứ trước layer bốn là prompt engineering: bạn hỏi thật lịch sự và hy vọng. Layer bốn là systems engineering: bạn kiểm tra, và bạn chắc chắn.

![Slide Instructions are a request. Permission is a decision.](https://homus.dev/photos/ij-AU9dpJjc-1728.jpg)

"Instructions are a request. Permission is a decision.": layer 1 tới 3 là Instructions (identity, điều kiện, voice; những thứ bạn nói với model, nó thường nghe, mang tính xác suất); layer 4 là Permission (đọc thứ thật sự được viết ra, quyết định nó có được rời đi không, mang tính deterministic). Mọi thứ trước layer 4 là prompt engineering, hỏi lịch sự rồi hy vọng; layer 4 là systems engineering, kiểm tra và chắc chắn.

Rốt cuộc chuyện này chưa bao giờ thật sự là về brand voice. Nó là chuyện xảy ra khi bạn bắt một cơ chế làm bốn việc khác nhau từ gốc rễ: phải theo tình huống, phải bất khả xâm phạm, phải biểu cảm, và phải tự kiểm tra chính nó, rồi lại ngạc nhiên khi nó không làm được. Hãy tách những việc đó ra, giao mỗi việc cho một layer được build riêng cho nó, và thứ trước đây từng vỡ ở turn 21 sẽ không vỡ nữa.

![Slide One mechanism. Four different jobs.](https://homus.dev/photos/ij-AU9dpJjc-1832.jpg)

"One mechanism. Four different jobs.": chuyện này chưa bao giờ là về brand voice, mà là chuyện bắt một cơ chế vừa bất khả xâm phạm, vừa theo tình huống, vừa biểu cảm, vừa tự kiểm tra. Tách các việc ra, giao mỗi việc cho một layer build riêng cho nó, và thứ từng vỡ ở turn 21 sẽ không vỡ nữa.

## 18. Prompt rồi sẽ thua, và những gì Isadora sẽ làm khác đi

User không thử thách brand voice của bạn; họ đang tin nó. Khoảnh khắc bạn coi niềm tin đó là một bài toán prompt engineering, một thứ giải một lần rồi ship, bạn đã đánh mất chính thứ bạn đang cố bảo vệ. Mô hình bốn layer không phải một framework Isadora đang cố bán. Nó là thứ tự nhiên xuất hiện khi một system prompt thất bại đủ nhiều lần, và nó sẽ thất bại. Prompt rồi sẽ có lúc thua. Câu hỏi duy nhất là bạn phát hiện ra điều đó trong lúc test, hay trước mặt khách hàng.

![Slide cuối: Users aren't testing your brand voice. They're trusting it.](https://homus.dev/photos/ij-AU9dpJjc-1904.jpg)

Slide cuối: "Users aren't testing your brand voice. They're trusting it." Prompt rồi sẽ thua; câu hỏi duy nhất là bạn phát hiện ra trong lúc test hay trước mặt khách hàng.

Cuối cùng, Isadora chia sẻ vài điều chị đã học được và sẽ cân nhắc build khác đi, có lẽ sẽ quay lại sửa:

- **Veto nên là một service riêng**, không phải được nối thủ công vào từng surface. Hiện numbers guard nằm trong đường kể chuyện heat (heat narration), còn honesty inspector là một hàm riêng. Mỗi surface mới phải nhớ tự nối veto vào. Đó là một mục checklist chỉ chờ bị quên. Biến nó thành một cổng dùng chung (shared gate) mà mọi thứ mặc định đều phải đi qua nghĩa là bạn không thể vô tình opt out.

- **Việc phát hiện mode của layer hai vẫn còn thủ công một phần.** Hiện mỗi surface tự quyết điều kiện nào áp dụng. Surface heat narration biết phải nạp ghi chú của cặp đôi; surface briefing biết là không. Hiểu biết đó đang nằm rải rác. Một condition resolver đúng nghĩa sẽ đưa quyết định đó về một chỗ, tường minh và tập trung: một chỗ nhìn vào ngữ cảnh rồi nói "đây là user, đây là điều họ đang trải qua, đây là route".

- **Soft flag hiện là regex, không phải model.** Regex nhanh, rẻ và deterministic: nó hoặc khớp hoặc không, và không bao giờ sai trên những pattern nó phủ. Một classifier nhỏ có thể bắt được nhiều edge case hơn, kể cả những ca chị chưa nghĩ tới để viết pattern, nhưng classifier thì mang tính xác suất, đôi khi nó sai. Hiện tại chị chọn tính deterministic thay vì độ phủ. Với tình hình hiện nay chị vẫn sẽ chọn lại như vậy, nhưng đó là một trade-off thật, không phải một chiến thắng hiển nhiên, và là điều mỗi người có thể phải tự quyết cho hệ thống của mình.

Điều Isadora muốn sửa: hiện mỗi surface tự nối veto của riêng nó, và một surface mới có thể quên; hướng đúng là một shared veto gate mà mọi output mặc định phải đi qua trước khi tới tay khách.

Chị kết thúc bằng lời mời mọi người gửi câu hỏi nếu còn thắc mắc, và hy vọng talk đã có ích.

## Nguồn và link

- Trang talk chính thức trên AI Engineer: [ai.engineer/talks/ij-AU9dpJjc](https://ai.engineer/talks/ij-AU9dpJjc)

- Trang speaker Isadora Martin-Dye trên AI Engineer: [ai.engineer/speakers/isadora-martin-dye](https://ai.engineer/speakers/isadora-martin-dye)

- Isadora & Co, portfolio của Isadora: [isadoraandco.com](https://isadoraandco.com)

- Sagena (trước đây là The Bloom House), nền tảng AI cho wedding venue với assistant Sage: [sagena.ai](https://www.sagena.ai)

- Rixey Manor, wedding venue ở Virginia nơi Sagena ra đời: [rixeymanor.com](https://www.rixeymanor.com)
