Skip to content

DEPRECATION NOTICE

This implementation plan has been completed. The checkboxes below were not updated during implementation and do not reflect current status. Please refer to the actual codebase for the current implementation state. Key implemented features include:

  • DialogueComponent (packages/maid-stdlib/src/maid_stdlib/components/dialogue.py)
  • ConversationManager (packages/maid-engine/src/maid_engine/ai/conversation.py)
  • PromptBuilder (packages/maid-engine/src/maid_engine/ai/prompts.py)
  • RateLimiter (packages/maid-engine/src/maid_engine/ai/rate_limiter.py)
  • NPCDialogueSystem (packages/maid-classic-rpg/src/maid_classic_rpg/systems/npc/dialogue.py)
  • Dialogue Commands (packages/maid-classic-rpg/src/maid_classic_rpg/commands/)

AI Integration Completion - Implementation Plan

Summary

This plan implements MAID's AI-powered NPC dialogue system, transforming the existing AI framework (providers, context builders, streaming) into a functional end-to-end dialogue system. The goal is feature parity with Evennia's LLMNPC while leveraging MAID's superior infrastructure (multi-provider support, streaming, ECS architecture).

Key Deliverables: - Working talk <npc> <message> command with AI-generated responses - Context-aware NPC conversations (world state, location, player info) - Conversation memory within sessions - Multi-provider support (Anthropic, OpenAI, Ollama) - Rate limiting and safety guardrails


Tasks

Phase 1: Core Infrastructure

1.1 DialogueComponent (maid-stdlib)

File: packages/maid-stdlib/src/maid_stdlib/components/dialogue.py

  • [x] Create DialogueComponent class extending Component
  • [x] AI config fields: ai_enabled, provider_name, model_name
  • [x] Personality fields: personality, speaking_style, knowledge_domains, secret_knowledge
  • [x] Role fields: npc_role, faction
  • [x] Behavioral constraints: will_discuss, wont_discuss
  • [x] Response settings: max_response_tokens, temperature
  • [x] Fallback dialogue: greeting, farewell, fallback_response
  • [x] Rate limiting: cooldown_seconds, last_response_time
  • [x] Add Pydantic validation rules (token range 50-500, temperature 0.0-1.0)
  • [x] Write unit tests for component (test_dialogue_component.py)
  • [x] Export from maid_stdlib/components/__init__.py

1.2 ConversationManager (maid-engine)

File: packages/maid-engine/src/maid_engine/ai/conversation.py

  • [x] Create ConversationMessage dataclass
  • [x] Fields: role, content, timestamp, metadata
  • [x] Create Conversation dataclass
  • [x] Fields: player_id, npc_id, messages, started_at, last_activity, context_data
  • [x] Method: add_message(role, content)
  • [x] Method: get_recent_messages(count=10)
  • [x] Method: to_conversation_context(...)
  • [x] Method: is_stale(timeout_minutes=30)
  • [x] Create ConversationManager class
  • [x] Method: get_or_create(player_id, npc_id)
  • [x] Method: get(player_id, npc_id)
  • [x] Method: end_conversation(player_id, npc_id)
  • [x] Method: cleanup_stale()
  • [x] Method: get_player_conversations(player_id)
  • [x] Write unit tests (test_conversation_manager.py)
  • Depends on: None

1.3 PromptBuilder (maid-engine)

File: packages/maid-engine/src/maid_engine/ai/prompts.py

  • [x] Create NPCPromptConfig dataclass
  • [x] Context toggles: include_world_context, include_location_context, include_player_context
  • [x] Safety flags: enforce_character, block_meta_discussion, block_harmful_content
  • [x] Limit: max_context_tokens, allowed_actions
  • [x] Create PromptBuilder class
  • [x] Define SYSTEM_TEMPLATE with personality, role, guidelines, restrictions
  • [x] Define WORLD_CONTEXT_TEMPLATE (time, weather, events)
  • [x] Define LOCATION_CONTEXT_TEMPLATE (room, exits, characters)
  • [x] Define PLAYER_CONTEXT_TEMPLATE (name, level, race, class, reputation)
  • [x] Method: build_system_prompt(...) - assembles full system prompt
  • [x] Method: build_messages(...) - builds message list for API call
  • [x] Method: build_for_npc(...) - convenience wrapper using DialogueComponent
  • [x] Add hardcoded safety guardrails in system prompt
  • [x] Write unit tests (test_prompt_builder.py)
  • Depends on: 1.2 ConversationManager (for ConversationContext integration)

Phase 2: System Integration

2.1 NPCDialogueSystem (maid-classic-rpg)

