In the previous chapters, we built the application's memory in State Management and its face in the Ink UI Framework.
But right now, our application is like a person who can remember things and smile, but can't hold a conversation. If you type a question, nothing processes it.
Enter the Query Engine. This is the logic that connects user input to the AI model, decides what to do next, and keeps the conversation going.
The Query Engine is the "Project Manager" of the application. It doesn't inherently know how to edit files or search the web. Instead, it coordinates everything.
Its job is to take your request, package it up with all the necessary context (history, permissions), send it to the AI (Claude), and then handle the AI's responseβwhether that response is a chat message or a command to run code.
Imagine you ask: "Read data.txt and tell me what it says."
Here is what the Query Engine must manage:
cat command."Without the Query Engine, the AI would just stop after step 3, waiting for someone to run the command.
Before we talk to the AI, we need to give it context. We can't just send "fix it." We need to send:
This is the most critical part. Modern AIs don't just talk; they can "call functions."
We don't want to wait 10 seconds for the whole answer. The Query Engine receives the answer in tiny chunks (tokens) so the Ink UI Framework can display typing animations in real-time.
From a code perspective, using the engine is surprisingly simple because all the complexity is hidden inside.
We usually call a main function, often named processUserMessage or submitQuery.
Here is how the UI triggers the engine when the user hits "Enter."
import { queryEngine } from './engine';
async function handleUserSubmit(userText) {
// 1. Start the engine with the user's text
const response = await queryEngine.submit({
text: userText,
mode: 'auto' // Let the AI decide what to do
});
return response;
}
Explanation: We pass the user's text into the engine. The engine takes over control until the task is done or it needs user input.
To show text appearing in real-time, we listen to events.
queryEngine.on('chunk', (token) => {
// Update the UI via State Management
updateCurrentResponse((prev) => prev + token);
});
Explanation: Every time the AI generates a word, the engine emits a 'chunk' event. We grab that word and add it to our display.
The Query Engine is essentially a while loop that keeps running until the AI says "I'm done."
Let's trace the flow when a user says "List files."
ToolCall: ls.ls in the terminal.Here is the visual flow:
The core of the engine is a recursive function (a function that calls itself).
// engine/loop.ts
async function runLoop(messages) {
// 1. Send current history to the AI
const response = await callClaudeAPI(messages);
// 2. Check if the AI wants to use a tool
if (response.hasToolCall) {
// Execute the tool (e.g., run a shell command)
const result = await executeTool(response.toolName, response.args);
// 3. Add result to history and LOOP AGAIN
const newHistory = [...messages, response, result];
return runLoop(newHistory); // <--- Recursion
}
// 4. If no tool, we are done. Return the text.
return response.text;
}
Explanation: This simplified code shows the heartbeat of claudeCode. It calls the API. If the API asks for a tool, it runs it and calls runLoop again immediately. It only stops when response.hasToolCall is false.
Before executing the tool in step 2 above, the Engine checks with the Permission System.
// Inside executeTool...
import { checkPermission } from './security';
async function executeTool(name, args) {
// Ask: Is this safe?
const isAllowed = await checkPermission(name);
if (!isAllowed) {
throw new Error("User denied permission");
}
// Run the tool...
}
Explanation: This ensures the AI doesn't delete files without your permission. We will cover this in detail in Chapter 8: Permission & Security System.
The Query Engine is the hub. It connects to almost every other chapter:
You have learned that the Query Engine is the active brain of the application. It manages the delicate dance between the user, the AI model, and the computer's tools. It uses a loop to perform complex tasks step-by-step without the user needing to type constantly.
But what happens when the Engine decides it needs to modify your code? It hands that job off to a specialist.
Generated by Code IQ