How the File-Picker Agent in Codebuff Identifies and Selects Relevant Files
The file-picker agent in Codebuff delegates file discovery to a specialized File-Lister sub-agent, parses the returned paths, deduplicates them using a Set, and then reads the actual file contents using the read_files tool.
The file-picker agent in Codebuff serves as an intelligent entry point for locating relevant code within a repository. Unlike traditional file search tools that rely solely on pattern matching, this agent leverages a sub-agent architecture to understand semantic context and return the most pertinent files. According to the Codebuff source code, the implementation resides primarily in agents/file-explorer/file-picker.ts and orchestrates a multi-step discovery pipeline.
Architecture Overview of the File-Picker Agent
The File-Picker operates as a secret agent that does not read code directly. Instead, it implements a discover-then-read pattern by spawning specialized sub-agents in parallel. The agent uses the generic spawn_agents tool to invoke either file-lister (default mode) or file-lister-max (max mode), depending on the configuration. This architecture separates the concerns of file discovery from file reading, allowing each sub-agent to optimize for its specific task.
Step-by-Step File Selection Process
1. Agent Initialization via createFilePicker
The process begins in agents/file-explorer/file-picker.ts with the createFilePicker function. This factory function builds a secret-agent definition that configures the Gemini model and defines the input schema (prompt plus optional directories). Crucially, it declares which sub-agents can be spawned:
- Default mode: Spawns
file-lister(returns up to 12 files) - Max mode: Spawns
file-lister-max(returns up to 20 files)
export const createFilePicker = (mode: 'default' | 'max'): Omit<SecretAgentDefinition, 'id'> => {
const isMax = mode === 'max';
// ...
spawnableAgents: isMax ? ['file-lister-max'] : ['file-lister'],
// ...
};
2. Spawning the File-Lister Sub-Agent
When the File-Picker executes, it yields control to either handleStepsDefault or handleStepsMax. These generator functions yield a spawn_agents call that instructs the runtime to execute the File-Lister sub-agent. The payload includes the original user prompt and any parameters such as target directories.
According to lines 71-80 of file-picker.ts, the spawn call looks like this:
const handleStepsDefault: SecretAgentDefinition['handleSteps'] = function* ({
prompt,
params,
}) {
const { toolResult: fileListerResults } = yield {
toolName: 'spawn_agents',
input: {
agents: [{ agent_type: 'file-lister', prompt, params }],
},
};
// ...
};
3. Directory Tree Analysis by the Sub-Agent
The spawned File-Lister (defined in agents/file-explorer/file-lister.ts) performs the actual discovery. It calls the read_subtree tool to obtain the directory structure, analyzes it against the provided prompt, and returns a list of relevant file paths—one per line. The default variant returns up to 12 paths, while the max variant in file-lister-max.ts returns up to 20.
4. Parsing and Deduplicating Results
Once the sub-agent completes, the File-Picker processes the results using extractSpawnResults and extractLastMessageText. These functions parse the sub-agent’s JSON output, locate the final assistant message, and extract the text containing file paths.
As implemented in lines 84-102 and 108-120 of file-picker.ts, the agent splits the text on newlines and stores paths in a Set<string> to eliminate duplicates:
function extractLastMessageText(agentOutput: any): string | null {
if (agentOutput?.type === 'lastMessage' && Array.isArray(agentOutput.value)) {
for (let i = agentOutput.value.length - 1; i >= 0; i--) {
const msg = agentOutput.value[i];
if (msg.role === 'assistant' && Array.isArray(msg.content)) {
for (const part of msg.content) {
if (part.type === 'text') return part.text;
}
}
}
}
return null;
}
5. Reading File Contents
With the deduplicated list of paths, the File-Picker yields the read_files tool to fetch the actual content. After the files are read, it yields a STEP marker to signal completion of the workflow.
yield {
toolName: 'read_files',
input: { paths: Array.from(allPaths) },
};
Key Implementation Details
The secret agent pattern distinguishes the File-Picker from standard tools. Rather than accessing the filesystem directly, it orchestrates other agents through the spawn_agents tool defined in common/src/tools/params/tool/spawn-agents.ts. This tool validates that the requested agent_type refers to a real agent rather than a tool, and normalizes the payload so sub-agents receive prompt and params as top-level fields.
The runtime transformation logic in sdk/src/impl/llm.ts handles the conversion of direct agent calls into spawn_agents invocations when necessary, ensuring the File-Picker can operate seamlessly within the broader Codebuff ecosystem.
Practical Usage Example
To leverage the file-picker agent in Codebuff, invoke it with a descriptive prompt and optional directory constraints:
// Client invocation to find authentication-related files
await runAgent({
agent_type: 'file-picker',
prompt: 'Find all files that handle authentication',
params: { directories: ['src/auth', 'src/user'] }, // Optional narrowing
});
The runtime translates this into a spawn_agents request for the underlying file-lister, manages the parsing and deduplication logic, and returns the full source content of the identified files—eliminating the need for manual file management.
Summary
- The file-picker agent in Codebuff operates as a secret agent that orchestrates file discovery rather than performing it directly.
- It spawns either
file-lister(12 files) orfile-lister-max(20 files) sub-agents using thespawn_agentstool defined incommon/src/tools/params/tool/spawn-agents.ts. - The sub-agent analyzes directory trees via
read_subtreeand returns relevant paths, which the File-Picker deduplicates using aSet<string>. - Finally, the agent fetches actual file contents via the
read_filestool, completing the discover-then-read workflow.
Frequently Asked Questions
What is the difference between the default and max modes in the file-picker agent?
The default mode spawns a file-lister sub-agent that returns up to 12 relevant files, while the max mode spawns file-lister-max to return up to 20 files. The createFilePicker function in agents/file-explorer/file-picker.ts configures the appropriate spawnable agent based on the mode parameter, allowing users to balance between precision and comprehensiveness.
How does the file-picker agent handle duplicate file paths?
After parsing the sub-agent's output using extractLastMessageText and extractSpawnResults, the File-Picker splits the returned text on newlines and stores each path in a Set<string>. This data structure automatically eliminates duplicates. The deduplication logic appears in lines 108-120 of agents/file-explorer/file-picker.ts, ensuring that the final read_files call only fetches unique content.
Why does the file-picker agent use a sub-agent instead of reading files directly?
The File-Picker implements a secret agent pattern that separates discovery from retrieval. By spawning a specialized File-Lister sub-agent, the system leverages distinct optimization strategies for each phase: the sub-agent focuses on semantic relevance and directory tree analysis via read_subtree, while the File-Picker handles orchestration, deduplication, and content retrieval. This architecture, defined in agents/file-explorer/file-picker.ts, promotes modularity and allows independent scaling of discovery logic.
What tools does the file-picker agent use to complete its task?
The agent relies on three primary tools: spawn_agents (defined in common/src/tools/params/tool/spawn-agents.ts) to invoke File-Lister sub-agents, read_subtree (used by the sub-agent to scan directories), and read_files (to fetch final content). The spawn_agents tool validates agent types and normalizes payloads, while the File-Picker's internal functions like extractLastMessageText handle the parsing of sub-agent responses.
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 →