Files
2nd/10_Wiki/Topics/Coding/AI_LangGraph_Agent_Frameworks.md
T
2026-05-09 21:08:02 +09:00

8.4 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
ai-langgraph-agent-frameworks Agent Frameworks — LangGraph / Mastra / CrewAI Coding draft B conceptual 2026-05-09 2026-05-09
ai
agent
framework
vibe-coding
language applicable_to
TS / Python
Backend
LangGraph
LangChain
Mastra
CrewAI
AutoGen
agent state
multi-agent

Agent Frameworks

Agent 구현 framework. LangGraph (state machine), Mastra (TS modern), CrewAI (multi-agent), AutoGen (Microsoft). 자체 implementation 도 좋음 — overkill 주의.

📖 핵심 개념

  • State graph: node + edge.
  • State persistence: checkpoint.
  • Streaming: 매 step 응답.
  • Human-in-the-loop: 중간 confirm.

💻 코드 패턴

LangGraph (Python / JS)

import { StateGraph, END, MemorySaver } from '@langchain/langgraph';
import { ChatAnthropic } from '@langchain/anthropic';
import { z } from 'zod';

const State = z.object({
  messages: z.array(z.any()),
  toolResults: z.record(z.string()).optional(),
});

const llm = new ChatAnthropic({ model: 'claude-opus-4-7' });

const graph = new StateGraph(State)
  .addNode('agent', async (state) => {
    const response = await llm.invoke(state.messages);
    return { messages: [...state.messages, response] };
  })
  .addNode('tools', async (state) => {
    const last = state.messages.at(-1);
    const results: Record<string, string> = {};
    for (const call of last.tool_calls ?? []) {
      results[call.id] = await executeTool(call.name, call.args);
    }
    return { 
      messages: [...state.messages, ...Object.entries(results).map(([id, content]) => ({ role: 'tool', tool_call_id: id, content }))],
      toolResults: results,
    };
  })
  .addEdge('__start__', 'agent')
  .addConditionalEdges('agent', (state) => {
    const last = state.messages.at(-1);
    return last.tool_calls?.length > 0 ? 'tools' : END;
  })
  .addEdge('tools', 'agent')
  .compile({ checkpointer: new MemorySaver() });

// 실행 (streaming)
const stream = await graph.stream(
  { messages: [{ role: 'user', content: '...' }] },
  { configurable: { thread_id: 'session-1' } }
);

for await (const chunk of stream) {
  console.log(chunk);
}

Mastra (TS modern)

import { Mastra } from '@mastra/core';

const mastra = new Mastra({
  agents: {
    weatherAgent: new Agent({
      name: 'Weather',
      instructions: 'Help users with weather questions.',
      model: openai('gpt-4o'),
      tools: { getWeather: weatherTool },
    }),
  },
  workflows: {
    customerSupport: workflow,
  },
});

const result = await mastra.agents.weatherAgent.generate('Tokyo weather?');

→ TS-first, modern, evals + observability built-in.

CrewAI (multi-agent, Python)

from crewai import Agent, Task, Crew

researcher = Agent(
    role='Senior Researcher',
    goal='Discover latest AI trends',
    backstory='You are an expert AI researcher...',
    tools=[search_tool],
)

writer = Agent(
    role='Tech Writer',
    goal='Write engaging articles',
)

task1 = Task(description='Research 2026 AI trends', agent=researcher)
task2 = Task(description='Write article based on research', agent=writer)

crew = Crew(agents=[researcher, writer], tasks=[task1, task2])
result = crew.kickoff()

→ Role-based multi-agent. 빠른 시작 but 정밀 제어 어려움.

Vercel AI SDK (modern, simple)

import { generateText, tool } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';

const result = await generateText({
  model: openai('gpt-4o'),
  tools: {
    getWeather: tool({
      description: 'Get weather',
      parameters: z.object({ city: z.string() }),
      execute: async ({ city }) => fetchWeather(city),
    }),
  },
  maxSteps: 5,  // tool loop
  prompt: 'Tokyo weather?',
});

console.log(result.text, result.toolCalls);

→ 단순 use case 강력.

State 영속 (LangGraph)

import { PostgresSaver } from '@langchain/langgraph-checkpoint-postgres';

const checkpointer = PostgresSaver.fromConnString('postgresql://...');
const graph = ...compile({ checkpointer });

// 같은 thread_id = 이어서
await graph.invoke(input, { configurable: { thread_id: userId } });

Human-in-the-loop

