Algorithms Used in moeru-ai/airi: A Technical Deep Dive into the Minecraft Bot's Cognitive Architecture
The moeru-ai/airi repository implements deterministic algorithms including A pathfinding with ETA-based timeouts, dependency-tree recipe planning, and token-budget error guards to ensure real-time Minecraft bot responsiveness independent of LLM latency.*
The algorithms used in moeru-ai/airi power "Airī," a conscious Minecraft agent architecture that separates real-time game mechanics from LLM-driven reasoning. By combining classical pathfinding, heuristic planning, and deterministic state management, the system guarantees predictable performance even when language model inference introduces variable delays.
A* Pathfinding with Dynamic ETA Timeouts
The navigation system in services/minecraft/src/skills/patched-goto.ts extends standard A* pathfinding with real-world travel estimation and stagnation detection to prevent the bot from hanging on impossible paths.
ETA-Based Timeout Calculation
Rather than using static timeouts, the algorithm computes expected travel time based on path length and movement speed. The computeTimeoutFromEta function generates dynamic timeouts that scale with distance, preventing premature cancellation on long journeys while ensuring stuck bots don't wait indefinitely.
Stagnation Detection Algorithm
The hasMeaningfulPathfindingProgress function implements a movement-threshold check to detect when the bot is stuck:
- Movement threshold: ≥ 1.5 blocks moved since last check (
STAGNATION_THRESHOLD) - Distance improvement: ≥ 0.75 blocks closer to target (
DISTANCE_IMPROVEMENT_THRESHOLD) - Activity exceptions: Mining or building operations bypass stagnation checks
A fixed-interval ticker (every 5 seconds) drives these checks via setInterval, ensuring consistent monitoring without blocking the main thread.
import { Bot } from 'mineflayer';
import { GoalBlock } from 'mineflayer-pathfinder';
import { patchedGoto } from '@/services/minecraft/src/skills/patched-goto';
// `bot` is a live Mineflayer instance.
const goal = new GoalBlock(100, 64, 200); // target coordinates
patchedGoto(bot, goal, {
// Optional progress callback – useful for UI or debugging
onProgress: (info) => console.log('Progress:', info),
}).then((result) => {
console.log('Path result:', result);
});
Dependency-Tree Recipe Planning
The crafting system in services/minecraft/src/utils/recipe-planner.ts uses graph algorithms to solve complex multi-step crafting requirements without LLM intervention.
Tree Construction
The buildDependencyTree function constructs a directed graph where:
- Nodes represent items or crafting steps
- Edges represent ingredient requirements
- Leaves are base materials already in inventory
Heuristic Recipe Selection
When multiple recipes exist for an item, the selectBestRecipe algorithm maximizes ingredient overlap with current inventory. This heuristic minimizes additional gathering steps by preferring recipes that use materials the bot already possesses.
The planner marks each step with statuses including craftable, requires_smelting, or requires_gathering, enabling the brain to prioritize actions based on feasibility.
import { Bot } from 'mineflayer';
import { planRecipe } from '@/services/minecraft/src/utils/recipe-planner';
// Assume `bot` is already connected.
const plan = planRecipe(bot, 'diamond_pickaxe', 1);
console.log(plan.status); // e.g. "requires_gathering"
console.log(plan.steps.map(s => s.action)); // ['craft', 'gather', ...]
Cognitive Layer Algorithms
The conscious layer in services/minecraft/src/cognitive/conscious/brain.ts manages attention, error handling, and resource budgets using deterministic algorithms that prevent runaway LLM loops.
Static Event Prioritization
Events receive fixed numeric priorities via getEventPriority:
player_chat: 0 (highest)perception: 1feedback: 2action_result: 3
This static tier system ensures critical player interactions preempt background processing without complex dynamic weight calculations.
No-Action Follow-up Budget
To prevent infinite loops of indecision, the brain implements a token-bucket-like counter (noActionFollowupBudgetRemaining). The system allows up to NO_ACTION_FOLLOWUP_BUDGET_MAX = 8 silent evaluations before forcing a response.
The budget resets on player chat events or manual intervention, ensuring the bot remains responsive to new instructions.
import { Brain } from '@/services/minecraft/src/cognitive/conscious/brain';
// Inside a Brain instance:
brain.setNoActionFollowupBudget(5); // allow up to 5 silent evaluations
// The budget automatically resets on player chat:
brain.resetNoActionFollowupBudget('player_chat');
Error-Burst Guard
The collectRecentErrorTurns function implements a sliding-window error counter to detect cascading failures. If ERROR_BURST_THRESHOLD = 3 errors occur within the last ERROR_BURST_WINDOW_TURNS = 5 turns, the guard activates and forces a giveUp action accompanied by explanatory chat.
This prevents the bot from repeatedly attempting impossible actions when the world state or LLM context has degraded.
// The Brain monitors recent turns automatically.
// To manually trigger a guard (e.g., in tests):
brain.maybeActivateErrorBurstGuard(bot, someEvent, brain.turnCounter);
Block Query DSL Heuristics
The query system in services/minecraft/src/cognitive/conscious/query-dsl.ts provides type-safe block filtering using name-based heuristics that operate without computer vision.
Ore Detection Algorithm
The isOreName function identifies ore blocks through pattern matching:
- Suffix matching: Names ending in
*_ore - Special cases: Explicit inclusion of
ancient_debris
These heuristics enable the DSL to compose complex queries like isOre().whereName(['coal_ore']) without maintaining exhaustive block lists or performing expensive image processing.
import { createQueryRuntime } from '@/services/minecraft/src/cognitive/conscious/query-dsl';
// `mineflayer` stub or real bot.
const q = createQueryRuntime(mineflayer);
// Get unique ore names within 24 blocks.
const oreNames = q.blocks()
.within(24)
.isOre()
.names()
.uniq()
.list();
console.log('Nearby ores:', oreNames);
Deterministic Context Summarization
The generateContextSummary function in services/minecraft/src/cognitive/conscious/context-summary.ts creates conversation snapshots without LLM calls.
The algorithm extracts:
- First player instruction (primary intent)
- Action tags (what the bot attempted)
- Turn count (conversation length)
This deterministic approach provides immediate context windows for the cognitive layer while conserving LLM tokens for actual decision-making.
import { generateContextSummary } from '@/services/minecraft/src/cognitive/conscious/context-summary';
const summary = generateContextSummary({
messages: recentChatMessages,
label: 'Mining Session',
llmLogEntries: llmLog,
startTurnId: 42,
endTurnId: 57,
});
console.log('Context summary:', summary);
Robustness Mechanisms
The system implements specific thresholds to ensure predictable behavior under failure conditions.
Stagnation Detection in Practice
The hasMeaningfulPathfindingProgress function uses concrete thresholds to determine if movement is occurring:
import { hasMeaningfulPathfindingProgress } from '@/services/minecraft/src/skills/patched-goto';
const snapshot = {
movedSinceLastTick: 0.7,
previousDistanceToTarget: 12.3,
distanceToTarget: 11.6,
isMining: false,
isBuilding: false,
};
if (!hasMeaningfulPathfindingProgress(snapshot)) {
console.warn('Bot appears stuck – consider re‑planning or aborting.');
}
The algorithm uses STAGNATION_THRESHOLD = 1.5 blocks and DISTANCE_IMPROVEMENT_THRESHOLD = 0.75 blocks to determine meaningful progress.
Summary
The moeru-ai/airi repository implements a hybrid architecture where deterministic algorithms handle real-time constraints while LLMs manage high-level reasoning:
- A pathfinding* with ETA-based timeouts and stagnation detection ensures reliable navigation in
patched-goto.ts - Dependency-tree planning with heuristic recipe selection optimizes multi-step crafting in
recipe-planner.ts - Token-budget systems (no-action follow-up and error-burst guards) prevent infinite loops and cascading failures in
brain.ts - Heuristic DSL for block queries and deterministic summarization provide fast cognitive preprocessing without LLM latency
These algorithms collectively guarantee that the Minecraft bot remains responsive, predictable, and robust regardless of LLM inference delays.
Frequently Asked Questions
What pathfinding algorithm does moeru-ai/airi use?
The repository uses A (A-Star)* pathfinding enhanced with ETA-based dynamic timeouts and stagnation detection. Located in services/minecraft/src/skills/patched-goto.ts, the algorithm calculates expected travel time based on path distance and movement speed, then monitors progress every 5 seconds to detect if the bot has moved fewer than 1.5 blocks or improved distance by less than 0.75 blocks.
How does the recipe planner decide which items to craft first?
The recipe planner in services/minecraft/src/utils/recipe-planner.ts builds a dependency tree of required materials, then applies a heuristic recipe selection algorithm that maximizes overlap with items already in inventory. When multiple recipes exist for the same item, it selects the one requiring the fewest additional gathering steps, marking each step with statuses like craftable, requires_smelting, or requires_gathering.
What prevents the bot from getting stuck in infinite loops?
The cognitive layer implements multiple safeguards in services/minecraft/src/cognitive/conscious/brain.ts. A no-action follow-up budget acts as a token bucket allowing up to 8 silent evaluations before forcing a response, resetting on player chat. An error-burst guard uses a sliding window to detect 3 or more errors within 5 turns, triggering a giveUp action. Additionally, static event priorities ensure player chat (priority 0) always preempts background processing.
How does the bot identify ore blocks without using computer vision?
The block query DSL in services/minecraft/src/cognitive/conscious/query-dsl.ts uses name-based heuristics via the isOreName function. It identifies ores by checking for the *_ore suffix or special cases like ancient_debris. This allows the DSL to compose queries such as isOre().whereName(['coal_ore']) without maintaining exhaustive block lists or performing expensive image processing.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →