> For the complete documentation index, see [llms.txt](https://wiki.halosdev.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.halosdev.com/halos-player-spoofer/setup-guide/ai-chat-setup-guide.md).

# AI Chat Setup Guide

{% hint style="warning" %}
**Read this first:** The AI Chat module is currently in BETA. You are responsible for any LLM provider bills you incur. Set a spending limit on your provider account or API key before enabling. We cannot guarantee any specific bill amount — that depends entirely on your settings and server activity.
{% endhint %}

### Quick Start

If you've used an LLM API before, the short version:

1. Pick a provider: OpenAI, Gemini, Anthropic, or local Ollama
2. Generate an API key
3. Edit `plugins/HalosPlayerSpoofer/ai-chat.yml`:
   * Set `enabled: true`
   * Set `provider-type` to your provider
   * Paste your API key into `api-key`
   * Set `model-name` to your provider's exact API identifier (see Step 3)
4. `/halos reload` or restart the server
5. Watch fake players start chatting in-game within a few minutes

If anything fails, see Troubleshooting.

### Step 1: Choose a Provider

| Provider           | Cost                | Quality   | Setup difficulty |
| ------------------ | ------------------- | --------- | ---------------- |
| **Google Gemini**  | Free tier available | Excellent | Easy             |
| **OpenAI**         | Pay-per-use         | Excellent | Easy             |
| **Anthropic**      | Pay-per-use         | Excellent | Easy             |
| **Ollama** (local) | Free                | Variable  | Advanced         |

For most server owners, **Gemini is the cheapest entry point** because of its generous free tier. **OpenAI** is the most reliable and widely tested. **Ollama** is the only option if you want zero LLM costs, but requires you to run a local model on your own hardware.

### Step 2: Get Your API Key

Generate a key from your chosen provider:

* **Gemini:** <https://aistudio.google.com/apikey>
* **OpenAI:** <https://platform.openai.com/api-keys>
* **Anthropic:** <https://console.anthropic.com/settings/keys>
* **Ollama:** No key needed — set `base-url` to your local Ollama endpoint instead

{% hint style="danger" %}
**Set a spending limit immediately after generating your key.** All three commercial providers let you cap monthly spend on the account or key. Do this BEFORE pasting the key into the config. If you don't, a misconfiguration could cost you hundreds of dollars before you notice.
{% endhint %}

### Step 3: Configure the Module

Open `plugins/HalosPlayerSpoofer/ai-chat.yml` and edit the top section:

```yaml
enabled: true

llm-provider:
  provider-type: GEMINI       # OPEN_AI | OLLAMA | ANTHROPIC | GEMINI
  api-key: YOUR_KEY_HERE
  model-name: gemini-2.5-flash
  base-url: none              # only used for OLLAMA
```

#### Valid model names per provider

{% hint style="danger" %}
**Model names must be your provider's exact API identifier.** Using marketing names like "GPT-4" or "Gemini 2.5 Flash" (with spaces and capitals) will fail with an `Illegal character in path` error. Use the exact lowercase, hyphen-separated identifier below.
{% endhint %}

**OpenAI:**

* `gpt-4.1-mini` — recommended for cost/quality balance
* `gpt-4.1`
* `gpt-4o`
* `gpt-4o-mini`

**Gemini:**

* `gemini-2.5-flash` — recommended (free tier eligible)
* `gemini-2.0-flash`
* `gemini-1.5-flash`
* `gemini-1.5-pro`

**Anthropic:**

* `claude-haiku-4-5-20251001`
* `claude-sonnet-4-6`
* `claude-opus-4-6`

**Ollama:**

* Whatever model name you have installed locally (e.g. `llama3.2`, `mistral`)
* Set `base-url` to your Ollama endpoint, e.g. `http://localhost:11434`

### Step 4: Set the Activity Level

These three settings control how often AI chat fires — which directly controls your LLM costs:

```yaml
chatter-chance: 0.75      # 75% of new fake players become chatters
max-chatters: 10          # cap on simultaneous chatting fakes
min-real-players: 1       # don't run AI chat until N real players are online
```

| Setting                   | Effect on cost             | Recommended starting value      |
| ------------------------- | -------------------------- | ------------------------------- |
| Higher `chatter-chance`   | More fakes will chat       | Start at `0.5`                  |
| Higher `max-chatters`     | More LLM calls in parallel | Start at `5`, raise once stable |
| Higher `min-real-players` | Less time chat is active   | `1-3` for cost control          |

{% hint style="info" %}
**Cost-control tip:** Set `min-real-players: 3` or higher to prevent AI chat from running on an empty server. There's no point spending API tokens when no real players are watching.
{% endhint %}

### Step 5: Test It

1. Save the config
2. In-game, run `/halos reload` or restart the server
3. Have at least `min-real-players` real players online
4. Wait for fake players to spawn (depends on your Fluctuation settings)
5. Watch chat — you should see fakes talking within a minute or two

If nothing shows up after \~3 minutes, jump to Troubleshooting.

### Personalities

Halos ships with 6 built-in personalities. Each fake player that becomes a chatter is randomly assigned one:

| Personality | Vibe                                                 |
| ----------- | ---------------------------------------------------- |
| **Eli**     | Dry humor, slightly grumpy, gives practical tips     |
| **Casey**   | Friendly, witty, asks occasional follow-up questions |
| **Nia**     | Warm, mentions her pets casually                     |
| **Milo**    | Lowercase only, chill, sleepy vibe                   |
| **Bex**     | Enthusiastic builder, lots of punctuation!!!         |
| **Toby**    | Friendly, occasional small typos                     |

You can edit any of them — or add new ones — under `prompt-config.personalities` in `ai-chat.yml`. Each personality has two prompts:

* `decision-prompt-template` — used when the agent is deciding whether to respond to a player's message
* `idle-prompt-template` — used when the agent decides to start a random chat during a quiet period

#### Adding a Custom Personality

Copy an existing personality block and rename the key. Example — adding a new personality called `kira`:

```yaml
prompt-config:
  personalities:
    kira:
      decision-prompt-template: |
        You are chatting in a public Minecraft server as '{agentName}'.
        Persona: Kira — competitive PvPer, brags about kills, friendly rivalry.
        Style rules:
        - short, confident replies.
        - occasional trash-talk in a friendly way.
        Behavior rules:
        - Avoid echo-chamber behavior: do NOT mindlessly agree, mirror, or repeat.
        - If message mentions your name, respond with high likelihood.
        - Output MUST be strict JSON only:
          {"respond":true|false,"recipient":"<optional username>","message":"<chat message if respond>"}
        - If respond=false, message must be "".
        - recipient should usually be the sender '{fromUser}' if replying.
      idle-prompt-template: |
        You are chatting in a public Minecraft server as '{agentName}'.
        Persona: Kira — competitive PvPer.
        We are in a lull. Write one short PvP-related chat line.
        Output MUST be strict JSON only:
          {"respond":true,"recipient":"","message":"..."}
```

{% hint style="info" %}
**Prompt rules:** Both templates MUST end with the JSON output instruction. Halos parses the agent's response as strict JSON — free-form text will fail.
{% endhint %}

### Cost Management

This is the most-asked-about topic. Here's what actually drives your bill:

**Bigger cost drivers:**

* High `chatter-chance` (more fakes are chatting)
* High `max-chatters` (more parallel API calls)
* High `max-context-events` (more tokens per call)
* Low `min-real-players` (chat running with no audience)
* Low `quiet-period-for-idle-ms` (more idle chats happening)

**Smaller cost drivers (worth tuning second):**

* Cheaper model (`gpt-4o-mini`, `gemini-2.5-flash`, `claude-haiku-4-5`)
* Higher cooldown settings (less frequent messages)
* Lower `p-idle-chatter` (less random chatting when no players)

#### Sample monthly cost estimates

| Profile         | Setup                                 | Estimated monthly cost |
| --------------- | ------------------------------------- | ---------------------- |
| Hobby server    | 5 fakes, `gpt-4o-mini`, 8h/day active | \~$3-8/mo              |
| Mid-size server | 10 fakes, `gpt-4o-mini`, 24/7         | \~$15-30/mo            |
| Large network   | 25+ fakes, `gpt-4.1`, 24/7            | $50+/mo                |

These are rough estimates. **Always set a hard spending limit with your provider before enabling.**

### Advanced Tuning

The `agent-config` section is for fine-tuning behavior. Defaults work for most servers. Touch these only if you have a specific reason.

#### Cooldowns & Timing

| Setting                     | What it does                                                        | Default          |
| --------------------------- | ------------------------------------------------------------------- | ---------------- |
| `engagement-ttl-ms`         | How long an agent stays engaged with a player after being mentioned | `180000` (3 min) |
| `global-speak-cooldown-ms`  | Cooldown between chats by any agent                                 | `3000`           |
| `per-recipient-cooldown-ms` | Per-agent and per-engagement cooldown between chats                 | `3000`           |
| `quiet-period-for-idle-ms`  | Quiet time before an agent might initiate idle chat                 | `18000` (18s)    |
| `min-idle-speak-gap-ms`     | Minimum delay between random idle messages                          | `35000` (35s)    |
| `min-response-delay-ms`     | Minimum delay before agent responds to a player                     | `5000` (5s)      |
| `max-response-delay-ms`     | Maximum delay before agent responds                                 | `10000` (10s)    |
| `tick-interval-ms`          | How often agents are evaluated                                      | `5000`           |
| `echo-suppress-window-ms`   | Window to ignore duplicate chat messages                            | `25000`          |

#### Response Probabilities

| Setting                    | What it does                                             | Default |
| -------------------------- | -------------------------------------------------------- | ------- |
| `p-reply-when-mentioned`   | Probability of replying when mentioned by name           | `0.85`  |
| `p-reply-when-engaged`     | Probability of replying when in active engagement        | `0.65`  |
| `p-reply-random-when-idle` | Probability of replying to a random chat when idle       | `0.08`  |
| `p-idle-chatter`           | Probability an idle agent submits a random chat per tick | `0.05`  |

#### Multi-Agent Coordination

| Setting                         | What it does                                                      | Default |
| ------------------------------- | ----------------------------------------------------------------- | ------- |
| `p-ignore-other-agents-base`    | Probability of ignoring another agent's chat when idle            | `0.75`  |
| `p-ignore-other-agents-if-busy` | Probability of ignoring other agents when engaged with a player   | `0.85`  |
| `p-bypass-ignore-if-mentioned`  | Multiplier reducing ignore probability if mentioned               | `0.35`  |
| `global-throttle-multiplier`    | Multiplier reducing reply probability when many agents are active | `0.35`  |

#### Focus System

| Setting                           | What it does                                                           | Default       |
| --------------------------------- | ---------------------------------------------------------------------- | ------------- |
| `focus-ttl-ms`                    | How long an agent focuses on a specific player                         | `90000` (90s) |
| `focus-boost-multiplier`          | Reply probability multiplier when sender is the focused player         | `5.0`         |
| `focus-suppress-multiplier`       | Reply probability multiplier from others when agent has a focused user | `0.4`         |
| `focus-mention-bypass-multiplier` | Reduction in focus suppression if agent is mentioned                   | `0.65`        |

#### Context

| Setting              | What it does                                          | Default |
| -------------------- | ----------------------------------------------------- | ------- |
| `max-history`        | Max history events kept internally per agent          | `200`   |
| `max-context-events` | Max events sent to the LLM per call (lower = cheaper) | `60`    |
| `debug-logging`      | Enable verbose decision logging — useful for tuning   | `false` |

### Troubleshooting

#### "Illegal character in path at index N"

The `model-name` in your config has invalid characters (usually spaces). Provider model names must be exact API identifiers, not marketing names.

* ❌ Wrong: `model-name: Gemini 2.5 Flash`
* ✅ Right: `model-name: gemini-2.5-flash`

See Step 3 for the full list of valid names per provider.

#### Chat isn't appearing in-game

Check in this order:

1. Is `enabled: true` in `ai-chat.yml`?
2. Are there at least `min-real-players` real players online?
3. Are fake players actually spawning? (Check the Fluctuation module is working first)
4. Is your API key valid? Test it directly with your provider.
5. Check `latest.log` for errors — search for `LLMAgent` or `RetryUtils`.
6. Set `debug-logging: true` under `agent-config` to see what each agent is deciding.

#### "401 Unauthorized" or "Invalid API key"

Your API key is wrong, expired, or revoked. Generate a new one with your provider and paste it into `api-key`.

#### "429 Too Many Requests" / Rate limit errors

You're hitting your provider's rate limits. Either:

* Lower `max-chatters` so fewer parallel calls happen
* Raise the cooldown settings (`global-speak-cooldown-ms`, `min-idle-speak-gap-ms`)
* Upgrade your provider plan to a higher rate limit tier

#### Bill is higher than expected

1. Lower `max-chatters`
2. Lower `chatter-chance`
3. Raise `min-real-players`
4. Switch to a cheaper model (`gpt-4o-mini` or `gemini-2.5-flash`)
5. Set a hard spending limit on your provider account
6. Reduce `max-context-events` to send less context per call

#### Fakes are repeating themselves or echoing real players

* Raise `echo-suppress-window-ms` (default 25000)
* Review your personality prompts — make sure "Avoid echo-chamber behavior" rule is present
* Lower `p-reply-when-engaged` so agents don't pile onto every message

#### Fakes are too chatty / spamming

* Lower `chatter-chance`
* Lower `p-idle-chatter` and `p-reply-random-when-idle`
* Raise `quiet-period-for-idle-ms` and `min-idle-speak-gap-ms`

#### Fakes are too quiet / never chat

* Raise `chatter-chance`
* Raise `p-reply-when-mentioned` and `p-reply-when-engaged`
* Lower `quiet-period-for-idle-ms`
* Confirm fakes are actually being spawned by Fluctuation

### FAQ

**Q: Will real players know they're talking to AI?**\
A: They shouldn't if your prompts are configured well. The default prompts explicitly tell agents not to behave like assistants. Test with friends before going live.

**Q: Can I use multiple LLM providers at once?**\
A: Not currently — one provider per server.

**Q: What about NSFW or rule-breaking content?**\
A: Your LLM provider handles content filtering. OpenAI and Anthropic block most disallowed content by default. Gemini is configurable. Your prompts also influence what gets generated.

**Q: My fakes are speaking in non-English languages.**\
A: Add an explicit language rule to the `global-system-prompt`, e.g. "Always respond in English."

**Q: Can fakes mention other fakes by name?**\
A: Yes — they're aware of other agents and can reference them. Tune `p-ignore-other-agents-base` to control how often this happens.

**Q: Does AI chat work on Folia?**\
A: Yes. All AI chat operations are async and Folia-compatible.

### Support

Stuck? Open a ticket in our Discord: [discord.gg/halosdev](https://discord.gg/halosdev)

Average response time: same day to 24 hours. We read every ticket.
