---
title: Building AI-enabled NPCs
summary: How to turn a mob into a "smart" NPC that answers tells, greets visitors, reacts to socials, and trash-talks in combat — using the LLM-backed AI service. Covers the four MOB_AI_* flags, writing personality strings, balance considerations, and when to use AI vs DG triggers.
order: 55
updated: 2026-05-19
---

# Building AI-enabled NPCs

JediMUD has an **AI service** that lets NPCs respond dynamically to player input via an LLM. When a player types `tell <npc> <message>`, walks past an AI greeter, bows at an AI emoter, or gets hit by an AI taunter, the engine builds a prompt from the NPC's personality + the situation, sends it to the AI backend, and delivers the response a couple seconds later in the NPC's voice.

For builders, this means: **any mob you make can have dynamic dialogue without writing a single trigger.** You define the personality once; the AI handles the rest.

For the implementation details (worker queue, prompt sanitization, OpenAI/Ollama fallback chain, caching), see [AI service](/staff/docs/ai-service/) on the staff docs.

## The four MOB_AI_* flags

Set on the mob via `medit <vnum>` → `A` (NPC flags). Each flag enables one behavior:

| Flag | Behavior |
|---|---|
| `AI_ENABLED` | Master switch — the mob responds to `tell <npc> <msg>` |
| `AI_GREETER` | NPC greets PCs walking into the room (60s cooldown per NPC) |
| `AI_EMOTER` | NPC reacts to socials targeting it (30s cooldown) |
| `AI_TAUNTER` | NPC trash-talks PCs when it lands damage in combat (90s cooldown) |

You can combine all four — the wise oracle who greets, reacts to bows, taunts in combat, AND answers questions. Or pick the ones that fit the character.

**`AI_ENABLED` is the gate for `tell`.** Without it, all four flags do nothing — the master switch matters.

### Cooldowns

The cooldowns are **per-NPC** — not per-player. If the Baker greets Foo at minute 0, he won't greet Bar (or Foo) until minute 1. This is intentional: it makes the NPC feel like a person rather than a slot machine, and it keeps the API costs bounded.

## Personality string

The AI's response is shaped by the NPC's **personality** — a short prose description of who they are, how they talk, what they care about. Stored in the `ai_npc_personalities` SQL table by mob vnum.

To add one, SQL is the canonical interface:

```sql
INSERT INTO ai_npc_personalities (mob_vnum, personality, enabled)
VALUES (3001,
  'You are Hans the Baker, a kindly old man in Midgaard. You speak with warmth, occasionally reference the weather, and care deeply about quality flour. You distrust elves but try to hide it.',
  1);
```

If no row exists for the mob, the AI uses a generic personality built from the mob's short desc — usable but bland.

### What makes a good personality

| Quality | Why it matters |
|---|---|
| **2-4 sentences max** | Longer = the LLM forgets details and drifts. |
| **Specific traits, not generic** | "Speaks with warmth, taps the counter when amused" beats "is friendly." |
| **One quirk per personality** | An NPC who hates elves AND loves dwarves AND stutters AND grieves a dead son AND… is confused. Pick one. |
| **In-fiction context** | Reference the zone, the era, the local politics. "Forty years in this fountain square" places the NPC in time. |
| **No meta-instructions** | Don't write "respond in one line" or "stay in character." The prompt template handles that. |

### Examples

**Good:**

```
You are Gertrude, the Midgaard fountain-keeper. You have lived in this square for forty years and know every secret. You speak slowly, look people in the eye, and remember names. You have a soft spot for orphans.
```

**Good:**

```
You are Captain Brennar, the no-nonsense quartermaster of the City Watch. You speak in short clipped sentences, suspect everyone of something, and respect only competence. You served on the southern wall during the orc siege twenty years ago.
```

**Bad — too long and meta:**

```
You are an NPC in a fantasy MUD. You should always stay in character and respond in one line. You are a baker who is friendly. Try not to break the fourth wall. Be helpful but not too helpful. Respond to greetings warmly. Don't reveal that you are AI.
```

**Bad — too generic:**

```
You are a baker. You are friendly. You sell bread.
```

### Editing personalities

There's no in-game personality editor yet. Two paths:

- **SQL** directly: `UPDATE ai_npc_personalities SET personality = '…' WHERE mob_vnum = 3001;`
- **Web staff page**: `/staff/` has links to the data; check with staff if a personality-edit UI exists for your tree.

After editing, changes take effect immediately for new prompts. Cached responses for the old prompt may keep coming back for up to an hour — clear the cache via `ai cache clear` (staff command) if you need immediate fresh responses.

## Building an AI NPC step-by-step

### 1. Build the mob normally

`medit <vnum>` and set the basics (name, descriptions, position, level, etc.) just like any other mob. The AI doesn't replace anything else — your stats / class / NPC flags all still apply.

### 2. Set the AI flags

In `medit … A`:

- Always set `AI_ENABLED` so `tell` works.
- Add `AI_GREETER` for a "comes alive when you walk in" feel.
- Add `AI_EMOTER` for social interactions.
- Add `AI_TAUNTER` for combat presence (only for fighting NPCs).

