AI 에이전트 SDK 비교 분석

에이전트 SDK 삼국지

oxicode-sdk, Claude Agent SDK, LangChain — 세 프레임워크는 "에이전트를 만든다"는 같은 목표를 전혀 다른 방식으로 푼다. 누가 루프를 소유하는지, 툴을 누가 준비하는지, 안전장치를 SDK가 주는지 개발자가 짜야 하는지가 근본적으로 갈린다. 아키텍처와 강점 분야를 짚고, 챗봇과 코딩 에이전트를 각각 어떤 코드로 빚어내는지 실제 스니펫으로 비교한다.

oxicode-sdk· Rust · 멀티에이전트 런타임
Claude Agent SDK· TS/Python · 완성형 코딩 하네스
LangChain· Python 우선 · 조립식 오케스트레이션
01

한눈에 보기

언어, 진입점, 루프 소유권부터 이미 세 프레임워크의 철학이 갈린다.

항목 oxicode-sdk Claude Agent SDK LangChain / LangGraph
언어 · 패키지 Rust crate oxicode-sdk (crates.io) Python claude-agent-sdk · TS @anthropic-ai/claude-agent-sdk Python langchain + langgraph
설계 철학 전역 상태 없이, 빌더로 조립하는 멀티에이전트 런타임 Claude Code를 그대로 라이브러리화한 "완성형 하네스" 그래프로 상태 기계를 직접 설계하는 "조립식" 오케스트레이션
핵심 진입점 OxicodeBuilderAgentBuilderAgent query() 비동기 제너레이터 · ClaudeSDKClient create_agent() (LangGraph 위에서 동작) 또는 StateGraph
루프 소유권 SDK가 tool-calling 루프를 직접 구현·소유 SDK가 Claude Code의 루프를 그대로 캡슐화해 제공 개발자가 노드·엣지로 루프의 모양을 직접 정의
기본 툴 read/write/edit/bash/grep/find 내장 + trait 기반 커스텀 툴 + MCP 클라이언트 Read/Edit/Write/Bash/Glob/Grep/WebSearch 내장 + MCP + 서브에이전트 내장 툴 없음 — @tool로 직접 정의, 대신 통합 카탈로그가 방대함
권한 · 보안 Capability 기반 역할·감사 로그 (Authorizer, CapabilitySet) 다층 권한 모드(acceptEdits/bypassPermissions/plan) + Hooks SDK 차원의 권한 계층 없음 — 노드·툴 내부에서 직접 구현
멀티에이전트 AgentGroup(Pipeline/Parallel/Orchestrated) + MessageBus AgentDefinition 서브에이전트, 격리 컨텍스트 + 예산 캡 그래프 합성 · 멀티 에이전트 핸드오프 패턴을 직접 설계
관측성 Tracer/AuditLog/CostTracker SDK 내장 턴·트리 단위 비용·사용량 자동 집계 LangSmith(별도 상용 제품) 연동이 표준 경로
배포 형태 단일 네이티브 바이너리로 컴파일 Node/Python 런타임 + 번들된 Claude Code 바이너리 Python 런타임, 다수의 서드파티 의존성
생태계 신생 · 틈새 프로젝트 (pi의 Rust 포트) Anthropic 공식, Claude Code와 동일 코드베이스 가장 오래되고 큰 생태계, 멀티 LLM 프로바이더 지원
02

아키텍처 뜯어보기

세 SDK가 실제로 어떤 레이어와 빌딩 블록으로 이루어져 있는지.

oxicode-sdk

Rust workspace

5개 크레이트로 나뉜 워크스페이스. 각 크레이트는 독립적으로도 배포된다.

oxicode-ai (8개 프로바이더 통합 LLM API) → oxicode-agent (tool-calling 루프·이벤트·MCP·압축) → oxicode-sdk (멀티에이전트 빌더) → oxicode-cli
  • 전역 상태 없음Oxicode 인스턴스마다 프로바이더·모델 레지스트리가 독립적이라 한 프로세스 안에 여러 엔진이 안전하게 공존한다.
  • 빌더 체인이 곧 설정OxicodeBuilder::new().with_builtins().build() 로 엔진을 만들고, .agent(config).workspace(dir).coding_tools().build() 로 에이전트를 조립한다.
  • Coordination 모듈WorkQueue(우선순위 작업 큐), SharedMemory(낙관적 락 공유 메모리), Consensus(투표 합의)로 에이전트 군집을 실제 분산 시스템처럼 다룬다.
  • Capability 기반 보안 — deny-by-default. Authorizer.define_role()로 역할을 정의하고 에이전트에 바인딩한다.

