Show HN: AI code reviewer with Python agent called from Rust, streaming works

3 months ago 2

RunAgent

Zoom image will be displayed

How to create AI agents with persistent memory that learn from every code review

In the quest to enhance software development with AI, building intelligent code reviewers is a key milestone. Letta, an innovative open-source framework, allows developers to create stateful AI agents that can retain memory and reason over time, making it ideal for tasks like code review where context is paramount. Join us as we explore how to use Letta to develop a sophisticated AI code reviewer for Rust, unlocking new possibilities for automated code improvement and learning.

Traditional AI code reviewers lack memory, treating each review as isolated and forgetting past interactions — this is akin to having a different reviewer for every pull request, starting from scratch each time. This limits their ability to learn from previous feedback or adapt to a developer’s style. However, with stateful AI frameworks like Letta, developers can build code reviewers that maintain persistent memory, remembering past reviews and providing more informed, contextual feedback over time.

Zoom image will be displayed

Letta changes this fundamentally.

Built by the creators of MemGPT, Letta enables AI agents to maintain persistent memory across sessions. Your code reviewer can remember:

  • Your coding patterns and preferences
  • Previously identified issues and how you resolved them
  • Team-specific guidelines and conventions
  • Historical context about your codebase evolution

This isn’t just about storage — it’s about intelligent context management that allows agents to build genuine understanding over time.

Letta’s memory system operates on three distinct levels:

Zoom image will be displayed

Core Memory: Editable memory blocks that stay in context, containing essential information like your coding style preferences and project-specific guidelines.

Recall Memory: Complete interaction history that can be searched and retrieved, preserving the context of every code review discussion.

Archival Memory: A vector database storing processed knowledge, from documentation snippets to best practices discovered through experience.

This tri-layered approach means our code reviewer doesn’t just analyze code — it builds institutional knowledge about your development practices.

Let’s walk through creating a simple memory-enabled code reviewer that grows smarter with every interaction.

First, we’ll establish our Letta server and create an agent equipped with specialized code analysis tools:

import os
from letta_client import CreateBlock, Letta
from code_review_tools import analyze_code_quality, detect_security_issues
# Create memory blocks for persistent learning
memory_blocks = [
{
"label": "coding_style",
"description": "Stores coding style preferences, patterns, and team conventions learned from reviews",
"value": "Prefers functional programming patterns, strict error handling, comprehensive documentation",
"limit": 5000
},
{
"label": "project_context",
"description": "Contains project-specific context, architecture decisions, and technology stack information",
"value": "Rust web application using Axum framework, emphasizing performance and security",
"limit": 5000
}
]
# Create our intelligent code reviewer
agent = client.agents.create(
name="rust-code-reviewer",
memory_blocks=memory_blocks,
system="You are an expert code reviewer...",
model="openai/gpt-4o-mini",
embedding="openai/text-embedding-3-small"
)

The magic happens in those memory blocks. Unlike stateless systems, our agent maintains persistent context about coding preferences and project specifics.

Zoom image will be displayed

Here’s where the story gets interesting for Rust developers. While our intelligent agent runs on Letta’s Python-based framework, we can interact with it seamlessly from Rust applications using a deployment bridge. Using a framework agnostic platform RunAgent, we can serve our Letta-based code reviewer and consume it from Rust:

First, let’s look at how to organize your code reviewer project:

code-reviewer/
├── code-reviewer/
│ ├── agent.py # Main Letta agent logic
│ ├── code_review_tools.py # Analysis functions
│ ├── runagent.config.json # Deployment configuration
│ └── requirements.txt # Python dependencies
| └── .env.example # Your OpenAI API
├── rust-client/
│ ├── Cargo.toml # Rust dependencies
│ ├── src/
│ │ └── main.rs # Rust integration code
│ └── examples/
│ └── code_review.rs # Usage examples
└── README.md

The deployment configuration (runagent.config.json) defines how your Letta agent becomes accessible:

{
"agent_name": "smart_code_reviewer",
"description": "AI-powered code reviewer with security analysis",
"framework": "letta",
"version": "1.0.0",
"agent_architecture": {
"entrypoints": [
{
"file": "agent.py",
"module": "letta_run",
"tag": "code_review"
},
{
"file": "agent.py",
"module": "letta_run_stream",
"tag": "code_review_stream",
"extractor": {
"tool_response": "$.tool_return",
"message": "$.content",
"tool_name": "$.tool_call.name",
"reasoning_content": "$.reasoning"
}
}
]
}
}

Entrypoints define how external systems can invoke specific functions or class within your AI agent. Each entrypoint maps to a Python function in your codebase and gets assigned a unique tag identifier.

Extractors are optional JSON path expressions that transform the raw agent response into a cleaner, structured format before returning it to the client.

When you call an agent through RunAgent:

  1. The tag routes to the specific module (function) in your file
  2. The function executes and returns raw output (often complex nested JSON)
  3. The extractor applies JSON path selectors to pull out specific fields
  4. Clean, structured data gets returned to your Rust client
"extractor": {
"tool_response": "$.tool_return", // Extracts tool execution results
"message": "$.content", // Pulls the main message content
"tool_name": "$.tool_call.name", // Identifies which tool was used
"reasoning_content": "$.reasoning" // Captures the agent's reasoning process
}

