The Framework Trap: What "Batteries Included" Actually Costs You
Frameworks optimize for the first 48 hours of a project — the demo, the hackathon, the internal proof-of-concept. Production systems optimize for the next 18 months. That mismatch is why teams repeatedly adopt LangChain, hit a wall, and either abandon it quietly or build workarounds that defeat the purpose of using a framework at all.
The friction points are structural, not incidental. LCEL and the Runnable interface leak abstraction boundaries: you declare a chain declaratively, but the moment you need conditional branching, dynamic tool selection, or non-linear state transitions, you're fighting the framework's execution model. Version churn compounds the problem — minor releases have introduced breaking changes to core interfaces (prompt templates, output parsers, agent executors) frequently enough that upgrading becomes a scheduled sprint, not a dependency bump. Debugging opacity is the third tax: stack traces terminate in framework internals, callback handlers fire in non-deterministic order, and the "magic" that made the demo work becomes the obstacle when something fails at 2 AM.
Vendor lock-in arrives subtly. Business logic couples to BaseMessage subclasses, Tool decorators, and framework-specific memory implementations. Extracting that logic later means rewriting the parts that actually matter.
Decision Matrix: Score Your Context Before You Commit
Opinions don't ship code. A weighted rubric lets your team agree on the trade-offs before investing in either path. Score each criterion 1–5 (1 = framework strongly favored, 5 = frameworkless strongly favored), multiply by weight, sum, and divide by total weight. If the weighted average falls below 3.5, the frameworkless path earns a spike.
Criterion Weight Score 1 (Framework) Score 3 (Neutral) Score 5 (Frameworkless) Team size & agent experience 0.20 < 3 engineers, no prior agent work 3–5 engineers, some production exposure > 5 engineers, multiple production agents Latency SLA strictness 0.15 No hard SLA, batch-tolerant P99 < 5s, some flexibility P99 < 2s, user-facing, cost-sensitive Custom tooling / non-standard integrations 0.20 Standard tools only (search, code exec, HTTP) 1–2 custom tools, well-defined schemas Many custom tools, legacy systems, dynamic discovery Hiring & onboarding constraints 0.15 Must hire juniors who know the framework Mixed seniority, can mentor Senior-heavy, values transferable patterns Compliance / audit requirements 0.15 No special requirements Standard SOC2, data residency PII handling, deterministic replay mandated, approved-library lists Expected agent lifespan 0.15 < 2 weeks (throwaway) 2–12 months > 12 months, evolving requirements
Example: a 5-person team building a RAG agent with PII constraints, 2-second P99 latency, and 3 custom internal tools. Scores: team 3, latency 4, tooling 4, hiring 3, compliance 5, lifespan 4. Weighted average = 3.8. Frameworkless spike justified.
Download the decision matrix CSV template — plug in your numbers, share with the team, avoid the "it depends" loop.
What You Rebuild When You Go Frameworkless (And What You Don't)
The "custom runtime" scare story assumes you're reimplementing LangChain. You're not. A minimal viable agent runtime is roughly 80 lines of async state machine: a loop that reads state, selects a tool or LLM call, executes it, updates state, and checks termination. The framework's 500+ lines of glue — callback managers, runnable config merging, middleware chains, serialization logic — vanish because you don't need generic extensibility; you need your extensibility.
Tool registry: a dict[str, ToolSpec] where ToolSpec holds a JSON Schema (for the model) and a handler Callable[[dict], Awaitable[ToolResult]]. No decorators, no metaclasses, no import-time side effects. Registration is explicit, testable, and hot-reloadable.
Observability: structured log lines (JSON) + span events (OpenTelemetry or similar) emitted at three points — agent.step.start, tool.call, agent.step.end. No callback hell, no context propagation through framework layers. You own the schema; dashboards query it directly.
What stays external: your vector DB client, LLM provider SDK (OpenAI, Anthropic, etc.), evaluation harness, secrets manager. The runtime coordinates; it doesn't replace infrastructure.
Reliability Patterns That Frameworks Obscure
Frameworks impose a linear "chain" mental model. Production agents need patterns that don't fit.
Idempotency at the tool-call level. Every tool invocation carries a content-addressable key (hash of tool name + frozen arguments + agent run ID). Before executing, check a cache (Redis, SQLite, in-memory). On hit, return cached result. This makes retries safe by default and enables deterministic replay — re-run the agent with the same input and seed, get the exact trajectory.
Saga compensation for multi-step agents. Each tool that mutates external state registers a rollback handler at call time. If a later step fails, the runtime walks the stack backward executing compensations. Frameworks treat tools as pure functions; they have no concept of "undo."
Deterministic replay. Log the full input, the random seed, and every tool call/result. Replay reproduces the exact LLM outputs (if temperature=0 and seed fixed) and tool interactions. Debugging becomes "re-run with this log" instead of "add print statements and hope."
Circuit breakers per tool, not per agent. A failing SQL tool shouldn't kill the web-search tool. Each tool registry entry wraps its handler with a breaker (failure threshold, timeout, half-open probe). The agent loop sees a ToolResult.error and decides — retry, fallback, escalate — without the framework's global error handler intercepting.
Migration Path: Strangler Fig Your Way Out
Rewrites fail. The strangler fig pattern works: wrap, route, observe, cut over.
Define your custom interface. A minimal protocol:
run(input: AgentInput) -> AsyncIterator[AgentEvent]. Events mirror the observability schema above.Wrap existing LangChain chains. An adapter implements your interface by invoking the LangChain executor and translating its callbacks into your event stream. Zero logic changes to the chain itself.
Route new agents to the custom runtime. Feature flag per agent type. Legacy stays on LangChain; new work uses the runtime. Both emit identical events — dashboards don't care.
Migrate incrementally. When a legacy agent needs changes, rewrite that agent in the custom runtime. The adapter stays for untouched agents.
Kill switch. Per-agent feature flag. If the custom runtime regresses, flip the flag; the adapter takes over instantly.
Teams executing this pattern often engage agentic AI systems specialists to design the adapter layer and event schema — the migration's success hinges on observability parity from day one.
When LangChain Still Makes Sense (Honest Boundaries)
This isn't anti-framework dogma. LangChain earns its keep in specific contexts:
Rapid prototyping, hackathons, internal tools with < 2 week lifespan. The demo velocity is real. If the code deletes itself in two weeks, framework tax is irrelevant.
Teams with zero prior agent experience needing guardrails. The framework enforces structure (prompts, tools, memory) that prevents common foot-guns. Treat it as training wheels with a removal date.
Heavy reliance on LangChain-specific integrations. Certain document loaders, vector store wrappers, and third-party toolkits only exist as LangChain packages. Porting them may cost more than the framework tax.
Compliance regimes mandating approved-library lists. If your infosec team has blessed LangChain and rejects custom code, the decision is made for you. Build the adapter layer anyway — it insulates your logic.
Outside these bands, the framework's opinions become your constraints.
Checklist: Your Go/No-Go Decision This Sprint
Answer yes/no. Five or more "yes" → start a frameworkless spike this sprint.
Does the agent need to run in production for > 3 months?
Do you have > 2 custom tools or non-standard integrations?
Is P99 latency < 3 seconds a hard requirement?
Does compliance require deterministic replay or audit logs per tool call?
Can your team write an async state machine and a dict-based registry without hand-holding?
Will hiring favor engineers who know patterns over engineers who know a framework?
Is the current LangChain version causing upgrade pain or debugging opacity?
If you're spinning up the spike, the agent runtime starter kit provides the 80-line loop, tool registry, OpenTelemetry hooks, and idempotency cache — MIT licensed, no framework dependencies. For teams wanting a second opinion on the matrix scoring, we offer a free 30-minute architecture review — bring your constraints, we'll walk through the trade-offs and tell you exactly which path minimizes regret.
How Armor Tech Can Help
At Armor Tech, we help SaaS businesses design and implement reliable AI agent architectures that balance flexibility, performance, and maintainability. Our team evaluates whether established frameworks or frameworkless approaches are best suited to each use case, building solutions with clear orchestration logic, efficient tool integrations, structured state management, and robust error handling. From developing lightweight custom agent workflows to simplifying complex AI pipelines and integrating RAG-based systems with existing APIs, we focus on architectures that are transparent, scalable, and production-ready. By prioritizing practical engineering decisions, measurable business outcomes, and appropriate human oversight, Armor Tech helps businesses move beyond experimentation and build AI systems they can confidently operate and maintain.
Frequently Asked Questions
How much boilerplate does a custom runtime actually add compared to LangChain?
Roughly 80–120 lines for the core loop, tool registry, and observability hooks. LangChain's surface area is larger, but most of it solves problems you don't have (generic serialization, middleware chains, multiple runnable types). The custom code solves exactly your problems — tool signatures, retry policies, event schema — and nothing else.
Can I keep using LangChain's prompt templates and output parsers in a frameworkless setup?
Yes. They're independent utilities. Import ChatPromptTemplate and PydanticOutputParser directly; they don't require the Runnable execution engine. Many teams keep the prompt/parser layer while replacing the orchestration layer.
What's the biggest risk of going frameworkless that the matrix doesn't capture?
Knowledge concentration. If one engineer builds the custom runtime and leaves, the bus factor is real. Mitigate: document the event schema and state machine as architecture decision records, pair-program the first three agents, and treat the runtime as a shared internal library with code review standards, not personal infrastructure.