Claude Agent SDK

harness

Claude Code를 구동하는 바로 그 루프를 라이브러리로 노출한다.

query() → SystemMessage(init) → AssistantMessage → (툴 실행) → UserMessage → … 반복 → ResultMessage
  • 6단계 권한 파이프라인 — hooks → deny rules → ask rules → permission mode → allow rules → callback 순으로 모든 툴 호출을 통과시킨다.
  • Hooks가 진짜 콜백PreToolUse/PostToolUse/Stop/PreCompact 등은 프롬프트에 섞이지 않는 프로세스 내 콜백이라 토큰을 쓰지 않는다.
  • 서브에이전트AgentDefinition으로 정의하고 Agent 툴로 호출. 격리된 컨텍스트에서 실행되고 부모에는 요약만 반환되며, 동시 실행 수·예산은 옵션으로 캡을 건다.
  • MCP 1급 지원 — stdio · HTTP/SSE · 인프로세스 SDK 서버 세 가지 트랜스포트를 모두 지원한다.

LangChain / LangGraph

graph runtime

LangChain(체인·통합) 위에 LangGraph(오케스트레이션 런타임)가 얹힌 2계층 구조.

StateGraph(State) + add_node/add_edge/add_conditional_edges → compile() → invoke/stream
  • 노드 = 함수, 엣지 = 전이 — 결정론적 스텝과 에이전틱(LLM 판단) 스텝을 한 그래프 안에 자유롭게 섞을 수 있다.
  • create_agent()는 LangGraph 위에 ReAct 패턴을 미리 얹어둔 헬퍼로, 그래프를 직접 설계하지 않아도 되는 지름길이다.
  • Checkpointer로 영속성InMemorySaver 등으로 thread_id 단위 대화 상태를 저장·재개한다. 사람이 개입하는(HITL) 승인 플로우에 필수적이다.
  • 통합 카탈로그 — 벡터스토어·문서로더·리트리버 등 수백 개 서드파티 연동이 핵심 자산이다.

그래프로 연결한다는 건 어떤 느낌인가

worked example

코드를 고치고 테스트하고 사람 승인을 받고 배포하는, 작은 그래프 하나로 실제 흐름을 본다.

START 통과 승인 END 실패 반려 plan 계획 수립 code 코드 수정 run_tests 테스트 실행 review 승인 대기 deploy 배포 실행
run_tests가 실패하면 code로, review에서 반려되면 다시 code로 — 처음(plan)으로 안 돌아가고 그래프 위의 서로 다른 지점으로 되돌아간다. 이게 "루프"와 "그래프"의 실질적 차이다.
LLM 노드 (plan, code) 결정론적 함수 (run_tests, deploy) 사람 개입 · interrupt() (review)
coding_review_graph.py
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.types import interrupt, Command
from langgraph.checkpoint.memory import InMemorySaver

class State(TypedDict):
    task: str
    test_result: str
    approved: bool

def plan(state: State) -> dict:
    ...  # LLM 호출: 무엇을 바꿀지 결정

def code(state: State) -> dict:
    ...  # LLM + 파일 편집 툴 호출

def run_tests(state: State) -> dict:
    result = subprocess.run(["pytest"], capture_output=True)
    return {"test_result": "pass" if result.returncode == 0 else "fail"}

def review(state: State) -> dict:
    decision = interrupt("이 변경을 배포해도 될까요?")  # 여기서 그래프가 실제로 멈춘다
    return {"approved": decision == "yes"}

def deploy(state: State) -> dict:
    ...  # 배포 스크립트 실행

builder = StateGraph(State)
for name, fn in [("plan", plan), ("code", code), ("run_tests", run_tests),
                 ("review", review), ("deploy", deploy)]:
    builder.add_node(name, fn)

