ai-era-architecture-principles
npx machina-cli add skill shimo4228/claude-code-learned-skills/ai-era-architecture-principles --openclawAI Era Architecture Principles
Extracted: 2026-02-09 Context: When deciding whether to use large frameworks (LangChain, LiteLLM, etc.) vs custom implementation in the Claude Code era
Problem
Traditional software development wisdom says "Don't Reinvent the Wheel" — use existing libraries and frameworks to save development time. But in the AI-driven development era with Claude Code, is this still the best approach?
Key Questions:
- Should I use LangChain for LLM applications?
- Should I use a large framework with 50+ dependencies?
- When is custom implementation better than a comprehensive library?
Solution: The Three Principles
1. Micro-Dependencies Principle
Avoid large frameworks when Claude Code can implement needed features in hours.
Traditional Development:
Custom implementation: weeks → months ⏰
Use existing framework: days → weeks ✅
Claude Code Era:
Custom implementation: hours → 1 day ✅
Use existing framework: still brings 50+ dependencies ❌
Example (pdf2anki project):
- ❌ With LangChain: 50+ dependencies, black-box abstractions, breaking changes
- ✅ Custom: 6 dependencies (anthropic, pymupdf, pydantic, pyyaml, typer, rich)
- ✅ Result: 3,348 lines, full control, 96% test coverage, transparent
Benefits:
- Minimal dependencies → Easier maintenance
- No black-box abstractions → Full transparency
- No framework lock-in → Complete flexibility
- Faster startup/install → Better user experience
2. Perfect Fit Principle
Generic abstractions → Domain-specific design
Large frameworks provide generic solutions that work for many use cases. But your project has specific requirements. With Claude Code, you can implement exactly what you need.
Example (pdf2anki project):
# Project-specific requirements:
@dataclass(frozen=True) # ← Immutability requirement
class Section:
# Structure-aware chunking for long documents
heading_stack: tuple[str, ...]
# Per-section model routing (Haiku vs Sonnet)
char_count: int
# Batch API with 50% discount (Claude-specific)
client.messages.batches.create(requests=[...])
# Prompt caching control (Claude-specific)
system=[{
"type": "text",
"text": SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"} # ← Direct control
}]
These features are perfectly tailored to the project's needs. A generic framework would either:
- Not support these features, or
- Support them through complex configuration/plugins
Benefits:
- Code matches domain model exactly
- No unused features → Simpler codebase
- Direct control over critical features
3. Full Control Principle
Complete control over API calls, cost tracking, error handling
With direct SDK usage, you understand every line of code. With frameworks, behavior is hidden behind abstractions.
Example:
# ✅ Direct SDK: Crystal clear what happens
client = anthropic.Anthropic()
response = client.messages.create(
model=model,
max_tokens=max_tokens,
system=[...], # Explicit prompt caching
messages=[...]
)
cost = (response.usage.input_tokens / 1_000_000) * PRICE_PER_1M
# ❌ Framework: What's happening internally?
llm = ChatAnthropic(model=model)
chain = prompt | llm | parser
result = chain.invoke({"text": text}) # Caching enabled? Cost?
Benefits:
- Debugging is easy → No abstraction layers to dig through
- Testing is simple → Mock at SDK level
- Performance optimization → Profile exact bottlenecks
- Cost control → Track every token
The New Mantra
Traditional Era
"Don't Reinvent the Wheel"
AI Era (with Claude Code)
"Don't Import the Warehouse for a Single Wheel"
Why?
- Claude Code can build the exact wheel you need in hours
- Importing the warehouse (large framework) brings:
- 50+ dependencies you don't need
- Features you'll never use
- Complexity you don't want
- Breaking changes you must handle
When to Use Large Frameworks
Large frameworks ARE valuable when:
-
You need 80%+ of the framework's features
- Example: Django for full-stack web apps (ORM, auth, admin, forms, templates)
-
The framework provides critical infrastructure you can't easily replicate
- Example: React for complex UI state management
-
You're prototyping and speed > control
- Example: Using LangChain to quickly test different LLM providers
-
The framework has strong network effects
- Example: TensorFlow/PyTorch for ML (ecosystem, community, tools)
When to Avoid Large Frameworks
Avoid large frameworks when:
-
You need < 20% of the framework's features
- Example: Using LangChain just for API calls to Claude/OpenAI
-
Your requirements are highly specific
- Example: Custom cost tracking, specific batching logic, domain-specific optimizations
-
You value simplicity and control
- Example: CLI tools, libraries, utilities
-
The framework is rapidly changing
- Example: Early-stage AI frameworks with frequent breaking changes
Decision Framework
┌─────────────────────────────────────────────┐
│ Do I need > 50% of the framework features? │
└─────────────┬───────────────────────────────┘
│
No ──┴── Yes
│ │
│ └─→ Use Framework
│
▼
┌─────────────────────────────────────────────┐
│ Are my requirements highly specific? │
└─────────────┬───────────────────────────────┘
│
No ──┴── Yes
│ │
│ └─→ Custom Implementation
│
▼
┌─────────────────────────────────────────────┐
│ Can Claude Code implement it in < 1 day? │
└─────────────┬───────────────────────────────┘
│
No ──┴── Yes
│ │
│ └─→ Custom Implementation
│
└─→ Consider Framework
Real-World Example: pdf2anki
Decision: Add OpenAI API support alongside Claude API
Option 1: Use LangChain
- Dependencies: +10 packages (langchain, langchain-core, langchain-anthropic, langchain-openai, etc.)
- Code: ~200 lines (shorter)
- Control: Limited (cost tracking, batch API, caching = opaque)
- Maintenance: Must track LangChain updates
Option 2: Custom Provider Abstraction
- Dependencies: +1 package (openai SDK)
- Code: ~500 lines (longer, but all visible)
- Control: Complete (cost tracking, batch API, caching = explicit)
- Maintenance: Only SDK updates (Anthropic, OpenAI)
Chosen: Option 2 with conditional dependencies (even better!)
[project.optional-dependencies]
claude = ["anthropic>=0.40.0"]
openai = ["openai>=1.0.0"]
all = ["anthropic>=0.40.0", "openai>=1.0.0"]
Users install only what they need:
pip install pdf2anki[claude] # Only Anthropic SDK
pip install pdf2anki[openai] # Only OpenAI SDK
pip install pdf2anki[all] # Both (for comparison)
Result:
- Micro-Dependencies ✅ (users choose)
- Perfect Fit ✅ (domain-specific features preserved)
- Full Control ✅ (transparent cost tracking, batch API)
When to Use This Skill
Trigger: When you or the user are considering adding a large framework (especially for LLM applications).
Questions to Ask:
- What percentage of the framework's features will we actually use?
- Can Claude Code implement the needed features in < 1 day?
- Are there project-specific requirements that need fine-grained control?
- How important is dependency minimization for this project?
Remember: In the AI era, the cost of custom implementation has dropped dramatically. Factor this into your architecture decisions.
Related Patterns
python-optional-dependencies.md- Implementation pattern for multi-provider supportcost-aware-llm-pipeline.md- Custom cost tracking implementationlong-document-llm-pipeline.md- Domain-specific document processing
Source
git clone https://github.com/shimo4228/claude-code-learned-skills/blob/main/skills/ai-era-architecture-principles/SKILL.mdView on GitHub Overview
Guides whether to adopt large AI frameworks or build custom components in the Claude Code era. It centers on three principles—Micro-Dependencies, Perfect Fit, and Full Control—and uses the pdf2anki project as a practical reference to show trade-offs and outcomes.
How This Skill Works
Technically, you compare options against three principles: avoid large dependencies when a feature can be built quickly, tailor abstractions to domain needs, and retain full control by using direct SDKs or minimal, transparent code. Then you validate with testing and cost tracking to ensure the chosen approach fits the project.
When to Use It
- Evaluating whether to use a large LLM framework like LangChain for a Claude Code project.
- When the project has domain-specific requirements that generic frameworks can't easily cover.
- When minimizing dependencies and avoiding black-box behavior is critical for maintenance.
- When you need explicit control over prompts caching, cost tracking, and error handling.
- When starting a new AI-driven project in Claude Code and choosing between bespoke vs library-driven architecture.
Quick Start
- Step 1: List project requirements, dependencies, and Claude Code capabilities.
- Step 2: Apply the three principles to decide between custom vs large framework.
- Step 3: Implement the chosen approach and validate with tests and cost tracking.
Best Practices
- Estimate feature implementation time with and without a framework; aim for hours rather than days if possible.
- Favor micro-dependencies and transparent code over monolithic platforms.
- Define domain-specific data models and routing to avoid generic abstractions.
- Prefer direct SDK usage to maintain visibility and testability.
- Instrument prompt caching, cost accounting, and error handling from day one.
Example Use Cases
- pdf2anki project demonstrating the trade-off between LangChain with 50+ dependencies and a custom approach with 6 dependencies.
- The custom approach for pdf2anki achieves full control, lower dependency surface, and high test coverage.
- Domain-specific features such as immutability in data models and per-section model routing are shown as perfect-fit examples.
- Prompt caching control via Claude-specific ephemeral cache showcases direct control over critical features.
- Direct SDK usage is highlighted as the path to clear debugging, straightforward testing, and precise cost tracking without framework layers.