### 3. Write a personality

```sql
INSERT INTO ai_npc_personalities (mob_vnum, personality, enabled)
VALUES (
  <vnum>,
  'Your personality string here (2-4 sentences).',
  1
);
```

### 4. Save the mob

`Q` → `y` in medit.

### 5. Test

```
load mob <vnum>          spawn next to you
tell <name> hello        try a direct conversation
bow <name>               try a social if AI_EMOTER set
                         (walk out and back in for greeter)
                         (start a fight for taunter)
```

You should see responses arrive 1-3 seconds after the input. The lag is the LLM thinking.

## Common patterns

### A welcoming shopkeeper

The baker who greets, has personality, but doesn't fight:

- Flags: `AI_ENABLED`, `AI_GREETER`, `AI_EMOTER`
- No `AI_TAUNTER` — he's not a combatant.
- Personality: warm, talks about bread / the weather / passing customers.

### A combat boss with menace

The dragon who taunts mid-fight:

- Flags: `AI_ENABLED`, `AI_TAUNTER`
- No `AI_GREETER` — encounter-level mob; the entrance is dramatic enough.
- Personality: arrogant, ancient, references the smallness of mortals.

### A quest-giver oracle

The seer who answers questions:

- Flags: `AI_ENABLED`, `AI_GREETER`
- Personality: cryptic, references prophecies + the local lore. **Don't** put quest information in the personality — the LLM will hallucinate quest steps inconsistently. Use DG triggers for the actual quest logic.

### A guard with attitude

The city guard who scowls at trespassers:

- Flags: `AI_ENABLED`, `AI_EMOTER`, `AI_TAUNTER`
- Personality: cynical, distrustful, references their duty.
- Pair with a Quest_block spec proc for the actual gate-keeping behavior; AI handles the flavor.

## What players see

When the AI fires, the NPC `say`s, `emote`s, or `tell`s back to the player. From the player's perspective, it's normal NPC speech — they don't see "AI thinking..." or any indication the line is generated.

Latency is typically 1-3 seconds (LLM round trip). For combat taunts, there's an instant audio cue (a grunt via the sound layer) so the player knows the NPC is engaging, then the spoken line arrives a moment later.

If the AI service is disabled or fails, the NPC falls back to:

- For `tell`: silence, or the legacy `Stock_speech` spec proc if attached.
- For ambient hooks (greet/emote/taunt): nothing fires.

## AI + DG triggers — they coexist

You can put AI flags AND DG triggers on the same mob. They don't conflict — triggers fire first; if a trigger handles the event (returns 1), the AI hook doesn't fire.

This means you can:

- Use a TELL trigger for **specific** keywords ("password", "quest", "help") and let AI handle the rest.
- Use a GREET trigger for the **first** greeting (quest hook), and let the AI greeter handle subsequent visits.
- Override AI taunts for **scripted** combat phases (e.g. "phase 2: the boss summons minions and roars").

In general:

- **AI** = flavor, atmosphere, "this NPC feels alive."
- **Triggers** = mechanics, quest state, conditional logic.

Use both for the best result.

## When NOT to use AI

| Situation | Better tool |
|---|---|
| NPC needs to give a specific quest item on a specific phrase | DG TELL or RECEIVE trigger |
| Combat needs deterministic boss behavior (phase 2, enrage, summon adds) | DG HITPRCNT trigger or spec procs |
| Shop dialogue (buy/sell prompts) | `Shop_keeper` spec proc |
| Quest accept/info/complete flows | `Questmaster` spec proc + `qedit` |
| Dialogue that must be word-for-word reproducible | DG SPEECH trigger with fixed responses |
| Anything where token cost or rate-limit pressure matters | Plain triggers (free) |

AI is great for atmosphere. It's bad for anything that needs to be **exactly** the same every time, or that the game logic needs to consume.

## Cost & rate awareness

The AI service has a **rate limit** (per-minute + per-hour caps on OpenAI calls). When the rate limit is hit, requests fall back to a local Ollama instance (slower, smaller model, but free) — and eventually to silent fallback.

A busy zone with many AI greeters can burn through rate limit budget fast. Some discipline:

- Don't put `AI_GREETER` on every NPC in a crowded city — pick a few flavor characters.
- Use cooldowns to your advantage — frequent re-entries to the same room don't re-trigger the greeter for 60 seconds.
- Combat zones with many taunters multiply the load — concentrate taunters on bosses, not minions.

The system is designed to be lossy when overloaded (silent fallback rather than queueing), so over-flagging won't crash anything — just produces less talkative NPCs as the budget runs out.

## See also

- [AI service](/staff/docs/ai-service/) — staff-side technical deep dive: API integration, async handoff, security, SQL schema.
- [Building mobiles](/builders/mobiles) — the main mob-building guide; AI is a layer on top.
- [Building triggers](/builders/triggers) — for deterministic / scripted behavior to pair with AI.
- [Spec procs (catalog)](/staff/docs/spec-procs-catalog/) — service NPCs (`Shop_keeper`, `Questmaster`, `Postmaster`) that handle mechanics; AI adds flavor on top.