File: packages/maid-classic-rpg/src/maid_classic_rpg/systems/npc/dialogue.py

  • [x] Create NPCDialogueSystem class extending System
  • [x] Set priority = 50
  • [x] Initialize ConversationManager in constructor
  • [x] Initialize PromptBuilder in constructor
  • [x] Implement lifecycle methods
  • [x] startup() - subscribe to events if needed
  • [x] shutdown() - cancel pending responses, cleanup
  • [x] update(delta) - periodic cleanup of stale conversations
  • [x] Implement process_dialogue(player_entity, npc_entity, message, session)
  • [x] Get DialogueComponent from NPC entity
  • [x] Check if AI is enabled, return fallback if not
  • [x] Check cooldown, return waiting message if on cooldown
  • [x] Get/create conversation via ConversationManager
  • [x] Build all contexts (World, Location, Entity, Conversation)
  • [x] Build messages via PromptBuilder
  • [x] Get LLM provider from registry (support per-NPC override)
  • [x] Stream response to player session
  • [x] Record messages in conversation history
  • [x] Update cooldown timestamp
  • [x] Handle errors with fallback response
  • [x] Implement find_npc_in_room(room_id, keyword) for NPC lookup
  • [x] Implement helper methods: _get_dialogue_component(), _get_entity_name(), _build_location_context(), _check_cooldown()
  • [x] Write unit tests with MockProvider (test_npc_dialogue_system.py)
  • Depends on: 1.1 DialogueComponent, 1.2 ConversationManager, 1.3 PromptBuilder

2.2 Register System in ContentPack

File: packages/maid-classic-rpg/src/maid_classic_rpg/pack.py

  • [x] Import NPCDialogueSystem
  • [x] Add to get_systems() method in ClassicRPGContentPack
  • [x] Verify initialization order (must come after component registration)
  • Depends on: 2.1 NPCDialogueSystem

Phase 3: Command Implementation

3.1 Talk Command

File: packages/maid-classic-rpg/src/maid_classic_rpg/commands/handlers/dialogue.py (new file)

  • [x] Create dialogue.py command handler file
  • [x] Implement cmd_talk command
  • [x] Parse target NPC keyword and message from input
  • [x] Handle missing target: "Talk to whom?"
  • [x] Handle missing message: "What do you want to say?"
  • [x] Get character's current room
  • [x] Get player entity from world
  • [x] Get NPCDialogueSystem from world systems
  • [x] Find NPC in room by keyword
  • [x] Handle NPC not found: "You don't see '{keyword}' here to talk to."
  • [x] Call dialogue_system.process_dialogue()
  • [x] Register command with category SOCIAL, aliases ["tell"]
  • [x] Write integration tests
  • Depends on: 2.1 NPCDialogueSystem

3.2 Ask Command

File: packages/maid-classic-rpg/src/maid_classic_rpg/commands/handlers/dialogue.py

  • [x] Implement cmd_ask command
  • [x] Parse "npc about topic" format
  • [x] Validate " about " separator exists
  • [x] Reformat topic as question: "What can you tell me about {topic}?"
  • [x] Delegate to cmd_talk logic
  • [x] Register command with category SOCIAL
  • [x] Write tests
  • Depends on: 3.1 Talk Command

3.3 Conversation Management Commands

File: packages/maid-classic-rpg/src/maid_classic_rpg/commands/handlers/dialogue.py

  • [x] Implement cmd_conversations command
  • [x] Get player's active conversations from ConversationManager
  • [x] Display NPC names and message counts
  • [x] Handle empty list: "You have no active conversations."
  • [x] Implement cmd_endconversation command
  • [x] Parse target NPC keyword
  • [x] Find NPC in room
  • [x] End conversation via ConversationManager
  • [x] Display NPC's farewell message
  • [x] Register commands with appropriate categories
  • [x] Write tests
  • Depends on: 3.1 Talk Command

3.4 Register Commands in ContentPack

File: packages/maid-classic-rpg/src/maid_classic_rpg/pack.py

  • [x] Import dialogue command handlers
  • [x] Add to register_commands() method
  • Depends on: 3.1, 3.2, 3.3

Phase 4: Configuration & Safety

4.1 AIDialogueSettings

File: packages/maid-engine/src/maid_engine/config/settings.py

  • [x] Create AIDialogueSettings class extending BaseSettings
  • [x] enabled: bool = True
  • [x] default_provider: str = "anthropic"
  • [x] default_model: str | None = None
  • [x] default_max_tokens: int = 150
  • [x] default_temperature: float = 0.7
  • [x] global_rate_limit_rpm: int = 60
  • [x] per_player_rate_limit_rpm: int = 10
  • [x] per_npc_cooldown_seconds: float = 2.0
  • [x] daily_token_budget: int | None = None
  • [x] per_player_daily_budget: int | None = 5000
  • [x] include_world_context: bool = True
  • [x] include_location_context: bool = True
  • [x] include_player_context: bool = True
  • [x] max_conversation_history: int = 10
  • [x] conversation_timeout_minutes: int = 30
  • [x] content_filtering: bool = True
  • [x] log_conversations: bool = False
  • [x] Set env_prefix = "MAID_AI_DIALOGUE_"
  • [x] Add to main Settings class
  • [x] Write validation tests
  • Depends on: None

4.2 RateLimiter

