Fully Native ADK-Rust Implementation

Meet Ralph

An autonomous agent loop that runs continuously until all PRD items are complete. No bash scripts needed — everything runs within ADK-Rust.

Architecture Overview

Built entirely in Rust using ADK-Rust's native loop capabilities

Loop Agent
Orchestrator
Worker Agent
Task Executor
PRD Tool
Task Manager
Git Tool
Version Control
Test Tool
Quality Check
1

Loop Agent

Main orchestrator that cycles through tasks, delegates work, and tracks overall progress.

2

Worker Agent

Executes individual tasks with focused context. Implements, tests, and commits changes.

3

Custom Tools

Native ADK-Rust tools for Git, file operations, quality checks, and PRD management.

Key Capabilities

Ralph showcases the full power of ADK-Rust for autonomous agent development

🔄

Autonomous Loop

Continuous execution until all PRD items complete. Native loop tool integration without bash scripts.

🤖

Multi-Agent Coordination

Loop Agent orchestrates Worker Agents. Each agent specializes in its role for maximum effectiveness.

🛠️

Custom Tools

Git, file operations, quality checks, PRD management - all built as native ADK-Rust tools.

📋

PRD-Driven

JSON-based task management with user stories, acceptance criteria, and pass/fail tracking.

Quality Gates

Automated cargo check, test, clippy, and fmt verification before any commit.

💾

State Persistence

Git commits, progress logs, and AGENTS.md updates provide complete memory and auditability.

Implementation Details

Clean, idiomatic Rust code that leverages ADK-Rust's full feature set

use serde::{Deserialize, Serialize};
use std::fs;
use anyhow::Result;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Prd {
    pub project: String,
    pub branch_name: String,
    pub description: String,
    pub user_stories: Vec<UserStory>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UserStory {
    pub id: String,
    pub title: String,
    pub description: String,
    pub acceptance_criteria: Vec<String>,
    pub priority: u32,
    pub passes: bool,
    #[serde(default)]
    pub notes: String,
}

impl Prd {
    pub fn load(path: &str) -> Result<Self> {
        let content = fs::read_to_string(path)?;
        let prd: Prd = serde_json::from_str(&content)?;
        Ok(prd)
    }
    
    pub fn save(&self, path: &str) -> Result<()> {
        let content = serde_json::to_string_pretty(self)?;
        fs::write(path, content)?;
        Ok(())
    }
    
    pub fn get_next_task(&self) -> Option<&UserStory> {
        self.user_stories
            .iter()
            .filter(|story| !story.passes)
            .min_by_key(|story| story.priority)
    }
    
    pub fn mark_complete(&mut self, task_id: &str) -> Result<()> {
        if let Some(story) = self.user_stories
            .iter_mut()
            .find(|s| s.id == task_id) 
        {
            story.passes = true;
        }
        Ok(())
    }
    
    pub fn is_complete(&self) -> bool {
        self.user_stories.iter().all(|story| story.passes)
    }
    
    pub fn stats(&self) -> (usize, usize) {
        let complete = self.user_stories
            .iter()
            .filter(|s| s.passes)
            .count();
        let total = self.user_stories.len();
        (complete, total)
    }
}

Project Structure

A clean, modular organization that separates agents, tools, and models for easy maintenance and extension.

ralph/
├── Cargo.toml                # Ralph agent config
├── src/
│   ├── main.rs               # Entry point
│   ├── agents/
│   │   ├── mod.rs
│   │   ├── loop_agent.rs     # Main orchestrator
│   │   └── worker_agent.rs   # Task executor
│   ├── tools/
│   │   ├── mod.rs
│   │   ├── git_tool.rs       # Git operations
│   │   ├── file_tool.rs      # File manipulation
│   │   ├── test_tool.rs      # Quality checks
│   │   └── prd_tool.rs       # PRD management
│   └── models/
│       ├── prd.rs            # PRD data structures
│       └── config.rs         # Configuration
├── prd.json                  # Task list
└── progress.txt              # Learnings log

Native vs Bash

Why build autonomous agents natively in Rust instead of orchestrating with shell scripts?

AspectBashNative
ImplementationShell script + ADK-RustPure Rust
Type SafetyRuntimeCompile-time
Error HandlingExit codesResult<T, E>
ConcurrencySequentialAsync/await
Tool IntegrationShell commandsNative ADK-Rust tools
DebuggingLog filesTracing + structured logging
PerformanceProcess spawning overheadZero-cost abstractions
Memory SafetyManual managementGuaranteed by compiler
TestingIntegration tests onlyUnit + integration tests

Ready to Build Your Own Ralph?

Explore the full source code, customize it for your use case, or use it as inspiration for your own autonomous agent systems.

ADK-Rust | بناء وكلاء ذكاء اصطناعي قوية في Rust