<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jesper Deng</title>
    <description>The latest articles on DEV Community by Jesper Deng (@jesperdeng).</description>
    <link>https://dev.to/jesperdeng</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3921325%2Fed105e8d-1ec4-4781-97b6-0472188abc23.png</url>
      <title>DEV Community: Jesper Deng</title>
      <link>https://dev.to/jesperdeng</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jesperdeng"/>
    <language>en</language>
    <item>
      <title>I Built an AI Search Monitoring Platform Because “Are We in ChatGPT?” Shouldn’t Be a Guess</title>
      <dc:creator>Jesper Deng</dc:creator>
      <pubDate>Wed, 07 Oct 2026 09:16:16 +0000</pubDate>
      <link>https://dev.to/jesperdeng/i-built-an-ai-search-monitoring-platform-because-are-we-in-chatgpt-shouldnt-be-a-guess-2m4j</link>
      <guid>https://dev.to/jesperdeng/i-built-an-ai-search-monitoring-platform-because-are-we-in-chatgpt-shouldnt-be-a-guess-2m4j</guid>
      <description>&lt;p&gt;AI search monitoring is a repeatable way to observe whether a brand appears, is mentioned, and is cited in answers to a stable set of buyer questions.&lt;/p&gt;

&lt;p&gt;It is an observation loop, not an official ranking.&lt;/p&gt;

&lt;p&gt;I built AI Search Vitals because traditional SEO reports were not answering a question I kept hearing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When a potential customer asks an AI system for a recommendation, what does it actually say about our brand?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Problem No One Talks About
&lt;/h2&gt;

&lt;p&gt;Traditional search gives you familiar signals: impressions, clicks, rankings, and backlinks.&lt;/p&gt;

&lt;p&gt;AI answers are different.&lt;/p&gt;

&lt;p&gt;The same buyer question can produce different results depending on the model, prompt wording, market, language, retrieval mode, source set, and time of day. A screenshot may show what happened once, but it does not explain whether the result is a pattern.&lt;/p&gt;

&lt;p&gt;There are four problems I wanted to solve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A brand can be relevant to a category but never appear in the answer.&lt;/li&gt;
&lt;li&gt;A brand can be mentioned without being cited as a source.&lt;/li&gt;
&lt;li&gt;A competitor can be recommended while your better explanation is ignored.&lt;/li&gt;
&lt;li&gt;A single visibility score cannot explain what changed or what to fix next.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The hard part is not generating another score. The hard part is preserving enough evidence to understand the answer behind the score.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What I Decided to Build
&lt;/h2&gt;

&lt;p&gt;AI Search Vitals is an AI search visibility monitoring platform for brands, marketing teams, SEO and GEO practitioners, agencies, and founders.&lt;/p&gt;

&lt;p&gt;The workflow starts with a project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a brand, website, market, language, and competitors.&lt;/li&gt;
&lt;li&gt;Save the buyer questions you want to monitor.&lt;/li&gt;
&lt;li&gt;Select the AI channels enabled for the workspace.&lt;/li&gt;
&lt;li&gt;Run an initial baseline.&lt;/li&gt;
&lt;li&gt;Review mentions, recommendations, competitors, and citations.&lt;/li&gt;
&lt;li&gt;Schedule daily or weekly observations.&lt;/li&gt;
&lt;li&gt;Use the results to decide which page, prompt, or content gap to improve.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The product keeps the evidence behind every successful observation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The original buyer prompt&lt;/li&gt;
&lt;li&gt;The actual model and provider&lt;/li&gt;
&lt;li&gt;Market and language&lt;/li&gt;
&lt;li&gt;Search mode and run timestamp&lt;/li&gt;
&lt;li&gt;Raw AI answer&lt;/li&gt;
&lt;li&gt;Brand and competitor mentions&lt;/li&gt;
&lt;li&gt;Ordered recommendation position when available&lt;/li&gt;
&lt;li&gt;Citation URLs, domains, titles, and snippets&lt;/li&gt;
&lt;li&gt;Token usage and request metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it possible to ask better questions than “Did our score go up?”&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the brand move from absent to mentioned?&lt;/li&gt;
&lt;li&gt;Was the mention accurate or misleading?&lt;/li&gt;
&lt;li&gt;Did the model cite our website or a competitor?&lt;/li&gt;
&lt;li&gt;Which page became the source?&lt;/li&gt;
&lt;li&gt;Did the change happen across a prompt group or only once?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI Search Vitals also includes competitor share of voice, citation exploration, prompt research, monitoring history, CSV export, and GEO audit tools for crawlability, content readiness, and AI Query Expansion.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works Under the Hood
&lt;/h2&gt;