const graph = new StateGraph(State)
  .addNode('plan', planNode)
  .addNode('confirm', confirmNode)  // 사용자 승인 대기
  .addNode('execute', executeNode)
  .addEdge('plan', 'confirm')
  .addConditionalEdges('confirm', (state) => 
    state.approved ? 'execute' : END
  )
  .compile({
    interrupt_before: ['execute'],  // 항상 멈춤
  });

// 1. Plan 까지 실행
const state = await graph.invoke(input, config);

// 2. UI 가 사용자 confirm
if (await askUser(state.plan)) {
  // 3. 이어서 실행
  await graph.invoke(null, { ...config, recursionLimit: 10 });
}

Streaming + tools

const stream = await graph.streamEvents(input, {
  ...config,
  version: 'v2',
});

for await (const event of stream) {
  if (event.event === 'on_chat_model_stream') {
    process.stdout.write(event.data.chunk.content);
  }
  if (event.event === 'on_tool_start') {
    console.log('\nTool:', event.name);
  }
}

자체 implementation (가벼운)

class Agent {
  private messages: Message[] = [];
  private maxIters = 10;
  
  constructor(
    private llm: LLM,
    private tools: Tool[],
    private systemPrompt: string,
  ) {}
  
  async run(userMsg: string): Promise<string> {
    this.messages.push({ role: 'user', content: userMsg });
    
    for (let i = 0; i < this.maxIters; i++) {
      const r = await this.llm.chat({
        system: this.systemPrompt,
        messages: this.messages,
        tools: this.tools,
      });
      
      this.messages.push({ role: 'assistant', content: r.content });
      
      if (r.stopReason === 'end_turn') return r.text;
      
      if (r.toolCalls) {
        const results = await Promise.all(
          r.toolCalls.map(call => this.executeTool(call))
        );
        this.messages.push(...results.map(toToolResult));
      }
    }
    
    throw new Error('max iters');
  }
}

→ 위 AI_Function_Calling_Deep 가 baseline.

Observability

// LangSmith / Langfuse / Helicone
import { LangSmithTracer } from 'langsmith';

const tracer = new LangSmithTracer({
  projectName: 'my-agent',
});

await graph.invoke(input, {
  callbacks: [tracer],
});

→ 매 LLM call + tool call 추적.

Memory systems

// Short-term: conversation messages
// Long-term: vector DB
import { MemoryClient } from '@mem0/sdk';

const memory = new MemoryClient();

// Save
await memory.add(userId, 'User prefers dark mode and minimal UI');

// Retrieve relevant
const memories = await memory.search(userId, currentQuery);

// Inject to system prompt
const system = `${baseSystem}\n\nRelevant context:\n${memories.join('\n')}`;

Eval (위 LLM Eval 문서)

import { evalDataset, exactMatch, llmJudge } from 'mastra/evals';

await evalDataset({
  agent: weatherAgent,
  cases: [
    { input: 'Tokyo weather?', expected: { contains: 'Tokyo' } },
  ],
  metrics: [exactMatch, llmJudge('helpful')],
});

비교

LangGraph:
+ 가장 강력 / production-ready
+ State machine 명시
- Python 우월 (TS 제한)

Mastra:
+ Modern TS-first
+ Eval / observability built-in
- 새로움 (검증 적음)

CrewAI:
+ Multi-agent simple
- 정밀 제어 어려움

Vercel AI SDK:
+ 단순 / TS 친화
- Multi-step 제한적

자체:
+ 정확 제어
- 모든 거 직접

🤔 의사결정 기준

상황 추천
단순 1-2 step Vercel AI SDK
Multi-step / state LangGraph (Python) / Mastra (TS)
Multi-agent CrewAI / AutoGen
Production / 큰 규모 LangGraph + LangSmith
Quick prototype Vercel AI SDK
완전 제어 자체

안티패턴

  • Framework 선택 전 use case 명시 X: overkill / 부족.
  • State persistence 없음 + long task: crash 시 잃음.
  • Max iter 없음: 무한 / 비용 폭발.
  • HITL 없음 + dangerous tool: 실수 책임.
  • Multi-agent 가 single agent 대체: 단일 가 충분 자주.
  • Memory 모든 거 inject: context 폭발. retrieval.
  • Eval 없음: 향상 측정 X.

🤖 LLM 활용 힌트

  • 단순 = Vercel AI SDK.
  • Production state = LangGraph / Mastra.
  • Multi-agent overkill 자주.
  • HITL + state persistence 필수.

🔗 관련 문서