builder.add_edge(START, "plan")
builder.add_edge("plan", "code")
builder.add_edge("code", "run_tests")

# 여기가 핵심 — 다음 노드가 상태에 따라 갈린다, 늘 같은 곳으로 돌아가지 않는다
builder.add_conditional_edges("run_tests",
    lambda s: "review" if s["test_result"] == "pass" else "code")
builder.add_conditional_edges("review",
    lambda s: "deploy" if s["approved"] else "code")
builder.add_edge("deploy", END)

graph = builder.compile(checkpointer=InMemorySaver())
config = {"configurable": {"thread_id": "fix-auth-bug"}}

graph.invoke({"task": "Fix the auth bug"}, config)
# review 노드의 interrupt()에서 실행이 그대로 멈춘다

graph.invoke(Command(resume="yes"), config)
# 사람이 승인하면, 멈췄던 바로 그 지점부터 이어서 재개된다

포인트 — oxicode-sdk와 Claude Agent SDK의 루프였다면 "다음에 뭘 할지"는 항상 LLM이 툴을 골라 결정하고, 실패해도 결국 같은 모양의 루프 처음으로 돌아갑니다. 여기서는 run_tests·deploy처럼 LLM이 전혀 아닌 결정론적 함수가 노드로 나란히 앉아 있고, 실패·반려는 각각 다른 지점(둘 다 code지만 경로가 다름)으로 돌아가며, review는 그냥 훅이 아니라 interrupt()로 실행 자체를 통째로 멈췄다가 프로세스가 재시작돼도 정확히 그 지점부터 재개됩니다. "루프를 반복한다"가 아니라 "그래프 위를 상태에 따라 이동한다"는 게 정확히 이 느낌입니다.

03

어디에 강한가

같은 "에이전트 SDK"라는 이름 아래 실제로 잘하는 일은 서로 겹치지 않는다.

oxicode-sdk

  1. 터미널 네이티브 코딩 에이전트실제 프로덕트(oxicode CLI)가 이 SDK로 만들어졌다. 스스로를 위해 쓴 코드라 신뢰도가 검증돼 있다.
  2. 분산 시스템급 멀티에이전트 조율WorkQueue·SharedMemory·Consensus로 에이전트 군집을 실제 분산 워커처럼 다룬다.
  3. 네이티브 바이너리 성능Python/Node 런타임이 필요 없다. .so/.dylib/.wasm 플러그인으로 확장한다.
  4. 내장 관측성Tracer·AuditLog·CostTracker가 부가 옵션이 아니라 SDK 1급 모듈이다.

Claude Agent SDK

  1. 완성형 코딩 에이전트 하네스Claude Code와 동일한 루프이므로 파일 편집·bash 실행·검증 사이클이 이미 실전 검증돼 있다.
  2. 세밀한 권한 스코프경로별(Edit(path)), 명령어별(Bash(ls *)) 룰까지 지정할 수 있다.
  3. MCP로 즉시 확장GitHub·Slack·DB를 커스텀 글루 코드 없이 붙인다.
  4. 세션 재개 & 자동 압축session_id로 프로세스 재시작 후에도 대화를 이어가고, 컨텍스트는 자동으로 압축·캐싱된다.

LangChain

  1. RAG 파이프라인문서로더·임베딩·벡터스토어 통합 수가 압도적으로 많다 — 역사적으로 가장 검증된 영역.
  2. 멀티 LLM 유연성OpenAI·Anthropic·Gemini·로컬 모델을 문자열 하나로 교체할 수 있다.
  3. 복잡한 분기 워크플로우StateGraph로 결정론적 단계와 에이전틱 단계를 명시적으로 섞어 승인 플로우 같은 걸 설계하기 좋다.
  4. 생태계 규모가장 크고 오래된 커뮤니티, LangSmith로 트레이싱·평가를 상용 지원한다.
04

코드로 보는 챗봇 만들기

툴이 필요 없는 순수 대화형 챗봇 — 세 SDK가 "아무것도 안 붙인 최소 구성"을 어떻게 다르게 만드는지.