&lt;p&gt;The application runs on Next.js 15, React, and TypeScript, with OpenNext and Cloudflare Workers handling the production runtime.&lt;/p&gt;

&lt;p&gt;Workspace, project, prompt, run, observation, mention, and citation data are stored in Cloudflare D1 through Drizzle. OpenRouter adapters keep provider metadata, usage information, citations, and raw response context instead of reducing every response to a plain string.&lt;/p&gt;

&lt;p&gt;Scheduled monitoring uses a server-controlled workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloudflare Cron finds prompts that are due.&lt;/li&gt;
&lt;li&gt;Each prompt and model target becomes a queue job.&lt;/li&gt;
&lt;li&gt;The worker executes the observation.&lt;/li&gt;
&lt;li&gt;The parser extracts mentions, positions, and citations.&lt;/li&gt;
&lt;li&gt;The observation is stored with an idempotency key.&lt;/li&gt;
&lt;li&gt;Retryable provider failures can be inspected without duplicating the result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to make AI search look deterministic.&lt;/p&gt;

&lt;p&gt;The goal is to make changes comparable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Harder Than It Sounds
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Prompt stability matters
&lt;/h3&gt;

&lt;p&gt;If the question changes every time, the result is difficult to compare.&lt;/p&gt;

&lt;p&gt;That is why AI Search Vitals stores prompt snapshots and encourages teams to separate discovery, evaluation, comparison, and task-based questions. A stable prompt set creates a baseline that can be reviewed over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Mentions need context
&lt;/h3&gt;

&lt;p&gt;Counting a brand name is not enough.&lt;/p&gt;

&lt;p&gt;The system needs to distinguish between a useful recommendation, a passing reference, an incorrect description, and a competitor comparison. A mention without context can lead to the wrong content decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. A mention is not a citation
&lt;/h3&gt;

&lt;p&gt;A model can name a brand without linking to its website.&lt;/p&gt;

&lt;p&gt;It can also cite a page for one narrow fact without recommending the whole brand. These are different signals, so they need to be measured separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Citation formats are inconsistent
&lt;/h3&gt;

&lt;p&gt;Different providers can return citations through annotations, markdown links, metadata, or no structured source list at all.&lt;/p&gt;

&lt;p&gt;The parser therefore checks provider annotations first and then uses deterministic URL extraction as a fallback. The result is not perfect, but it is inspectable and tied to the actual answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Evidence beats an opaque score
&lt;/h3&gt;

&lt;p&gt;A score can tell you that something changed. Raw answer evidence helps explain why.&lt;/p&gt;

&lt;p&gt;The useful unit is not “visibility increased by 8%.” It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For this prompt and channel, the answer changed, the brand became more specific, and this page became the cited source.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Measurement boundaries build trust
&lt;/h3&gt;

&lt;p&gt;AI Search Vitals does not claim to reproduce the first-party consumer experience of ChatGPT, Google AI Overviews, or any other platform.&lt;/p&gt;

&lt;p&gt;The current product records provider and API proxy observations. These observations are useful for repeatable analysis, but they are not official or universal rankings.&lt;/p&gt;

&lt;p&gt;Google AI Overviews still require a manual check in the target market. Estimated intent is directional, not official search volume. A citation is evidence, not a guarantee of future visibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  GEO and monitoring should be connected
&lt;/h3&gt;

&lt;p&gt;Monitoring tells you what the answer system did.&lt;/p&gt;

&lt;p&gt;A GEO audit helps investigate why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can the page be fetched?&lt;/li&gt;
&lt;li&gt;Are the headings and metadata clear?&lt;/li&gt;
&lt;li&gt;Is the entity defined consistently?&lt;/li&gt;
&lt;li&gt;Does the page contain enough evidence?&lt;/li&gt;
&lt;li&gt;Are there related questions the content should answer?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That creates a loop:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Observe → inspect evidence → improve the page → observe again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;Start with a small prompt set instead of monitoring everything at once.&lt;/p&gt;

&lt;p&gt;Use five to twelve buyer questions across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Category discovery&lt;/li&gt;
&lt;li&gt;Product comparison&lt;/li&gt;
&lt;li&gt;Recommendation&lt;/li&gt;
&lt;li&gt;Problem solving&lt;/li&gt;
&lt;li&gt;Brand-specific queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read the raw answers before reacting to the metrics. Then compare the same prompts, channel, market, and language after a content change.&lt;/p&gt;