File: packages/maid-engine/src/maid_engine/ai/rate_limiter.py (new file)

  • [x] Create RateLimitState dataclass
  • [x] request_times: list[float]
  • [x] tokens_used_today: int = 0
  • [x] day_start: float = 0.0
  • [x] Create RateLimiter class
  • [x] Constructor params: global_rpm, per_player_rpm, daily_token_budget, per_player_daily_budget
  • [x] Method: check_rate_limit(player_id)tuple[bool, str]
    • [x] Check global RPM limit
    • [x] Check per-player RPM limit
    • [x] Check global daily token budget
    • [x] Check per-player daily token budget
    • [x] Return appropriate rejection messages
  • [x] Method: record_request(player_id, tokens_used)
  • [x] Write unit tests (test_rate_limiter.py)
  • Depends on: None

4.3 Integrate Rate Limiting into NPCDialogueSystem

File: packages/maid-classic-rpg/src/maid_classic_rpg/systems/npc/dialogue.py

  • [x] Import RateLimiter
  • [x] Initialize RateLimiter from AIDialogueSettings in constructor
  • [x] Add rate limit check before processing dialogue
  • [x] Record request after successful response
  • [x] Handle rate limit rejection with user-friendly message
  • Depends on: 4.1 AIDialogueSettings, 4.2 RateLimiter

4.4 Content Filtering (Optional Enhancement)

File: packages/maid-engine/src/maid_engine/ai/safety.py (new file)

  • [x] Create ContentFilter class (optional/future)
  • [x] Method: check_input(message) - validate player input
  • [x] Method: check_output(response) - validate AI response
  • [x] Integrate into NPCDialogueSystem if enabled in settings
  • Depends on: 4.1 AIDialogueSettings

Phase 5: Testing & Polish

5.1 Create Test NPCs

Directory: packages/maid-classic-rpg/data/npcs/ or test fixtures

  • [x] Create bartender NPC configuration
  • [x] Personality: gruff but kind-hearted
  • [x] Knowledge: local gossip, drinks, travelers' tales
  • [x] Create town guard NPC configuration
  • [x] Personality: dutiful, formal
  • [x] Knowledge: town laws, local crimes
  • [x] Restrictions: won't discuss bribes
  • [x] Create mysterious merchant NPC configuration
  • [x] Personality: flowery, hints at secrets
  • [x] Knowledge: rare items, distant lands
  • [x] Higher temperature (0.9) for variety
  • [x] Document NPC configuration format in examples
  • Depends on: 1.1 DialogueComponent

5.2 End-to-End Tests

File: packages/maid-classic-rpg/tests/test_dialogue_e2e.py

  • [x] Test talk bartender hello full flow with MockProvider
  • [x] Test ask guard about trouble reformatting
  • [x] Test multiple exchanges maintain conversation context
  • [x] Test conversation timeout resets history
  • [x] Test different NPC personalities respond differently
  • [x] Test rate limiting prevents rapid requests
  • [x] Test fallback when AI provider unavailable
  • [x] Test streaming response format (quotes, NPC name)
  • Depends on: 3.1 Talk Command, 5.1 Test NPCs

5.3 Manual Provider Testing

  • [x] Test with Anthropic provider (Claude)
  • [x] Test with OpenAI provider (GPT-4)
  • [x] Test with Ollama provider (local models)
  • [x] Verify streaming works correctly for each
  • [x] Document any provider-specific quirks
  • Depends on: 5.2 E2E Tests

5.4 Documentation

  • [x] Update main README with AI dialogue feature
  • [x] Create NPC creation guide (docs/guides/npc_dialogue.md)
  • [x] DialogueComponent field explanations
  • [x] Personality design tips
  • [x] Example configurations
  • [x] Document configuration options in settings guide
  • [x] Add prompt engineering tips for NPC personalities
  • [x] Update CLAUDE.md if needed
  • Depends on: 5.3 Manual Testing

File Location Summary

Component Package Path
DialogueComponent maid-stdlib src/maid_stdlib/components/dialogue.py
ConversationManager maid-engine src/maid_engine/ai/conversation.py
PromptBuilder maid-engine src/maid_engine/ai/prompts.py
RateLimiter maid-engine src/maid_engine/ai/rate_limiter.py
AIDialogueSettings maid-engine src/maid_engine/config/settings.py
NPCDialogueSystem maid-classic-rpg src/maid_classic_rpg/systems/npc/dialogue.py
Talk/Ask Commands maid-classic-rpg src/maid_classic_rpg/commands/handlers/dialogue.py

Acceptance Criteria

Must Have (MVP)

  • [x] talk bartender hello produces AI-generated response
  • [x] Response displays as: {NPC Name} says, "{response}"
  • [x] Response streams incrementally to player
  • [x] Conversation history maintained within session
  • [x] Works with all three providers (Anthropic, OpenAI, Ollama)
  • [x] Rate limiting prevents abuse
  • [x] Fallback response when AI unavailable
  • [x] NPCs stay in character (no meta-discussion)

Should Have

  • [x] ask npc about topic command
  • [x] conversations command to list active chats
  • [x] endconversation command to end a chat
  • [x] Per-NPC provider/model override
  • [x] Configurable conversation timeout

Nice to Have (Post-MVP)

  • [ ] Emotion/mood system affecting responses
  • [ ] Memory persistence across sessions
  • [ ] Action triggers from dialogue (quest starts, item gives)
  • [ ] NPC-to-NPC background conversations