DEV Community

Cover image for Langchain has trapped me in hell. Finally I escaped
Michał Szczepański
Michał Szczepański

Posted on

Langchain has trapped me in hell. Finally I escaped

I spent 15 days tuning the LangChain DeepAgents library for my documentation app to improve UX and bring CASCADE. Finally, I resolved the problem by publishing RavenADK.

Static story

Tuning Langchain was a journey through a maze of abstractions heated up to white steel, where every step felt like fighting the framework instead of building something that will be easy as a feature for the next app iterations.

The biggest pain? Most agent libraries are built to be static, non-evolving, and non-communicating with the world. They don't evolve. You write the logic, and it stays static for life; while it should learn, it should improve itself. Once I'd realised this, I found that I needed my agents to learn, to grow, and to show the user what they were doing without leaving them "worried" with a spinny loading circle.

"We've to know what's going on" they told me

The shortest path to realise what I've thought was to build an agents library with a clever design.

RavenADK Logo

Solution

Here I announce RavenADK cuts to the case that I supposed LangChain to have. It’s auto-evolving with CASCADE, light, documented, and built for people who want to implement ideas in minutes, not weeks. A clever design prevents maze abstractions, just event-driven logic for UI/UX that moves as fast as your ideas do.

RavenADK Build

RavenADK was built on three pillars.

  • Events: Every executable construct is a factory of events. You listen to them and act according to needs.

import { ReActAgent } from "@ravenlens/raven-adk/agents";

const agent = new ReActAgent({ /* ... */ });

// Real-time tracking without fighting abstractions

agent.onEvent("reasoning", (thought) => {

    updateUI(`Thinking: ${thought}`);

});

Enter fullscreen mode Exit fullscreen mode
  • CASCADE: I hated manually updating skills for every edge case. Following the CASCADE pattern, RavenADK agents can actually auto-create and use their own skills.

*   Discovery: The agent finds a gap in its knowledge. Originally file consists of 2048 worlds are conclusion of full agent knowledge is load to Agent Memory to know more about user, task. Then agent leverages memory to delve deeper in seeking facts included in memory

*   Creation: It generates a new script or instruction set.

*   Persistence: It saves it to its own "brain" so it gets smarter for the next user.

Enter fullscreen mode Exit fullscreen mode
  • Connecting the Mesh of Agents (GACP Protocol):

Static delegation is a bottleneck. The Graph Agent Communication Protocol enables a living ecosystem of agents:


*   Centralized Broker (MQTT): A marketplace for skills and tools.

*   Serverless (WebRTC/Web3): Direct, peer-to-peer communication for high-privacy environments.

Enter fullscreen mode Exit fullscreen mode

Features

ReAct Agent

ReAct is the main RavenADK agent, which works in a continuous workflow of actions reason -> act where it delegates tasks to the subagents, uses tools, skills and memory along progress and reasons about tasks on demand.

Use RLM when you have a large dataset and need to extract structured information through iterative analysis.
You can take advantage of RLM before send task to ReActAgent to reduce costs

Example code

import { ReActAgent } from "@ravenlens/raven-adk/agents";
import { tool } from "@ravenlens/raven-adk/tools";
import { OpenAI, Anthropic } from "@ravenlens/raven-adk/models";
import * as z from "zod";
import { SkillMongoDBStore } from "@ravenlens/raven-adk/skills/store";
import { MemoryChromaDBStore } from "@ravenlens/raven-adk/memory/store";
import { HITLSocketIo } from "@ravenlens/raven-adk/tools/hitl";

const reactAgent = new ReActAgent({
    model: new OpenAI({
        model: "gpt-5.6-luna",
        apiKey: "your-api-key",
    }),
    systemPrompt: "You are a helpful assistant.",
    messages: [
        {
            type: "user",
            content: "Check the weather in London"
        }
    ],
    tools: [
        tool(
            ({ location }) => {
                return JSON.stringify({ temperature: 22, unit: "Celsius" });
            }, 
            {
                toolName: "get_weather",
                toolDescription: "Check weather condition for given location",
                toolArguments: z.object({
                    location: z.string()
                })
            }
        )
    ],
    // Optional: High Performance Execution Configuration
    parallelTools: true,
    parallelizeSubagents: true,
    withConclusion: true,
    maximumReasoningRecalls: 5,
    // Optional: Skills, Memory, HITL, Subagents configuration
    // ...
});

// Register event listeners
reactAgent.onEvent("reasoning", (thought) => {
    console.log("Thinking...", thought);
});

reactAgent.onEvent("reasoning_end", (thoughts) => {
    console.log("Agent full thoughts:", thoughts);
});