&lt;p&gt;At the time of writing, AI Search Vitals includes a seven-day trial without a credit card, so the easiest way to start is with one project and a focused baseline.&lt;/p&gt;

&lt;p&gt;You can try &lt;a href="https://aisearchvitals.com/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=ai-search-monitoring-build" rel="noopener noreferrer"&gt;AI Search Vitals&lt;/a&gt;, read the &lt;a href="https://aisearchvitals.com/blog/ai-search-monitoring-guide" rel="noopener noreferrer"&gt;AI Search Monitoring Guide&lt;/a&gt;, or review the &lt;a href="https://aisearchvitals.com/blog/how-to-track-ai-citations" rel="noopener noreferrer"&gt;AI Citation Tracking Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am especially interested in hearing how other teams measure AI visibility without turning a changing answer into a fake ranking report.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>seo</category>
    </item>
    <item>
      <title>I Built an AI Mock Trial Platform Because Practicing Law Shouldn't Require a Full Cast</title>
      <dc:creator>Jesper Deng</dc:creator>
      <pubDate>Wed, 20 May 2026 05:20:41 +0000</pubDate>
      <link>https://dev.to/jesperdeng/i-built-an-ai-mock-trial-platform-because-practicing-law-shouldnt-require-a-full-cast-2cl5</link>
      <guid>https://dev.to/jesperdeng/i-built-an-ai-mock-trial-platform-because-practicing-law-shouldnt-require-a-full-cast-2cl5</guid>
      <description>&lt;h2&gt;
  
  
  The Problem No One Talks About
&lt;/h2&gt;

&lt;p&gt;If you're a law student preparing for mock trial, or a lawyer rehearsing for court, you face a frustrating reality: you can't practice alone.&lt;/p&gt;

&lt;p&gt;A real trial involves a judge, opposing counsel, witnesses, and jurors. To run even a basic practice session, you need to coordinate 3-5 people's schedules. Most of the time, that just doesn't happen.&lt;/p&gt;

&lt;p&gt;So what do people actually do?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Law students&lt;/strong&gt; rehearse opening statements in front of a mirror&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mock trial teams&lt;/strong&gt; only get 1-2 full run-throughs before competition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Young lawyers&lt;/strong&gt; go into their first trial with almost no live courtroom experience&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solo practitioners&lt;/strong&gt; have zero way to simulate cross-examination or hostile witnesses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fundamental bottleneck isn't skill — it's access to practice partners.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Decided to Build
&lt;/h2&gt;

&lt;p&gt;I asked a simple question: what if AI could play every other role in the courtroom?&lt;/p&gt;

&lt;p&gt;Not a chatbot that answers legal questions. Not a document tool. A full courtroom simulation where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You play the attorney (plaintiff or defense)&lt;/li&gt;
&lt;li&gt;AI plays the &lt;strong&gt;judge&lt;/strong&gt; — ruling on objections, managing procedure&lt;/li&gt;
&lt;li&gt;AI plays &lt;strong&gt;opposing counsel&lt;/strong&gt; — making arguments against you, objecting to your questions&lt;/li&gt;
&lt;li&gt;AI plays &lt;strong&gt;witnesses&lt;/strong&gt; — responding to direct and cross-examination with realistic personalities&lt;/li&gt;
&lt;li&gt;The trial follows real procedure: voir dire → opening → witness examination → closing → verdict&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end, you get scored on your performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Harder Than It Sounds
&lt;/h2&gt;

