Welcome to Chapter 3!
Now, we need the Head Chef. We need a logic controller that takes an order (input), checks if the ingredients are fresh (validation), cooks the meal (updates storage), and finally rings the bell to let the waiters know it's ready (updates the app state).
We call this the Tool Execution Logic.
Imagine holding a Universal TV Remote. You press the "Volume Up" button.
In ConfigTool, the AI is the person holding the remote. The Tool Execution Logic is the microchip inside the TV. It ensures that when the AI tries to change a setting, it doesn't break the system.
The execution logic happens inside a main function called call(). It follows a strict 4-step process:
dark vs light).Before we do any logic, we define exactly what inputs we accept using a Schema. We use a tool called Zod for this.
We accept two things:
setting: The name of the setting (e.g., "theme").value: (Optional) What to change it to. If this is missing, we assume you just want to read the current value.// Inside ConfigTool.ts
const inputSchema = z.strictObject({
// The key must be a string
setting: z.string(),
// The value can be a string, boolean, or number
// It is optional (for "Get" operations)
value: z.union([z.string(), z.boolean(), z.number()]).optional(),
})
Explanation: If the AI tries to send a list or an object as a value, Zod blocks it immediately. This protects our code from crashing.
Once the input passes the "Bouncer," we enter the main call() function. Here is the simplified logic:
async call({ setting, value }: Input, context) {
// 1. Check the Registry (Chapter 1)
if (!isSupported(setting)) {
return { error: `Unknown setting: "${setting}"` }
}
// 2. If no value is provided, it's a GET request
if (value === undefined) {
// Read from Storage (Chapter 2)
const current = getValue(config.source, path)
return { success: true, operation: 'get', value: current }
}
// 3. If value IS provided, proceed to SET logic...
}
Explanation: This is the traffic cop. It directs "Read" requests one way and "Write" requests another.
Writing data is dangerous. We need to be careful.
Sometimes the AI sends the string "true" instead of the boolean true. Our logic creates a friendly user experience by fixing this automatically.
let finalValue = value
// If the registry says this should be a boolean...
if (config.type === 'boolean' && typeof value === 'string') {
// Convert "true" string to real true
if (value.toLowerCase() === 'true') finalValue = true
if (value.toLowerCase() === 'false') finalValue = false
}
Explanation: This makes the tool "forgiving." It understands intent even if the format isn't perfect.
If a setting only allows specific words (like "dark" or "light"), we reject anything else.
// Get allowed options from Registry
const options = getOptionsForSetting(setting)
// If options exist, and our value isn't one of them...
if (options && !options.includes(String(finalValue))) {
return {
error: `Invalid value. Options are: ${options.join(', ')}`
}
}
Explanation: This prevents the AI from inventing settings, like setting the theme to "Pizza-Party."
Saving the file to the hard drive is good, but the user wants to see the change now. We use AppState to update the running application in real-time.
// 1. Save to file (Persist)
saveGlobalConfig(prev => ({ ...prev, [key]: finalValue }))
// 2. Update live AppState (Side Effect)
if (config.appStateKey) {
context.setAppState(prev => ({
...prev,
[config.appStateKey]: finalValue // Updates UI instantly
}))
}
Explanation:
.json file so it remembers the setting next time you open the app.Let's look at the complete journey of a command using a sequence diagram.
Sometimes, changing a setting requires checking the outside world. A prime example is Voice Mode.
You can't just set voiceEnabled: true if the user doesn't have a microphone! The Execution Logic handles these "Gatekeeper" checks.
// Inside call() - simplified
if (setting === 'voiceEnabled' && finalValue === true) {
// 1. Check if microphone is available
const micParams = await checkRecordingAvailability()
if (!micParams.available) {
return {
success: false,
error: 'Voice mode not available: No microphone found.'
}
}
// If checks pass, proceed to save...
}
Why this matters: The logic layer is responsible for sanity-checking the environment. It ensures the configuration matches reality.
The Tool Execution Logic is the brain of the operation.
However, for the AI to make smart decisions, it needs to know the current state of the system before it even tries to change anything. It needs context.
In the next chapter, we will learn how we feed this information to the AI automatically.
Next Chapter: Dynamic Context Injection
Generated by Code IQ