// Invoke the agent with reasoning configuration
const result = await reactAgent.invoke({
    reasoning: {
        budgetTokens: 16000 // For models supporting thought budgets (Claude 3.7 / Gemini)
    }
});
console.log("Final Answer:", result.messages.at(-1).content);
Enter fullscreen mode Exit fullscreen mode

RLM

Recurrent Language Models is a pattern to reduce costs by 60% avg and enlength context window of standalone model, It consists of orchestrator executes code and subagents to resolve given subtasks

import { RLMAgent } from "@ravenlens/raven-adk/rlm";
import { NodeExecutionSandbox } from "@ravenlens/raven-adk/sandboxes";
import { OpenAI } from "@ravenlens/raven-adk/models";

// Load a massive log file (e.g., 10MB+ of server logs)
const hugeLogData = await fs.readFile("./logs/production.log", "utf-8");

// Initialize RLM with orchestrator and sub-models
const rlmAgent = new RLMAgent(hugeLogData, {
    model: new OpenAI({
        model: "gpt-5.5",  // Orchestrator: expensive, powerful
        apiKey: process.env.OPENAI_API_KEY
    }),
    submodels: [
        {
            model: new OpenAI({
                model: "gpt-5.5-mini",  // Sub-model 1: fast, cheap
                apiKey: process.env.OPENAI_API_KEY
            }),
            instruction: "Extract error messages and their frequency"
        },
        {
            model: new OpenAI({
                model: "gemini-3.5-flash-preview",  // Sub-model 2: reusable
                apiKey: process.env.OPENAI_API_KEY
            }),
            instruction: "Identify performance anomalies and latency issues"
        }
    ],
    maxIterations: 10,
    codeSandbox: new NodeExecutionSandbox()
});

// Listen to events
rlmAgent.onEvent("start_iteration", (iterNum) => {
    console.log(`▶ Iteration ${iterNum} started...`);
});

rlmAgent.onEvent("orchestrator_model_call", (model, result) => {
    console.log(`📝 Orchestrator decided:`, result.substring(0, 100) + "...");
});

rlmAgent.onEvent("execute_code_start", (code) => {
    console.log(`🔧 Executing code:\n${code.substring(0, 200)}...`);
});

rlmAgent.onEvent("submodel_call", (model, task) => {
    console.log(`🤖 Delegating to sub-model: ${task.substring(0, 80)}...`);
});

// Run the analysis
const result = await rlmAgent.invoke(
    "Analyze the logs and provide: 1) Top 5 error types, 2) Error frequency trend, 3) Performance bottlenecks"
);

console.log("✅ Final Analysis:\n", result);

// Get token usage for cost calculation
const usage = rlmAgent.getUsage();
console.log("📊 Token Usage:", {
    orchestrator: usage.orchestrator_llm,
    submodels: usage.submodels
});
Enter fullscreen mode Exit fullscreen mode

RAG

Ground answers in reality with retrieval-augmented generation.

  • Use with a standalone LLM or with a ReAct agent
  • Use upfront a configured ChromaDB, Pinecone, or in-memory for the production now
  • Implement your own vector database in 4 minutes
import { ResourceAugmentedGeneration } from "@ravenlens/raven-adk/augmented_generation";
import { OpenAI, OpenAIEmbedding } from "@ravenlens/raven-adk/models";
import { ReActAgent } from "@ravenlens/raven-adk/agents";
import { ChromaDB } from "@ravenlens/raven-adk/vector_databases/chromadb";

const embeddingModel = new OpenAIEmbedding({ 
    apiKey: "your-api-key", 
    model: "text-embedding-3-small" 
});

const ragBase = new ResourceAugmentedGeneration({
    query: "What is the state of AI Development at our company?",
    database: chromaDbInstance,
    model: embeddingModel
});

// Using with a Standalone Model
const modelResult = await ragBase
    .register(new OpenAI({ model: "gpt-5.5" }))
    .invoke({ method: "invoke" });

// Using with a ReAct Agent
const agentResult = await ragBase
    .register(new ReActAgent({ /* config */ }))
    .invoke();
Enter fullscreen mode Exit fullscreen mode

Check Documentation and meet other constructs and API

Why You Should Use RavenADK for Your Next Project

We’ve deliberately avoided the "abstraction hell" that plagues the ecosystem. RavenADK is:

  1. Lightweight: No overengineering, just powerful code.
  2. Event-Based: Use events to listen and communicate everything your agent is doing just like a VSCode, ClaudeCode, Cursor show progress steps
  3. Well Documented: Go from `npm install "to" production in minutes.

  4. Community First: We want your PRs, your custom sandboxes, and your plugins.

Check out the repo here.

Let’s stop fighting the framework. Give RavenADK a star. ⭐️, try it on your next project, and let’s build agents that actually evolve. I want to hear your nightmare stories in the comments—how long have you spent trying to "tune" a library that just wouldn't bend?

Top comments (0)