My approach to planning takes a somewhat different direction compared to other agentic platforms.
Chipper
Instead of generating a large md file describing a plan, I use what I call the chipper approach.
It works like this:
- Define a sub-goal
- Plan for the sub-goal
- Implement code for the sub-goal
- Run the Objective (e.g. compile, tests, etc)
- Summarize (a) what we’ve done so far (b) is the Objective satisfied
- If DONE exit, if not return to #1. (i.e. continue chipping at the problem)
In practice the structure of the Planner is a behavior tree that looks like this:
sequence {
action [Setup]
retry [${MAX_OUTER_ATTEMPTS}] {
sequence {
retry [${MAX_PLAN_ATTEMPTS}] {
sequence {
action [InvokePlanner]
action [IsPlanAccepted]
action [RunScratchpad]
}
}
retry [${MAX_CHIPPER_ATTEMPTS}] {
sequence {
action [InvokeChipper]
}
}
action [InvokeSummary]
}
}
}
Tools orchestration
I do not use tool calling in the traditional way. Instead, the llm generates code (scratchpad.ts) that orchestrates multiple mixers.
Given the following instruction:

Here is what the llm generates:

Unpacking that code:
1const symbolDefs = await findSymbolDefinition(context, ['findRelevantSymbol']);
2await memento(symbolDefs, '#findRelevantSymbol_def');
3
4for (const def of symbolDefs) {
5 const refs = await findSymbolReference(context, def);
6 await memento(refs, '#findRelevantSymbol_refs');
7}
8
9await setCodingGoal('Rename findRelevantSymbol to localSearch in the os workspace');
For that task the code below shows the following:
- It uses the LSP
findSymbolDefinitionto first locate the symbol. - It then leverages the LSP
findSymbolReferenceto find references to those symbols. - It saves all this information in
Mementofrom where those snippets can be referenced in the coding phase.
Note that this leads to efficient use of the LLM because in the coding phase we do not need to send FULL files, but only the snippets from Memento that need to be modified.
Finally, my approach differs from the popular “autonomous agent” paradigm where you can step away while the agent works independently. Instead, it’s about raising the abstraction level. The agent performs a kind of meta-programming, like the orchestration of LSP tools in the example above, while I remain in the loop to ensure things stay on track. My experience is that I am more productive with the oversight and control approach.
Inspired by the actor-critic RL approach, one technique I implemented is to have a separate Critic agent that does the approval for low stakes tasks on my behalf. More on that later.