Skip to main content

HippoBuddy Architecture Philosophy

An Agent framework for the AI era: from "framework-driven" to "capability-driven"


Origin

By installation volume, Pull Request count, and Stack Overflow discussion热度, the vast majority of AI Agent frameworks on the market today are Python-based (LangChain, CrewAI, AutoGPT, etc.). Behind this lies historical inertia and ecosystem path dependency:

  • LLM SDKs prioritize Python first — OpenAI, Anthropic, and HuggingFace SDKs all ship Python first
  • Academic tradition — Deep learning / CV / NLP research is almost entirely Python-based; researchers naturally carry this into industry
  • Jupyter culture — Agent development is inherently experiment-driven; Python's REPL + Jupyter enables rapid iteration

But HippoBuddy chose Java 21. This is not a contrarian technical choice, but a deliberate architectural judgment: the core complexity of an Agent isn't "calling an LLM" — it's "building a reliable automation system" — which is precisely where the Java ecosystem has accumulated decades of strength.


Core Insight: The Changing Role of Frameworks in the AI Era

The Golden Age of Frameworks

Before the AI explosion, the value of frameworks was undisputed:

You want to build a Web project →
Need HTTP, routing, MVC, ORM, transaction management, DI…
Write it yourself? That's half a year gone
→ Use Spring Boot, done in a day ✅

A framework's essence is "package up大量 repetitive infrastructure so you can focus on business logic."

The Turning Point of the AI Era

But the "infrastructure" of Agent development has fundamentally changed:

You want to build an Agent →
Need LLM calls, Tool Calling loops, message management, Prompt templates…
Write it yourself? — Let AI write it for you

"Write me a Tool Calling loop in Java that
parses function_call responses from the LLM
and executes local tools with the given arguments"
→ Generated in 30 seconds, working in 5 minutes ✅

Old world:

Framework value = work saved - learning cost - constraint cost
≈ huge, because writing by hand was too hard

AI era:

Framework value = work saved - learning cost - constraint cost
≈ diminished, because AI can write most infrastructure for you

Frameworks Solve "Old Problems," Not "New Problems"

FrameworkOld Problem It SolvesWhat Agents Actually Need
SpringTransaction mgmt, ORM, AOPAgents don't need database transactions
LangChainChain, Agent, Memory abstractionsTweaking a prompt is 10x faster than tweaking framework config
HibernateORM mappingAgent state is conversation messages, not relational data
MyBatisSQL mappingSame as above

What Agents really need, frameworks can't help with:

Real NeedSolutionNeed a Framework?
Call LLM APIOkHttp + Jackson send HTTP❌ Done in 10 lines
Parse Tool CallJSON deserialization❌ One Jackson annotation
Execute local toolsInterface + implementation❌ 7-line interface definition
Manage conversation historyList<Message>❌ ArrayList is enough
SSE streamingOkHttp SSE❌ One library dependency

The core complexity of an Agent isn't in infrastructure — it's in prompt design and tool orchestration. Frameworks can't help you there, and often constrain you.


HippoBuddy's Architectural Choices

No Frameworks, Just Patterns

HippoBuddy's Java backend uses no heavyweight frameworks — no Spring, no LangChain4j, no Guice. Instead, a lightweight, hand-written architectural pattern:

1. Manual DI, Not Auto-Injection

// CoreModule.java — manually assemble dependencies by layer
ServiceLocator.registerSingleton(ToolRegistry.class, toolRegistry);
ServiceLocator.registerSingleton(LlmClient.class, llmClient);
ServiceLocator.registerSingleton(ConcurrentToolExecutor.class, concurrentToolExecutor);

No @Autowired, no @Bean, no component scanning. Every service's lifecycle and dependency relationship is explicitly declared — traceable and debuggable.

2. Interface Contracts, Not Framework Annotations

// ToolExecutor.java — 7 lines define everything
public interface ToolExecutor {
String getName();
String getDescription();
String getParametersSchema(); // JSON Schema string
String execute(JsonNode arguments) throws ToolExecutionException;
}

Each tool is simply an interface implementation — no decorators, no base class inheritance chains, no need to understand the framework's "correct usage."

3. Direct JSON Schema, Not Framework Abstractions

// ReadFileTool.java — Java 21 text blocks write Schema directly
@Override
public String getParametersSchema() {
return """
{
"type": "object",
"properties": {
"path": { "type": "string", "description": "File path" },
"offset": { "type": "integer", "description": "Starting line" },
"limit": { "type": "integer", "description": "Lines to read" }
},
"required": ["path"]
}
""";
}

The format LLMs understand is JSON Schema — no framework "double translation" needed.

Why Not Dedicated AI Frameworks

The Java ecosystem also has dedicated AI frameworks — Spring AI and LangChain4j. We chose neither, for the same reasons about the role of frameworks in the AI era:

1. Fast-changing frameworks become a liability in the AI-coding era

Most of the code today is generated by AI, but Spring AI and LangChain4j are still in rapid iteration with frequent API changes. AI models have limited and easily stale knowledge of these "young frameworks" — ask it "how to call tool calling with Spring AI" and the generated code is likely based on an outdated API, producing NoSuchMethodError at runtime, forcing you back to the official docs. Rather than having AI learn a framework it can't get right, it's better to generate the most stable, lowest-level HTTP + JSON code — the OpenAI API specification hasn't changed in over a year, and AI's knowledge of it is far more accurate.

2. What frameworks encapsulate, AI generates faster and with more control

Spring AI's ToolCallback and LangChain4j's ToolSpecification are essentially wrappers around the "call LLM API → parse JSON → invoke local method" flow. But having AI write this loop directly takes 5 minutes and yields dependency-free, step-debuggable code. The little work a framework saves you is negligible in the face of AI's coding ability, and in return you get complete control over every line.

