소개합니다: Ralph
PRD의 모든 항목이 완료될 때까지 계속 실행되는 자율 에이전트 루프입니다. Bash 스크립트 없이 모든 작업이 ADK-Rust 안에서 실행됩니다.

실시간 ADK-Ralph v2 데모
Ralph에게 작은 제품 하나를 만들어 달라고 요청하기
이것은 실제 Rust 바이너리를 실행합니다. PRD 에이전트는 하나의 사용자 스토리를 정의하고, 아키텍트 에이전트는 설계 및 작업 계획을 만들며, Ralph Loop 에이전트는 격리된 작업 공간에서 프로젝트를 작성하고 검증합니다.
01 · PRD Agent
제품 정의
02 · Architect Agent
시스템 설계
03 · Ralph Loop Agent
빌드 및 검증
하나의 프로젝트 · 세 번의 구현 반복 · 8분 제한 · 전달 후 임시 파일 삭제
실제 실행이 여기에 표시됩니다.
에이전트 단계, 도구 활동, 품질 검사 및 Ralph가 반환하는 파일을 확인할 수 있습니다.
아키텍처 개요
ADK-Rust의 네이티브 루프 기능을 사용해 전부 Rust로 구축
루프 에이전트
주 오케스트레이터가 작업을 순회하고 업무를 위임하며 전체 진행 상황을 추적합니다.
작업 에이전트
집중된 컨텍스트로 개별 작업을 실행하고 변경 사항을 구현, 테스트, 커밋합니다.
사용자 지정 도구
Git, 파일 작업, 품질 검사, PRD 관리를 위한 네이티브 ADK-Rust 도구입니다.
핵심 기능
Ralph는 자율 에이전트 개발을 위한 ADK-Rust의 주요 기능을 보여줍니다
자율 루프
모든 PRD 항목이 완료될 때까지 계속 실행합니다. Bash 스크립트 없이 루프 도구를 네이티브로 통합합니다.
멀티 에이전트 협업
루프 에이전트가 작업 에이전트를 조율합니다. 각 에이전트는 자신의 역할에 집중해 효율적으로 작업합니다.
사용자 지정 도구
Git, 파일 작업, 품질 검사, PRD 관리를 모두 네이티브 ADK-Rust 도구로 구현했습니다.
PRD 기반
사용자 스토리, 승인 기준, 통과/실패 추적을 포함한 JSON 기반 작업 관리입니다.
품질 게이트
각 커밋 전에 cargo check, test, clippy, fmt를 자동으로 검증합니다.
상태 영속성
Git 커밋, 진행 로그, AGENTS.md 업데이트로 전체 컨텍스트와 감사 가능성을 제공합니다.
구현 세부 정보
ADK-Rust의 전체 기능을 활용하는 깔끔하고 자연스러운 Rust 코드
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)
}
}프로젝트 구조
에이전트, 도구, 모델을 분리한 깔끔한 모듈 구조로 유지보수와 확장이 쉽습니다.
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
네이티브 구현과 Bash
왜 셸 스크립트로 조율하는 대신 Rust에서 자율 에이전트를 직접 구축할까요?
| 비교 항목 | Bash | 네이티브 |
|---|---|---|
| 구현 | 셸 스크립트 + ADK-Rust | 순수 Rust |
| 타입 안전성 | 런타임 | 컴파일 시점 |
| 오류 처리 | 종료 코드 | Result<T, E> |
| 동시성 | 순차 실행 | Async/await |
| 도구 통합 | 셸 명령 | 네이티브 ADK-Rust 도구 |
| 디버깅 | 로그 파일 | 트레이싱 + 구조화 로그 |
| 성능 | 프로세스 생성 오버헤드 | 제로 코스트 추상화 |
| 메모리 안전성 | 수동 관리 | 컴파일러가 보장 |
| 테스트 | 통합 테스트만 | 단위 테스트 + 통합 테스트 |
나만의 Ralph를 만들어 보시겠어요?
전체 소스 코드를 살펴보고 사용 사례에 맞게 수정하거나, 자체 자율 에이전트 시스템을 만드는 데 참고하세요.