<div align="center">
⚠️ 사용 중단됨 — 더 이상 유지보수되지 않습니다.
이 프로젝트는 공식 A2A Rust SDK인 github.com/a2aproject/a2a-rs로 대체되었습니다.
PS: 저희는 멀티 에이전트 환경을 위한 음성 클라이언트를 구축하고 있습니다 — 초기 컨셉은 agents.sh에서 확인하실 수 있습니다.
</div
<br>
<div style="text-align: center;">
<div class="centered-logo-text-group">
<img src="https://raw.githubusercontent.com/agents-sh/radkit/HEAD/docs/src/assets/logo.svg" alt="RadKit Logo" width="100">
<h1>Radkit - Rust 에이전트 개발 키트</h1>
</div>
</div>
[A2A Protocol] 지원을 통해 안정적인 AI 에이전트 시스템을 구축하기 위한 Rust SDK.
Radkit은 무엇보다도 개발자 경험과 제어권을 우선시합니다.
개발자는 에이전트의 동작, 실행 흐름, 컨텍스트 관리 및 상태에 대한 완전한 통제권을 유지할 수 있습니다.
라이브러리가 추상화(abstraction)를 제공하지만, 필요할 때 언제든지 개발자는 더 낮은 수준의 API로 내려갈 수 있습니다.
Crates.io
Documentation
License
기능 (Features)
- A2A Protocol 우선 지원 - 에이전트 간(Agent-to-Agent) 통신 표준에 대한 네이티브 지원
- 통합 LLM 인터페이스 - Anthropic, OpenAI, Gemini, Grok, DeepSeek을 위한 단일 API 제공
- 도구 실행 (Tool Execution) - 멀티 턴 루프 및 상태 관리를 통한 자동 도구 호출
- 구조화된 출력 (Structured Outputs) - JSON Schema를 사용한 타입 안전 디시리얼라이제이션(deserialization)
- 타입 안정성 (Type Safety) - 신뢰성과 정확성을 위해 Rust의 타입 시스템 활용
설치 (Installation)
radkit을 Cargo.toml에 추가하세요.
기본 설정 (Default, 최소 구성)
LlmFunction 및 LlmWorker와 같은 핵심 타입과 헬퍼를 에이전트 서버 런타임 없이 사용하려면:
[dependencies]
radkit = "0.0.4"
tokio = { version = "1", features = ["rt-multi-thread", "sync", "net", "process", "macros"] }
...
에이전트 서버 런타임 사용 시 (With Agent Server Runtime)
런타임 서버 핸들(runtime server handle)을 포함하고 전체 A2A 에이전트 서버 기능(네이티브 타겟에서)을 활성화하려면 runtime 기능을 활성화해야 합니다:
[dependencies]
radkit = { version = "0.0.4", features = ["runtime"] }
tokio = { version = "1", features = ["rt-multi-thread", "sync", "net", "process", "macros"] }
...
기능 플래그(Feature Flags)
Radkit은 타겟별로 선택할 수 있는 옵션 기능을 제공합니다:
runtime: 네이티브 런타임 핸들, HTTP 서버, 트레이싱(tracing) 및 로컬에서 A2A 규격 준수 에이전트를 실행하는 데 필요한 기타 종속성을 활성화합니다.
agentskill: SKILL.md 파일에서 스킬을 로드하기 위해 AgentSkillDef, include_skill!, 및 with_skill_dir를 활성화합니다. 기본적으로 macros 기능에 포함됩니다.
dev-ui: runtime을 기반으로 구축되며, 작업을 트리거하고 스트리밍 출력(streaming output)을 검사할 수 있는 인터랙티브 UI(네이티브 전용)를 제공합니다.
task-store-sqlite: 영구적인 작업(task), 이벤트 및 상태 저장을 위해 네이티브 SQLite 기반의 TaskStore를 활성화합니다.
핵심 개념(Core Concepts)
스레드(Thread) - 대화 컨텍스트(Conversation Context)
Thread는 시스템 프롬프트와 메시지 교환을 포함하여 LLM과의 전체 대화 기록을 나타냅니다.
use radkit::models::{Thread, Event};
...
타입 변환(Type Conversions):
let thread: Thread = "Hello".into();
...
콘텐츠(Content) - 멀티모달 메시지(Multi-Modal Messages)
Content는 텍스트, 이미지, 문서, 도구 호출(tool calls), 및 도구 응답을 지원하는 메시지의 페이로드(payload)를 나타냅니다.
use radkit::models::{Content, ContentPart};
use serde_json::json;
...
이벤트(Event) - 대화 메시지(Conversation Messages)
Event는 관련 역할(role)과 함께 대화의 단일 메시지를 나타냅니다.
use radkit::models::{Event, Role};
...
LLM 제공업체(LLM Providers)
Radkit은 통합된 인터페이스를 통해 여러 LLM 제공업체를 지원합니다.
Anthropic (Claude)
use radkit::models::providers::AnthropicLlm;
use radkit::models::{BaseLlm, Thread};
...
OpenAI (GPT)
use radkit::models::providers::OpenAILlm;
...
OpenRouter
OpenRouter는 단일 API 키 뒤에 호스팅된 Anthropic, Google, Cohere 및 기타 마켓플레이스 모델로 호출을 라우팅할 수 있는 OpenAI와 호환되는 엔드포인트를 제공합니다.
use radkit::models::providers::OpenRouterLlm;
...
Google Gemini
use radkit::models::providers::GeminiLlm;
...
Grok (xAI)
use radkit::models::providers::GrokLlm;
...
DeepSeek
use radkit::models::providers::DeepSeekLlm;
...
LlmFunction - 단순 구조화된 출력 (Simple Structured Outputs)
LlmFunction<T>는 도구 실행 없이 구조화되고 타입이 지정된 응답을 원할 때 완벽합니다.
기본 사용법 (Basic Usage)
use radkit::agent::LlmFunction;
use radkit::models::providers::AnthropicLlm;
use schemars::JsonSchema;
...
시스템 지침 포함 (With System Instructions)
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
struct CodeReview {
issues: Vec<String>,
...
다중 턴 대화 (Multi-Turn Conversations)
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
struct Answer {
response: String,
...
복잡한 데이터 구조 (Complex Data Structures)
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
struct Recipe {
name: String,
...
LlmWorker<T>는 LlmFunction에 자동 도구 호출(tool calling) 및 다중 턴 실행 루프를 추가합니다.
use radkit::agent::LlmWorker;
use radkit::models::providers::AnthropicLlm;
use radkit::tools::{tool, ToolResult};
...
use radkit::tools::tool;
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
...
도구는 ToolContext를 사용하여 호출 간에 상태(state)를 유지할 수 있습니다.
use radkit::tools::{tool, ToolContext};
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
...
A2A 에이전트(Agents)
Radkit은 Agent-to-Agent (A2A) 프로토콜을 준수하는 에이전트를 구축하기 위한 최고 수준의 지원(first-class support)을 제공합니다. 이 프레임워크는 코드가 컴파일되면 자동으로 A2A를 준수하도록 보장합니다.
A2A란 무엇인가요?
A2A 프로토콜은 AI 에이전트 간의 원활한 통신과 협업을 가능하게 하는 개방형 표준입니다. 이는 다음 기능을 제공합니다:
- Agent Card를 통한 표준화된 에이전트 검색(discovery)
- 작업 생명주기 관리 (제출됨, 진행 중, 완료 등)
- 입력이 필요한 상태를 가진 다중 턴 대화(multi-turn conversation)
- 장시간 실행되는 작업을 위한 스트리밍 지원
- 유형의 결과물(tangible outputs)을 위한 아티팩트 생성
A2A 에이전트 구축하기
radkit의 에이전트는 **스킬(skills)**로 구성됩니다. 각 스킬은 특정 기능을 처리하며, A2A 메타데이터를 제공하기 위해 #[skill] 매크로가 주석 처리되어 있습니다.
스킬 정의하기
use radkit::agent::{Artifact, LlmFunction, OnRequestResult, SkillHandler};
use radkit::errors::AgentError;
use radkit::macros::skill;
...
다중 턴 대화(Multi-Turn Conversations)
스킬은 필요할 때 사용자로부터 추가 입력을 요청할 수 있습니다. 다양한 입력 상태를 추적하려면 **슬롯 열거형(slot enums)**을 사용하세요:
use serde::{Deserialize, Serialize};
...
중간 업데이트 및 부분 아티팩트(Partial Artifacts)
장시간 실행되는 작업을 위해 진행 상황 업데이트와 부분 결과를 전송합니다:
#[cfg_attr(all(target_os = "wasi", target_env = "p1"), async_trait::async_trait(?Send))]
#[cfg_attr(
not(all(target_os = "wasi", target_env = "p1")),
...
에이전트 구성하기
use radkit::agent::{Agent, AgentDefinition};
use radkit::models::providers::AnthropicLlm;
use radkit::runtime::Runtime;
...
Radkit은 어떻게 A2A 준수를 보장하는가?
Radkit은 **컴파일 타임 보장(compile-time guarantees)**과 자동 프로토콜 매핑을 통해 A2A 준수를 보장합니다:
1. 타입 지정 상태 관리 (Typed State Management)
pub enum OnRequestResult {
InputRequired { message: Content, slot: SkillSlot },
Completed { message: Option<Content>, artifacts: Vec<Artifact> },
...
보장 사항: 유효한 A2A 태스크 상태만 반환할 수 있습니다. 유효하지 않은 상태는 컴파일되지 않습니다.
progress.send_update("Processing...").await?;
...
보장 사항: 실수로 종료 상태를 보내거나 중간 업데이트를 최종(final)으로 표시할 수 없습니다.
#[skill] 매크로는 다음을 자동으로 생성합니다:
- Agent Card용 A2A
AgentSkill 항목
input_modes/output_modes 기반의 MIME 유형 유효성 검사
- 적절한 스킬 검색 메타데이터
보장 사항: Agent Card는 항상 스킬 구현과 일관성을 유지합니다.
4. 프로토콜 유형 매핑 (Protocol Type Mapping)
프레임워크는 radkit 유형과 A2A 프로토콜 유형 간의 변환을 자동으로 처리합니다:
| Radkit 유형 | A2A 프로토콜 유형 |
|---|
Content | Message with Part[] |
| ... | |
| 보장 사항: 사용자는 A2A 프로토콜 유형을 직접 다룰 필요가 없습니다. 프레임워크가 올바른 직렬화(serialization)를 보장합니다. | |
5. 라이프사이클 강제 적용 (Lifecycle Enforcement)
progress.send_update("Working...").await?;
...
보장 사항: 타입 시스템이 컴파일 시간에 프로토콜 위반을 방지합니다.
이러한 보장 사항의 작동 방식 (How These Guarantees Work)
Radkit은 여러 타입 레벨 메커니즘을 통해 A2A 준수를 강제합니다:
1. 표현 불가능한 유효하지 않은 상태 (Unrepresentable Invalid States)
OnRequestResult 및 OnInputResult 열거형은 유효한 A2A 상태만을 변형(variant)으로 노출합니다. 타입 시스템이 허용하지 않기 때문에 유효하지 않은 상태를 구성하는 것이 불가능합니다:
Ok(OnRequestResult::Completed { message: None, artifacts: vec![] })
...
2. 제한된 메서드 API (Restricted Method APIs)
Methods like progress.send_update()는 내부적으로 최종 플래그 없이 TASK_STATE_WORKING을 사용하도록 하드코딩되어 있습니다. 이 API는 유효하지 않은 조합을 설정할 수 있는 매개변수를 노출하지 않습니다:
pub async fn send_update(&self, message: impl Into<Content>) -> Result<()> {
...
3. 반환 타입을 통한 관심사 분리(Separation of Concerns)
중간 업데이트는 ProgressSender 메서드를 통해 이루어지는 반면, 최종 상태는 오직 on_request()와 on_input_received()의 반환 값을 통해서만 설정됩니다. Rust의 타입 시스템에 의해 강제되는 이러한 아키텍처적 분리는 중간 업데이트를 실수로 최종 상태로 표시하거나 실행 도중에 터미널 상태를 전송하는 것을 불가능하게 만듭니다:
progress.send_update("Working...").await?;
...
4. 컴파일 타임 WASM 호환성(Compile-Time WASM Compatibility)
이 라이브러리는 조건부 컴파일과 compat 모듈을 사용하여 동일한 API 표면적을 유지하면서 WASM 이식성을 보장합니다. ?Send 트레이트 바운드는 대상에 따라 조건부로 적용됩니다:
#[cfg_attr(all(target_os = "wasi", target_env = "p1"), async_trait(?Send))]
#[cfg_attr(not(all(target_os = "wasi", target_env = "p1")), async_trait)]
이는 WASM 호환성이 컴파일 시점에 검증됨을 의미합니다. 에이전트가 네이티브 타겟용으로 컴파일되더라도 코드 변경 없이 WASM용으로 컴파일될 것입니다.
AgentSkills — 파일 기반 LLM 스킬
프로그래밍 방식의 Rust 스킬 외에도, radkit은 AgentSkills를 지원합니다. 이는 SKILL.md 파일에 완전히 정의되며, 별도의 Rust 코드가 필요하지 않습니다. LLM이 이 지침을 읽고 작업을 구동합니다.
AgentSkills는 AgentSkills 사양을 따릅니다. 스킬은 SKILL.md 파일을 포함하는 디렉토리입니다:
skills/
└── text-summariser/
└── SKILL.md
SKILL.md 파일은 YAML 프런트매터(frontmatter)와 마크다운 지침으로 구성됩니다:
name: text-summariser
description: 텍스트를 요약합니다. 사용자가 텍스트 요약 또는 압축을 요청할 때 사용하세요.
...
에이전트 스킬 등록 (Registering AgentSkills)
AgentSkill을 등록하는 방법은 두 가지가 있습니다:
컴파일 시간 임베딩 (Compile-time embedding) — SKILL.md 파일이 바이너리에 포함됩니다(예: include_str!). 시작 시 파일 시스템 I/O가 발생하지 않습니다. WASM에서 작동합니다.
use radkit::{agent::Agent, include_skill};
let agent = Agent::builder()
...
런타임 로딩 (Runtime loading) — 시작 시 디스크에서 SKILL.md 파일을 읽습니다. 재컴파일 없이 스킬을 업데이트하고 싶을 때 유용합니다.