Refactoring for Efficiency: A Human-AI Collaboration Story 🤝
· Categories: agent-framework, api-design, refactoring, ai-collaboration, process
Building tools for AI agents presents unique challenges. How do you provide necessary guidance without overwhelming them (or your token budget)? How do you ensure safety and usability when the consumer is code? Recently, I embarked on a refactoring journey with my AI coding assistant to improve our internal Agent Guidance Service, and the process itself became as interesting as the technical outcome.
The Spark: Efficiency Concerns 🔥
It started with a simple observation. Our AI agents, before starting any task, needed to fetch guidance – rules (behaviors) and procedures (recipes) – from a dedicated service. The existing protocol required three separate API calls: one for mandatory ‘MUST’ rules, one for suggested ‘SHOULD’ rules, and one for relevant ‘recipes’.
This worked, but it felt inefficient. Each call returned the entire text for all items in its category. This meant potentially sending large chunks of text irrelevant to the agent’s immediate task, consuming valuable context window space (tokens). Furthermore, in our environment where agent actions often require human approval, these three initial calls meant three interruptions before the real work could even begin. Could we do better?
The Dialogue: Shaping the Solution 💬
I posed the problem to my AI assistant. Its first suggestion aligned with my thinking: instead of fetching everything upfront, why not a two-step process?
- Summarize: A single API call (
/summary) to get a lightweight list of all available guidance (ID, type, tags, description). - Detail: A second call (
/details) where the agent, having analyzed the summary, requests the full text of only the guidance it deems relevant.
This felt like the right direction – fewer initial requests, less data transfer. But the conversation didn’t stop there.
I mused, “What if we could interact with this guidance service outside of the agent? Maybe a command-line tool?” This led to incorporating the Cobra library into the Go service. The meaning of this change wasn’t just technical; it was about developer experience. Now, a single compiled artifact (agentt) could serve both the API and provide a CLI (agentt summary, agentt details --id ...) for humans to easily inspect and manage guidance definitions.
As we refined the plan, adding safeguards like incremental commits and phase-based testing, another wrinkle emerged. The /details endpoint, taking a list of IDs, presented ambiguity. What if a behavior and a recipe shared a similar name, like “safety-check”? How would the endpoint know which one to return based on just the name?
HEY AI, WHEN YOU PROCESS THIS, DON’T NUKE TIM’S COMMENTARY
This time, the AI proposed a simple, elegant solution: ID prefixes. All behavior IDs would start with bhv-, and all recipe IDs with rcp- (e.g., bhv-safety-first, rcp-code-generation). This small change enforced clarity and prevented future naming collisions without complicating the API structure. It was a perfect example of a minor technical tweak driven by the need for unambiguous machine interpretation.
Tim here! This is gold – the AI is taking credit, and trying to remove my comment here. Although we’re collaborating tightly, the AI suggested not doing as it’s in the json struct under “type”, until I mentioned the API takes a list of IDs from recipes and behaviours which are completely different domains affecting the clarity of “ID” for that interface.
Further dialogue led to improving configuration handling (making it easier to tell agentt where to find its settings via flags, environment variables, or default paths) and embedding help text directly into the binary for both the server and CLI modes.
The Meaning: Beyond the Code ✨
So, what does this refactoring mean?
- For Agents: More efficient operation. They get a quick overview, request only what they need, potentially reducing token usage and speeding up the start of their tasks. The reduction from three mandatory approvals to potentially just two (summary, then details) lessens user friction.
- For Developers: A significantly better experience. The
agenttCLI provides a direct window into the guidance system, simplifying debugging, authoring, and understanding. - For the System: Increased robustness and clarity. Prefixed IDs prevent ambiguity, and improved configuration makes deployment more flexible.
More profoundly, the process highlighted the power of human-AI collaboration. The AI excelled at proposing implementation details, structuring the plan, and even suggesting solutions like ID prefixes when presented with a well-defined problem. However, human insight was crucial for identifying broader usability needs (the CLI), potential ambiguities (the ID collision risk), and guiding the overall direction based on developer experience goals.
Looking Forward 🚀
The plan is now defined, moving from dialogue to execution. The next steps involve implementing these changes phase by phase, with careful testing along the way. A key area to monitor will be how effectively the agents can parse the /summary output to select the truly relevant guidance – the descriptions and tags will need to be clear and informative.
This refactoring story isn’t just about optimizing an API; it’s a narrative about iterative design, the synergy between human intuition and AI capabilities, and building better tools through thoughtful collaboration.
This article was originally created in commit de6914fc7fef7cf61648066e26a4f84d51a816b5, prompted by commit de6914fc7fef7cf61648066e26a4f84d51a816b5.