examples/minimal.rs
// oxicode-sdk 공식 예제 그대로 — 툴을 하나도 붙이지 않은
// AgentBuilder가 그 자체로 순수 챗봇이 된다.
use oxicode_sdk::prelude::*;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let oxicode = OxicodeBuilder::new().with_builtins().build();

    let agent = oxicode
        .agent(AgentConfig {
            model_id: "anthropic/claude-sonnet-4-20250514".into(),
            ..Default::default()
        })
        .system_prompt("You are a helpful assistant. Respond briefly.")
        .build()?;

    let (response, _events) = agent.run("What is 2+2?".into()).await?;
    println!("{}", response.content);
    Ok(())
}

포인트.coding_tools()를 호출하지 않으면 AgentBuilder는 그대로 툴 없는 순수 대화 에이전트가 된다. 챗봇을 위한 별도 타입이 없고, 코딩 에이전트와 같은 빌더에서 "무엇을 안 붙이느냐"로 갈린다.

chatbot.py
# allowed_tools=[] 로 툴 접근을 명시적으로 비워야 진짜 챗봇이 된다.
# 기본값은 Claude Code의 전체 툴셋을 그대로 물려받기 때문이다.
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

async def main():
    async for message in query(
        prompt="What is 2+2?",
        options=ClaudeAgentOptions(
            allowed_tools=[],
            system_prompt="You are a helpful chatbot. Be conversational and warm.",
        ),
    ):
        if isinstance(message, ResultMessage):
            print(message.result)

asyncio.run(main())

포인트 — 챗봇에도 query()와 똑같은 에이전틱 루프가 돌아간다. 다만 allowed_tools를 비워 루프가 텍스트 한 번으로 즉시 끝나게 만드는 것. 멀티턴이 필요하면 ClaudeSDKClient로 세션을 유지한다.

chatbot.py
# 순수 챗봇이라면 create_agent()조차 필요 없다.
# LCEL로 prompt | model 파이프만 조립하면 끝 — 툴 호출 루프 자체가 없다.
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate

model = ChatAnthropic(model="claude-sonnet-4-20250514")
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful chatbot. Be conversational and warm."),
    ("human", "{input}"),
])

chain = prompt | model
print(chain.invoke({"input": "What is 2+2?"}).content)

포인트 — LangChain은 "에이전트"와 "체인"을 명확히 구분한다. 챗봇처럼 툴 호출이 필요 없는 경우 create_agent·StateGraph를 아예 건너뛰고 LCEL 파이프만으로 끝낼 수 있다는 게 다른 두 SDK와의 차이다.

05

코드로 보는 코딩 에이전트 만들기

파일을 읽고 고치고 셸을 실행하는 자율 에이전트 — 여기서 세 SDK의 설계 철학 차이가 가장 뚜렷하게 드러난다.

coding_agent.rs
use oxicode_sdk::prelude::*;

let oxicode = OxicodeBuilder::new()
    .with_builtins()
    .api_key("anthropic", "sk-ant-...")
    .build();

let agent = oxicode.agent(AgentConfig {
        model_id: "anthropic/claude-sonnet-4-20250514".into(),
        max_iterations: 20,
        ..Default::default()
    })
    .workspace("/my/project")
    .coding_tools()          // read/write/edit/bash/grep/find 일괄 부착
    .coding_capabilities()   // 워크스페이스 범위로 권한 자동 스코프
    .system_prompt("You are a senior Rust developer.")
    .build()?;

let (response, _events) = agent.run("Refactor main.rs".into()).await?;

// 리뷰어 + 테스터를 동시에 돌리는 멀티에이전트 그룹도 빌더 한 줄
let group = AgentGroup::new(GroupStrategy::Parallel { max_concurrency: 4 })
    .agent(Arc::new(reviewer))
    .agent(Arc::new(tester));
let result = group.run("Review this codebase.".into()).await?;

포인트.coding_tools() 한 줄이 read/write/edit/bash/grep/find를 전부 붙이고, .coding_capabilities()가 그 워크스페이스 경로로 권한을 자동으로 좁힌다. 멀티에이전트 병렬 실행도 AgentGroup 빌더 체인에 그대로 이어붙인다.