&lt;p&gt;The challenge isn't just "make AI talk like a lawyer." It's:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Multi-role coherence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The judge, opposing counsel, and witness are all AI — but they need to behave as separate people with different goals. The judge is neutral. Opposing counsel is adversarial. The witness has a backstory and may be unreliable. One model, multiple conflicting personas, in the same conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Stage management&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A trial isn't a free-form chat. It has strict procedural stages. You can't cross-examine during opening statements. The AI needs to enforce courtroom rules while still feeling natural.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Reactive complexity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you raise an objection, the judge must rule. If sustained, opposing counsel must rephrase. If you introduce surprise evidence, the witness must react consistently with their backstory. Every action cascades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Solo practice must feel real&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If it feels like talking to a chatbot, lawyers won't use it. The responses need enough unpredictability and pushback to create genuine practice pressure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start with the state machine, not the prompts.&lt;/strong&gt; I spent too long tweaking AI personalities before realizing the real problem was managing trial flow. Once I built a proper stage system (8 stages, with rules for what's allowed in each), the AI behavior fell into place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoring creates motivation.&lt;/strong&gt; Early testers would quit mid-trial. Adding a verdict with performance scoring changed everything — people now complete full trials because they want to see their score.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credits &amp;gt; subscriptions for this audience.&lt;/strong&gt; Law students are broke. A generous free tier with credits lets them actually use the tool. Power users (practicing attorneys) will pay when they see the value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;If you're curious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live platform:&lt;/strong&gt; &lt;a href="https://mocktrialonline.com" rel="noopener noreferrer"&gt;mocktrialonline.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demo video:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=CNXzT5zIVpg" rel="noopener noreferrer"&gt;YouTube walkthrough&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's free to sign up and run several full trials without paying. I'm a solo developer building this actively — feedback from anyone (devs, lawyers, or just people curious about legal AI) is genuinely welcome.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>buildinpublic</category>
      <category>startup</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I Made AI Behave Differently Based on Conversation Context (Multi-Role Prompt Engineering)</title>
      <dc:creator>Jesper Deng</dc:creator>
      <pubDate>Sat, 09 May 2026 08:35:09 +0000</pubDate>
      <link>https://dev.to/jesperdeng/how-i-made-ai-behave-differently-based-on-conversation-context-multi-role-prompt-engineering-26o6</link>
      <guid>https://dev.to/jesperdeng/how-i-made-ai-behave-differently-based-on-conversation-context-multi-role-prompt-engineering-26o6</guid>
      <description>&lt;p&gt;I've been working on a project that requires multiple AI "characters" to behave differently in the same conversation — think of it like NPCs in a game, except each one needs to respond based on their role, personality, and the current situation.&lt;/p&gt;

&lt;p&gt;Here's what I learned about making this work reliably.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;If you just tell an AI "you are character A" and "you are character B" in separate prompts, they all end up sounding the same. Generic. Helpful. Boring. You need them to have distinct behaviors — one should be cooperative, another defensive, another authoritative.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Behavioral constraints &amp;gt; personality descriptions
&lt;/h3&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a friendly witness who is helpful.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a witness being questioned. Rules:
- Only answer what is directly asked
- If the question is vague, ask for clarification
- Never volunteer extra information
- If pressed on a contradiction, become defensive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Constraints produce more consistent behavior than adjectives.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Context-dependent behavior switching
&lt;/h3&gt;

&lt;p&gt;The same character might need to behave differently depending on who's talking to them. I handle this by passing a &lt;code&gt;mode&lt;/code&gt; parameter in the system prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;friendly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hostile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You are &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Background: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bio&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;friendly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n\nBehavior: Be cooperative. Give detailed answers. Expand on your responses when appropriate.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n\nBehavior: Be defensive. Give minimal answers. Only confirm what you cannot deny. Redirect when possible.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tiny switch makes a huge difference in how natural the responses feel.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. State management across turns
&lt;/h3&gt;

&lt;p&gt;The hardest part: making characters remember what happened earlier and adjust. I maintain a simplified state object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ConversationState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;currentSpeaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;previousStatements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;contradictions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;mood&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;neutral&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;defensive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;confident&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before each AI call, I inject a summary of what's happened so far. This keeps responses contextually aware without blowing up the token count.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The "don't be helpful" problem
&lt;/h3&gt;

&lt;p&gt;LLMs are trained to be helpful. When you need a character to be evasive or unhelpful, you have to fight against this training. What works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicitly say "you do NOT want to help the questioner"&lt;/li&gt;
&lt;li&gt;Give the character a motivation for being difficult&lt;/li&gt;
&lt;li&gt;Add examples of deflection in the prompt
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are being questioned about something you want to hide.
Your goal is to answer without revealing [specific fact].
Techniques you use: giving technically true but misleading answers,
answering a different question than what was asked, saying "I don't recall."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Temperature matters more than you think
&lt;/h3&gt;

&lt;p&gt;For authoritative characters (judges, experts), use lower temperature (0.3-0.5). They should be consistent and decisive.&lt;/p&gt;

&lt;p&gt;For emotional or unpredictable characters, bump it up (0.7-0.9). The randomness makes them feel more human.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaway
&lt;/h2&gt;

&lt;p&gt;Multi-role AI isn't about writing better character descriptions. It's about defining behavioral rules, injecting context, and fighting the model's default "helpful assistant" mode. Once I figured that out, everything clicked.&lt;/p&gt;

&lt;p&gt;Would love to hear if anyone else is doing multi-agent stuff — what patterns are you using?&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
  </channel>
</rss>