3. Complex features still need to be written yourself — frameworks become the ceiling

Once your Agent needs capabilities the framework didn't anticipate — tool-level caching, file locking, concurrency control policies, custom security interceptors — the framework's abstractions become obstacles. You either hack its internals (upgrade compatibility nightmare) or wrap another layer around it (defeating the purpose). "Complex functionality" in the Agent domain is being defined rapidly; committing to a framework means accepting its assumptions about what counts as "complex."

The Freedom These Choices Bring

By removing framework constraints, HippoBuddy can freely implement capabilities that are difficult in Python Agent frameworks:

CapabilityImplementationDifficulty Under Frameworks
File cachingReadFileTool with built-in LRU cache to avoid repeated disk readsLangChain Tools are stateless; need to wrap them yourself
Security interceptor chainBlockerChain performs permission/security checks before tool executionAgentExecutor has no such hook point
Event monitoringEventBus publishes tool execution events for monitoring and statisticsRequires extending the framework's callback mechanism
Concurrent tool executionVirtual threads + ConcurrentToolExecutor — synchronous code running concurrentlyasyncio infects the entire call chain
File lockingrequiresFileLock() controls mutual exclusion between toolsEssentially non-existent in Python Agents
Granular error handlingLlmApiException / LlmConnectionException / LlmTimeoutException layered exceptionsUsually a single APIError catches everything

Defining Tools with JSON Schema

Each tool defines its parameter structure via getParametersSchema(), returning a JSON Schema string. ToolRegistry registers them uniformly, Jackson serializes them uniformly, building the tools parameter list for LLM function calling.

Tool execution flow:

LLM returns tool_call (JSON)
→ ToolRegistry.execute(name, arguments)
→ BlockerChain security check
→ ToolExecutor.execute(JsonNode)
→ Returns result string
→ Result appended to message list
→ Continue next LLM call

Comparison with Python Agents

Common Python Agent Problems

# Typical pain points with Python + LangChain
from langchain.agents import AgentExecutor

# Want to customize tool execution logic?
# → Must extend BaseTool, implement _run + _arun
# → Want to change agent prompt? Must rewrite the entire agent class
# → Want concurrent execution? AgentExecutor doesn't support it
# → Want middleware? No hook points

HippoBuddy's Corresponding Solution

// Implement the interface, that's it
public class CustomTool implements ToolExecutor {
@Override
public String execute(JsonNode arguments) {
// Complete freedom — add caching, locking, logging, monitoring as needed
// No need to follow any framework's "proper way"
}
}

Summary Comparison

DimensionPython Agent (LangChain)HippoBuddy (Java)
Getting startedFast, pip install and goSlower, but AI-assisted coding helps
FlexibilityFramework constraints, customization is hardNo constraints, complete freedom
Type safetyType errors found at runtimeMost errors caught at compile time
Concurrency modelasyncio infects the entire chain, mental overheadVirtual threads, synchronous code
Desktop supportNeeds Electron/PyQt wrapperNative Electron integration
Enterprise integrationNeeds bridge to Java stackNaturally fits Java ecosystem
Production deploymentComplex environment management (pip env)Maven shade single JAR
Framework upgradesLangChain breaking changes are frequentNo framework, never need to upgrade

Thoughts on Software Engineering in the AI Era

The Role of Frameworks is Changing

Before: Framework = the ceiling of what you can build
Now: Framework = the floor of what you can build (and sometimes a bottleneck)

When Should You Use a Framework?

Frameworks still have value, but need re-evaluation:

ScenarioSuggestionRationale
Team has mature tech stackUse existing frameworkReduce team switching cost
Non-core businessUse frameworksLogging, config, monitoring — not worth writing yourself
Agent core logicWrite it yourselfThis is your core differentiator; frameworks can't help
Experimental projectsFramework for quick validationOnce validated, consider de-framing

Why "Writing It Yourself" is Feasible in the AI Era

In traditional development, writing a Tool Calling loop requires:

  1. Understanding HTTP requests and SSE streaming responses
  2. Mastering JSON serialization/deserialization
  3. Designing state management (message list)
  4. Handling errors and retries
  5. Designing tool registration and discovery mechanisms

Each of these requires consulting大量 documentation and code examples.

In the AI era, you just tell the LLM:

"Write me a Java method that receives an LLM chat completion response, parses the tool_calls, finds the corresponding executor by tool name, executes with the given arguments, and wraps the result as a tool message."

30 seconds later, you have runnable code. The rest is just adapting it to your specific needs — which is exactly where frameworks constrain you most.


Conclusion

The core philosophy behind HippoBuddy's architectural choices:

In the AI era, the best "framework" is no framework.

Not because frameworks are bad, but because frameworks solve "known problems," while the Agent domain is still evolving rapidly, with new "unknown problems" every day.

A flexible architecture + AI's coding ability adapts to change better than any framework.

This also explains the logic behind HippoBuddy's tech stack choices:

QuestionAnswer
Why Java?Type safety + virtual threads + enterprise ecosystem — an Agent is a system, not a script
Why not Spring?Agents don't need ORM/transactions/AOP; hand-written DI is more controllable
Why not LangChain4j?Tool Calling is fundamentally a loop; writing it yourself is faster than learning a framework
Why Electron?Desktop is the best Agent interaction modality; Electron is the most natural partner for a Java backend
Why can we write it ourselves?Because AI reduces the cost of writing infrastructure from "months" to "minutes"

This is HippoBuddy's architecture philosophy: don't follow framework trends — build genuinely usable AI Agents the way that fits best.