coding-agent.ts
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Find and fix all failing tests in the auth module",
  options: {
    allowedTools: ["Read", "Edit", "Bash", "Glob", "Grep"],
    permissionMode: "acceptEdits",   // 파일 편집은 자동 승인
    maxTurns: 50,
    hooks: {
      PreToolUse: async (event) => {
        if (event.toolName === "Bash" && event.input.command?.includes("rm -rf")) {
          return { allow: false, reason: "Destructive command blocked" };
        }
        return { allow: true };
      },
    },
    agents: {
      "code-reviewer": {
        description: "Security and quality reviewer",
        prompt: "You are a code review expert...",
        tools: ["Read", "Grep", "Glob"],
        model: "opus",
      },
    },
  },
})) {
  if (message.type === "result") {
    console.log(`Cost: $${message.total_cost_usd}, Turns: ${message.num_turns}`);
  }
}

포인트permissionMode, hooks, agents(서브에이전트) 세 옵션이 실질적으로 제품의 안전장치와 확장성을 결정한다. 이 루프 자체는 Claude Code가 실전에서 쓰는 것과 동일하다.

coding_agent.py
from langchain.agents import create_agent
from langchain.tools import tool
from langgraph.checkpoint.memory import InMemorySaver
import subprocess

# 파일시스템 · 셸 툴은 LangChain이 대신 만들어주지 않는다 — 직접 정의한다.
@tool
def read_file(path: str) -> str:
    """Read a file's contents."""
    return open(path).read()

@tool
def run_shell(command: str) -> str:
    """Run a shell command and return its output."""
    return subprocess.run(command, shell=True, capture_output=True, text=True).stdout

agent = create_agent(
    model="anthropic:claude-sonnet-4-20250514",
    tools=[read_file, run_shell],
    system_prompt="You are a senior developer. Follow best practices.",
    checkpointer=InMemorySaver(),   # thread_id 단위로 대화 상태 재개
)

config = {"configurable": {"thread_id": "fix-auth-tests"}}
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Find and fix all failing tests in the auth module"}]},
    config=config,
)

포인트 — 파일 읽기·셸 실행 툴도, 위험 명령 차단 같은 권한 로직도 전부 개발자가 @tool과 그래프 노드 안에 직접 작성한다. 이 보일러플레이트를 줄이려고 planning·파일시스템·서브에이전트를 미리 조립해 둔 deepagents 패키지가 별도로 존재한다.

06

언제 무엇을 쓸까

세 SDK는 경쟁 관계라기보다 서로 다른 문제를 풀도록 태어났다.

oxicode-sdk

Rust 네이티브 앱·CLI·데몬에 에이전트를 내장해야 하거나, 여러 에이전트를 실제 작업 큐·합의 알고리즘으로 조율해야 하거나, 단일 바이너리로 배포하고 싶을 때.

Claude Agent SDK

Claude Code와 동급의 자율 코딩 에이전트를 가장 빠르게 제품화하고 싶을 때, 세밀한 권한·훅으로 엔터프라이즈 가드레일이 필요할 때, MCP로 외부 툴을 빠르게 붙여야 할 때.

LangChain / LangGraph

RAG·문서 검색이 핵심 기능일 때, 여러 LLM 프로바이더를 유연하게 교체해야 할 때, 승인 단계가 섞인 복잡한 분기 워크플로우를 그래프로 명시적으로 설계하고 싶을 때.

07

정면 승부: oxicode-sdk vs LangChain

Claude Agent SDK를 빼고 둘만 놓고, 실제 기능으로 어디가 유리한지 두 시나리오로 뜯어본다.

구조가 닮아 보이는 이유 — oxicode-sdk와 LangChain은 "루프의 모양"에서는 다르다(oxicode는 여전히 정해진 tool-calling 루프를 돈다). 하지만 "코드를 어떻게 조립하는가"는 실제로 닮았다. 둘 다 Security/Coordination/Observabilitytools/retriever/checkpointer처럼 독립된 모듈을 낱개로 import해서 직접 쌓는 라이브러리 스타일이다. 옵션 객체 하나로 거의 다 결정되는 Claude Agent SDK의 query()와는 이 지점에서 갈린다.

