Welcome to Chapter 3!
In the previous chapter, Update Lifecycle Hooks, we learned when to update our documentation: during the "Idle State," right after the main AI finishes a task.
But now we have a logistical problem. The Main AI is sitting there, waiting for the user to reply. If we ask the Main AI to suddenly start reading and rewriting documentation, it gets "distracted." It might pollute its context window or lose track of the conversation flow.
We need a way to do this work in the background.
In this chapter, we introduce The Magic Docs Sub-Agent.
Imagine you are in a high-stakes strategy meeting with your Chief Architect (the Main AI). You are brainstorming on a whiteboard.
You don't want the Chief Architect to stop thinking about code just to tidy up the meeting notes. Instead, you bring in a Scribe.
In our system, this "Scribe" is a Sub-Agent.
Using a sub-agent solves three major problems:
Technically, creating a sub-agent involves Forking.
Imagine the conversation history is a timeline. When the Main AI goes idle, we split the timeline into two branches.
How do we code this "Scribe"? We use the runAgent function provided by the core system. Let's break down the implementation steps.
First, we define who the Scribe is. We create a configuration object that tells the system: "This agent is for Magic Docs, and it is only allowed to edit files."
function getMagicDocsAgent() {
return {
agentType: 'magic-docs',
// Only allow the "File Edit" tool. No terminal, no web search.
tools: ['file_edit_tool'],
model: 'sonnet', // Use a smart model for writing
whenToUse: 'Update Magic Docs',
}
}
Explanation: This acts as the job description. The most important part is the tools array. By limiting this to file_edit_tool, we ensure the Scribe cannot do anything dangerous.
Before we let the agent work, we need to give it a copy of the current file state. If the Main AI just wrote a file, the Sub-Agent needs to "see" that new content to document it.
import { cloneFileStateCache } from '../../utils/fileStateCache.js';
// Inside our update function...
const clonedReadFileState = cloneFileStateCache(
toolUseContext.readFileState
);
// We remove the specific doc from the cache so we force a fresh read
clonedReadFileState.delete(docInfo.path);
Explanation: cloneFileStateCache is like photocopying the papers on the desk. The Sub-Agent gets its own stack of papers to scribble on, so it doesn't mess up the Main AI's original copies.
Even though we gave the agent the "File Edit" tool, we want to be extra safe. We want to ensure it only edits the Magic Doc, not your source code.
We create a "Guard" function:
const canUseTool = async (tool, input) => {
// Only allow editing if the file path matches our Magic Doc
if (tool.name === 'file_edit_tool' && input.file_path === docInfo.path) {
return { behavior: 'allow' };
}
// Block everything else
return { behavior: 'deny', message: 'You can only edit the Magic Doc.' };
}
Explanation: This is the strict manager standing over the Scribe's shoulder. If the Scribe tries to edit server.js, the manager says "No." If the Scribe tries to edit README.md (the Magic Doc), the manager says "Go ahead."
Finally, we spin up the agent. This is where the magic happens.
import { runAgent } from '../../tools/AgentTool/runAgent.js';
// Run the sub-agent
await runAgent({
agentDefinition: getMagicDocsAgent(),
// This is the KEY: pass the Main AI's history to the Sub-Agent
forkContextMessages: mainConversationMessages,
// Apply our strict security guard
canUseTool: canUseTool,
// Tell it to run in the background (async)
isAsync: true
});
Explanation:
forkContextMessages: This passes the entire conversation memory to the Sub-Agent so it knows what just happened (e.g., "The user just added a login feature").isAsync: This allows the process to happen without freezing the user interface.In this chapter, we learned how to build The Magic Docs Sub-Agent.
canUseTool) to ensure only the documentation file is touched.Now we have a Scribe ready to work. But... what exactly do we tell the Scribe to do? We can't just say "Update the file." We need to construct a specific, intelligent prompt that combines the old file content, the user's instructions, and the recent conversation.
In the next chapter, we will learn how to generate these instructions on the fly.
Next Chapter: Dynamic Prompt Templating
Generated by Code IQ