This means instead of receiving Letta’s full internal response object, your Rust code gets a clean structure with just the extracted fields you care about. Without extractors, you’d need to parse complex nested JSON manually in your Rust client — extractors handle this transformation automatically at the deployment layer.

Using RunAgent, we can serve our Letta-based code reviewer as a REST API:

# Navigate to your project
cd code-reviewer
# Install Python dependencies
pip install -r requirements.txt
# Start your Letta server (in another terminal)
letta server
# Deploy the agent as a service
runagent serve .

This creates a REST API endpoint that outputs something like:

🚀 Agent started successfully!
🆔 Agent ID: 355a44e4-c7a0-483b-85c8-80d9b676e293
🌐 URL: http://127.0.0.1:8450
📖 Docs: http://127.0.0.1:8450/docs

Your Rust Cargo.toml needs the RunAgent SDK:

[dependencies]
runagent = "0.1.1"
tokio = { version = "1.0", features = ["full"] }
serde_json = "1.0"
futures = "0.3"

Now from your Rust application, you can interact with the intelligent code reviewer:

use runagent::client::RunAgentClient;
use serde_json::json;
use std::fs;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connect to your deployed Letta agent
let client = RunAgentClient::new(
"355a44e4-c7a0-483b-85c8-80d9b676e293", // Agent ID from deployment
"code_review",
true // local deployment
).await?;

// Read Rust code to review
let rust_code = fs::read_to_string("src/main.rs")?;

// Send for intelligent review
let response = client.run(&[
("code", json!(rust_code)),
("language", json!("rust")),
("focus_area", json!("security"))
]).await?;

println!("🔍 Code Review Results:");
println!("{}", response);
Ok(())
}

For comprehensive analysis of larger codebases, you can use streaming:

use futures::StreamExt;let mut stream = client.run_stream(&[
("code", json!(large_rust_file)),
("language", json!("rust")),
("analysis_type", json!("comprehensive"))
]).await?;
println!("📡 Streaming analysis...");
while let Some(chunk_result) = stream.next().await {
match chunk_result {
Ok(chunk) => print!("{}", chunk),
Err(e) => println!("Stream error: {}", e),
}
}

Letta’s streaming capabilities integrate seamlessly with RunAgent’s WebSocket infrastructure, enabling real-time code analysis feedback. As your agent processes large files or performs complex analysis, you receive immediate updates through native streaming APIs. This same streaming architecture works consistently across all supported frameworks — whether you’re using Letta’s memory-driven analysis, LangGraph’s workflow steps, or CrewAI’s multi-agent discussions.

After setting up the deployment and Rust client, navigate to your project’s rust-client directory and run:

cd rust-client
cargo run

This will start your Rust application and display a local URL (typically http://localhost:3001) where you can access the web interface. Open this link in your browser to interact with your intelligent code reviewer through a clean, responsive interface that streams real-time analysis as you paste or upload code files.

Zoom image will be displayed

One of the most compelling aspects of this approach is framework flexibility. While we’ve focused on Letta for its memory capabilities, the same deployment architecture supports multiple AI frameworks:

  • LangGraph for complex workflow orchestration
  • CrewAI for multi-agent code review teams
  • AutoGen for collaborative review processes
  • Custom frameworks tailored to specific needs

This unified approach is powered by RunAgent — an open-source platform that abstracts away deployment complexity across AI frameworks. With RunAgent, you write your agent logic once in Python using any framework (or take any open-source agent), then access it natively from Rust, JavaScript, Go, or Python through type-safe SDKs. Soon, RunAgent will integrate with Cursor as an MCP server, making agent file creation effortless with RunAgent config, directly from your IDE.

Whether you’re deploying a Letta memory agent, a LangGraph workflow, or a CrewAI team, the deployment command (runagent serve .) and integration patterns remain identical. This means you can choose the right AI framework for each specific use case while maintaining consistent deployment and integration patterns across your entire development toolchain.

For Rust developers, this translates to a single SDK that works with any AI framework — no need to learn different APIs or integration methods as you experiment with various agent architectures.

As software development evolves, AI is transforming code review. Traditional tools merely catch errors, but memory-enabled AI agents understand context, learn from past interactions, and provide personalized feedback. These stateful AI systems, like those built with Letta, remember your coding style and previous issues, offering insights that grow smarter over time. Imagine a code reviewer that evolves from a simple linter to an architectural advisor, from a bug detector to a mentorship system, continuously learning and adapting to your needs. With frameworks enabling such intelligent agents, the future of development tools is here, ready to elevate your coding experience. The choice is yours: how intelligent do you want your code review process to become?

Ready to build your own intelligent code reviewer? The complete implementation, including all analysis tools, deployment configurations, and Rust integration code, is available as an open-source project at:

RunAgent-Example

Clone the repository, follow the setup guide, and you’ll have a working intelligent code reviewer in minutes. Start with the basic setup and evolve it into the development companion your team deserves.

This gives readers a direct path to the working code while maintaining the article’s educational flow.

For Rust developers interested in exploring other AI frameworks through RunAgent deployment architecture, the integration patterns demonstrated here work seamlessly with LangChain, LangGraph, CrewAI, and custom implementations, giving you the flexibility to choose the right tool for each specific challenge.

This project builds upon the amazing work of the Letta team and the open-source AI community. Special thanks to:

Letta — The stateful agents framework with memory, reasoning, and context management that makes intelligent, persistent AI agents possible.

Read Entire Article