시나리오 A — 코딩 에이전트

파일 편집 · bash 실행 · 반복 검증
항목 oxicode-sdk LangChain / LangGraph
파일 · bash 툴 .coding_tools() 한 줄로 즉시 사용 없음 — @tool로 직접 작성
권한 스코프 .coding_capabilities()로 워크스페이스에 자동 스코프 없음 — 노드·툴 안에 직접 구현
배포 형태 단일 네이티브 바이너리 Python 런타임 + 의존성 다수
복잡한 분기(재시도·승인 게이트) 불가 — workflow DSL이 조건 분기·사이클 미지원, 직접 구현 필요 StateGraph + interrupt()로 정확히 이 용도
대규모 코드베이스 탐색 grep/glob 중심, semantic 검색 없음 벡터스토어 기반 semantic 코드 검색 turnkey
멀티에이전트 협업 AgentGroup::Parallel + WorkQueue/SharedMemory로 실제 분산 워커처럼 직접 그래프로 설계해야 함
프로젝트 장기 기억 with_memory_backend()memory_recall/memory_retain 툴 자동 등록 checkpointer는 실행 상태 재개용 — 장기 기억엔 별도 벡터스토어 필요

결론 — 파일 고치고 커맨드 실행하는 표준적인 코딩 에이전트라면 oxicode-sdk 쪽이 손이 훨씬 덜 간다. 승인 게이트가 낀 복잡한 재시도 워크플로우가 필요하면 LangGraph 없이는 표현 자체가 안 된다.

시나리오 B — RAG 기반 챗봇

문서 검색 · 근거 기반 답변

oxicode-sdk에는 oxicode-mnemopi라는 로컬 SQLite 벡터 메모리 엔진이 따로 있다. EmbeddingProvider가 로컬 ONNX(완전 오프라인)와 원격 API 둘 다 지원하고, FTS5(키워드) + 벡터(의미) 하이브리드 검색에 MMR 재정렬까지 붙어 있다. AgentBuilder::with_memory_backend()를 부르면 memory_recall/memory_reflect/memory_retain/memory_edit 툴이 자동 등록되어 LLM이 스스로 기억·회상을 판단한다 — 생각보다 훨씬 붙어있는 시나리오다.

항목 oxicode-sdk (mnemopi) LangChain
임베딩 로컬 ONNX(오프라인) + 원격 API 둘 다 1급 지원 대부분 원격 API, 로컬도 가능하나 직접 연결
벡터 검색 SQLite 내장, 별도 서비스 불필요 — FTS5+벡터+MMR 하이브리드가 기본값 Pinecone/Chroma/Weaviate 등 수십 종, 대부분 외부 서비스 필요
문서 수집(파싱 · 청킹) 없음 — document loader · splitter 관련 코드 전무 핵심 자산 — 수백 종 로더·스플리터 지원
대규모 확장성 로컬 SQLite 한계 안에서 전용 벡터DB로 수평 확장, 엔터프라이즈 규모에 최적화
성격 세션·시간·개체(entities, triples) 중심의 "기억" 정적 문서 코퍼스 중심의 "검색"
에이전트 루프 통합 툴로 자동 등록, LLM이 스스로 기억·회상 결정 리트리버를 체인·그래프에 명시적으로 배선해야 함

결론 — "회사 문서 100개를 PDF로 넣고 그 안에서 답을 찾는" 고전적 RAG라면 파싱·청킹·외부 벡터DB 생태계가 있는 LangChain이 여전히 유리하다 — oxicode는 이 앞단을 아예 안 만들어놨다. 반대로 "대화하며 사용자를 알아가고 기억해서 다음에 써먹는" 개인화 챗봇이라면, 오히려 oxicode 쪽이 하이브리드 검색+MMR+엔티티 그래프까지 이미 배선된 채로 외부 서비스 하나 없이 단일 바이너리로 나온다.

코딩 에이전트는 oxicode-sdk가 우세, 정적 문서 기반 RAG는 LangChain이 우세, "기억하는 챗봇"이라는 제3의 영역에서는 의외로 oxicode가 선전한다.