처음부터 데이터 분석 에이전트 구축

처음부터 데이터 분석 에이전트 구축 (Build a data analysis agent from scratch)

create_agent과 Deep Agents 미들웨어를 사용해 데이터 분석 에이전트를 단계별로 구축해요.

이 가이드는 create_agent과 Deep Agents 미들웨어를 사용해 첫 원리부터 데이터 분석 에이전트를 구축해요.

create_agentcreate_deep_agent 모두 툴, 메모리 등에 대한 세밀한 제어를 제공해요. 두 개의 주요 차이는 Deep Agents에 계획, 파일시스템 툴, 서브에이전트 같은 흔히 유용한 기능이 이미 내장되어 있다는 것이에요.

Deep Agents의 기본 harness가 요구사항에 맞지 않으면, 이 가이드가 create_agent에서 시작해 harness를 한 조각씩 조립하는 방법을 보여줘요. 각 컴포넌트가 무엇을 추가하는지 정확히 볼 수 있고, 사용 사례에 필요한 것만 교체할 수 있어요.

이 가이드를 따라 다음을 수행하는 에이전트를 구축해요:

  1. 분석용 CSV 파일 수용
  2. 격리된 샌드박스에서 Python 코드 작성·실행
  3. 시각화 작업을 전용 서브에이전트에 위임
  4. 스킬 파일에서 데이터 분석 패턴 로드

최종 스택은 create_deep_agent가 기본으로 조립하는 것과 동일해요.

배울 내용 (What you will learn)

각 단계는 같은 데이터 분석 에이전트에 한 가지 기능을 추가해요:

단계 그것이 없을 때의 문제 추가하는 것
최소 에이전트 기준 루프: 모델 + 툴, harness 없음
샌드박스 + 파일시스템 에이전트가 CSV를 읽거나 Python 실행 불가 격리된 백엔드 + 파일 및 실행 툴
요약 긴 세션이 컨텍스트 한도에 도달 자동 기록 압축
스킬 도메인 규칙이 시스템 프롬프트를 부풀림 점진적 공개(progressive disclosure)를 통한 요구 시 전문 지식
서브에이전트 차트 반복이 메인 스레드를 혼잡하게 함 격리된 워커 + 병렬 위임

설정 (Setup)

  1. 패키지 설치 (Install packages): 이 튜토리얼의 패키지를 설치하세요:
npm install deepagents langsmith
  1. LangSmith API 키 설정 (Set up LangSmith API keys): 이 튜토리얼은 LangSmithSandbox를 사용하는데, 이는 SandboxClient를 통해 샌드박스를 프로비저닝해요. 그 클라이언트는 환경 변수의 LANGSMITH_API_KEY로 LangSmith에 인증하므로, 튜토리얼을 실행하려면 API 키가 필요해요. LangSmith를 설정하면 에이전트 실행 시 일어나는 일의 트레이스도 볼 수 있어요.

    1. 무료 계정에 가입하세요. Google, GitHub, 이메일을 사용할 수 있어요.
    2. Settings > API Keys에서 API 키를 만드세요.
    3. LangSmith API 키를 내보내세요: export LANGSMITH_API_KEY=...
    4. 각 조각을 추가할 때 툴 호출, 미들웨어 단계, 서브에이전트 위임을 검사하도록 트레이싱을 활성화하세요: export LANGSMITH_TRACING=true
  2. 모델 제공자 API 키 추가 (Add a model provider API key): 코드 샘플에 사용하는 모델 제공자의 API 키를 내보내세요:

export GOOGLE_API_KEY=... # Google
export OPENAI_API_KEY=... # OpenAI
export ANTHROPIC_API_KEY=... # Anthropic
export OPENROUTER_API_KEY=... # OpenRouter
export FIREWORKS_API_KEY=... # Fireworks
export BASETEN_API_KEY=... # Baseten
export OLLAMA_API_KEY=... # Ollama (로컬 또는 클라우드)

에이전트 구축 (Build the agent)

최소 에이전트 만들기 (Create the minimal agent)

데이터 분석 에이전트는 채팅 루프 이상이 필요하지만, 먼저 기준 즉 모델과 루프만으로 시작하세요.

create_agent를 사용하고 사용할 모델을 지정하세요:

import { createAgent } from "langchain";
let agent = createAgent({
  model: "google-genai:gemini-3.6-flash", // google-genai, openai:gpt-5.5, anthropic:claude-sonnet-5, openrouter:z-ai/glm-5.2, fireworks:..., baseten:..., ollama:...
  tools: [],
});

이것은 실행되지만 에이전트에 파일시스템이 없고 코드를 실행할 방법이 없어요. CSV를 분석하라고 하면 프롬프트에서 추측만 할 수 있어요. 다음 단계에서 실제 파일 접근과 코드 실행을 추가해요.

샌드박스 백엔드 추가 (Add a sandbox backend)

데이터를 효율적으로 분석하려면 에이전트가 파일에서 코드를 실행해야 해요. 이는 두 가지가 필요해요:

  • 에이전트가 호스트 머신에 접근하지 않고 파일을 두고 그 파일에서 코드를 실행할 격리된 샌드박스
  • 샌드박스와 작업하기 위한 파일시스템 툴(read_file, write_file, edit_file, glob, grep)을 제공하는 백엔드FilesystemMiddleware 사용

LangSmithSandbox는 파일이 살고 명령이 실행되는 곳이에요. FilesystemMiddleware는 그 환경을 툴로 모델에 노출해요. 같은 미들웨어는 나중에 백엔드를 교체해도 다른 백엔드와 작동해요.

LangSmithSandbox는 파일시스템과 셸 명령 실행용 execute 툴이 있는 격리된 환경을 에이전트에게 제공해요. 이를 통해 에이전트는 호스트에 닿지 않고 패키지를 설치하고, 스크립트를 작성하고, 실행할 수 있어요. 기본 런타임 대신 커스텀 이미지로 부팅하려면 LangSmithSandbox.create()snapshotId를 전달하세요. 샌드박스 스냅샷을 참고하세요.

FilesystemMiddleware를 포함한 에이전트로 이전 단계의 에이전트를 교체하세요:

import { createFilesystemMiddleware, LangSmithSandbox } from "deepagents";
import { SandboxClient } from "langsmith/sandbox";

const client = new SandboxClient();
const sandbox = await client.createSandbox({
  name: "langchain-docs",
  snapshotName: "docs-test-ci",
});
const backend = new LangSmithSandbox({ sandbox });

agent = createAgent({
  model: "google-genai:gemini-3.6-flash",
  tools: [],
  middleware: [createFilesystemMiddleware({ backend })],
});

샌드박스 파일시스템은 노트북과 분리돼 있어요. 에이전트를 호출하기 전에 필요한 파일을 업로드해야 해요:

const rows = [
  ["Date", "Product", "Units", "Revenue"],
  ["2025-08-01", "Widget A", "10", "250"],
  ["2025-08-02", "Widget B", "5", "125"],
  ["2025-08-03", "Widget A", "7", "175"],
  ["2025-08-04", "Widget C", "3", "90"],
];
const csv = rows.map((row) => row.join(",")).join("\n");
const encoder = new TextEncoder();
await backend.uploadFiles([["/sales.csv", encoder.encode(csv)]]);

const uploadStream = await agent.streamEvents(
  {
    messages: [
      {
        role: "user",
        content:
          "Read /sales.csv and summarize total revenue by product in one sentence. Do not run shell commands.",
      },
    ],
  },
  { version: "v3", recursionLimit: 8 },
);

await Promise.all([
  (async () => {
    for await (const message of uploadStream.messages) {
      console.log(await message.text);
    }
  })(),
  uploadStream.output,
]);
[`LangSmithSandbox`](https://reference.langchain.com/javascript/deepagents/backends/LangSmithSandbox)에서 업로드 경로는 절대 POSIX 경로(예: `/sales.csv`)여야 해요. `sales.csv` 같은 상대 경로는 `invalid_path`로 거부되고 파일이 샌드박스에 기록되지 않아요.

이전 단계들의 코드를 하나의 스크립트로 결합해 실행하세요:

npx tsx analyze-sales.ts

첫 실행에서 LangSmith가 샌드박스를 프로비저닝해요(몇 초 걸릴 수 있어요). 스크립트가 sales.csv를 업로드하고, 에이전트 실행을 스트리밍하며, 도착하는 대로 assistant 메시지를 출력해요. 샘플 판매 데이터 분석(제품별 매출, 어떤 위젯이 가장 팔렸는지, 간단한 트렌드 메모)이 보일 거예요. 정확한 문구는 모델 실행에 따라 달라져요.

LangSmith에서 실행을 열고 에이전트가 응답 전에 파일시스템 툴(read_file, 샌드박스에서 Python을 실행하면 execute)을 사용하는 것을 관찰하세요.

컨텍스트 관리 추가 (Add context management)

2단계 후에 모든 툴 결과는 메시지 기록에 남아요. 실제 분석 세션(여러 플롯, 실패한 스크립트, 큰 read_file 출력)은 컨텍스트 윈도우를 빠르게 채워요.

SummarizationMiddleware는 기록이 너무 커질 때 이전 턴을 압축하므로, 메시지를 수동으로 다듬지 않아도 에이전트가 계속 작동해요. 첫 sales.csv 질문에서는 덜 중요하지만 "이제 제품별로 세분화하고 월별 트렌드를 플롯해줘" 같은 후속 질문에서 더 중요해요.

미들웨어 목록에 SummarizationMiddleware를 추가해 2단계의 에이전트를 업데이트하세요:

import { createSummarizationMiddleware } from "deepagents";

let model = "google-genai:gemini-3.6-flash";
agent = createAgent({
  model,
  tools: [],
  middleware: [
    createFilesystemMiddleware({ backend }),
    createSummarizationMiddleware({
      model,
      backend,
    }),
  ],
});

요약이 작동하는 것을 보려면 다중 턴 세션을 실행하세요. 초기 분석 후 더 많은 파일 읽기나 스크립트 실행을 유발하는 후속 질문을 하세요. LangSmith에서 이후 모델 호출 전에 요약 단계를 찾아보세요. 자세한 내용은 컨텍스트 엔지니어링 참고.

스킬 추가 (Add skills)

스킬은 점진적 공개를 사용해 필요할 때 에이전트에게 요구 시 도메인 지식을 제공하는 방법이에요. 스킬에는 다단계 워크플로, 규칙, 관례가 포함될 수 있어요. 이 정보를 스킬에 배치하면 기본적으로 시스템 프롬프트에 추가되지 않으므로, 작업에 스킬 정보가 필요할 때만 토큰이 사용됨을 보장해요.

에이전트가 시작하면 각 스킬에 대한 가벼운 메타데이터만 보아요. 작업이 스킬을 필요로 할 때 에이전트가 전체 스킬 파일을 요구 시 로드해요.

스킬 디렉터리에 스킬 파일을 만드세요:

skills/
  pandas-patterns/
    SKILL.md
---
name: pandas-patterns
description: Common pandas and matplotlib patterns for data analysis and visualization
---

## Data loading
Use `pd.read_csv()` for CSV files. Always check `df.info()` and `df.describe()` first.

## Visualization
Use `matplotlib` for bar charts, `seaborn` for statistical plots.
Save figures with `plt.savefig("output.png", dpi=150, bbox_inches="tight")`.

## Reporting
Write a markdown summary to `report.md` alongside any generated charts.

이 스킬은 시각화가 어떻게 수행되어야 하는지에 대한 정보를 포함해요.

LangSmithSandbox에서 스킬 경로는 로컬 머신이 아니라 샌드박스 파일시스템에서 해석돼요. SkillsMiddleware를 구성하기 전에 로컬 skills/ 디렉터리를 업로드하세요:

import { readFileSync, readdirSync, statSync } from "node:fs";
import { join, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const skillsDir = resolve(
  fileURLToPath(new URL(".", import.meta.url)),
  "skills",
);

const skillFiles: Array<[string, Uint8Array]> = [];
function collectSkillFiles(dir: string): void {
  for (const entry of readdirSync(dir)) {
    const fullPath = join(dir, entry);
    if (statSync(fullPath).isDirectory()) {
      collectSkillFiles(fullPath);
    } else {
      const rel = relative(skillsDir, fullPath).replace(/\\/g, "/");
      skillFiles.push([`/skills/${rel}`, readFileSync(fullPath)]);
    }
  }
}
collectSkillFiles(skillsDir);
await backend.uploadFiles(skillFiles);

그런 다음 SkillsMiddleware를 추가해 스킬과 함께 에이전트를 만드세요:

import { createSkillsMiddleware } from "deepagents";

model = "google-genai:gemini-3.6-flash";
agent = createAgent({
  model,
  tools: [],
  middleware: [
    createFilesystemMiddleware({ backend }),
    createSummarizationMiddleware({ model, backend }),
    createSkillsMiddleware({ backend, sources: ["/skills/"] }),
  ],
});

"우리의 pandas 패턴을 사용해 sales.csv를 분석해줘" 같은 프롬프트를 시도해보세요. 에이전트는 플로팅이나 리포팅 지침이 필요할 때 스킬을 로드해요. 스킬이 필요하지 않은 다른 질문을 하면 에이전트는 스킬을 로드하지 않아요.

시각화 서브에이전트 추가 (Add a visualization subagent)

일부 작업은 큰 중간 출력(스크립트 초안, 실패한 실행, 파일 읽기)을 생성하며, 한 스레드에 두면 메인 에이전트의 컨텍스트를 혼잡하게 해요. 서브에이전트는 자체 컨텍스트 윈도우에서 실행되므로 슈퍼바이저는 모든 툴 호출이 아니라 최종 결과만 보아요. 이는 메인 분석을 집중 유지하고 후속 질문을 위한 여지를 남겨요.

서브에이전트 사용이 합리적인 한 예는 차트 생성이에요. 플로팅은 종종 Python 스크립트를 반복하고, 패키지를 설치하고, 그림이 준비되기 전에 오류 출력을 읽는 것을 의미해요. 다음 visualizer 서브에이전트는 메인 에이전트가 계속 계획·분석하는 동안 그 작업을 격리해서 처리할 수 있어요. TodoListMiddleware로 메인 에이전트는 각 플롯을 블로킹하는 대신 차트 작업을 병렬로 위임할 수도 있어요.

TodoListMiddlewareSubAgentMiddleware를 추가해 4단계의 에이전트를 업데이트하세요:

import { todoListMiddleware } from "langchain";
import { createSubAgentMiddleware, type SubAgent } from "deepagents";

const visualizer: SubAgent = {
  name: "visualizer",
  description:
    "Generates charts and visualizations from data files in the sandbox.",
  systemPrompt:
    "You are a data visualization specialist. Write Python scripts using matplotlib and seaborn. Save all figures as PNG files.",
};

agent = createAgent({
  model,
  tools: [],
  middleware: [
    createFilesystemMiddleware({ backend }),
    createSummarizationMiddleware({ model, backend }),
    createSkillsMiddleware({ backend, sources: ["/skills/"] }),
    todoListMiddleware(),
    createSubAgentMiddleware({
      defaultModel: model,
      defaultTools: [],
      subagents: [visualizer],
    }),
  ],
});

"sales.csv를 분석한 다음 제품별 매출 막대 차트를 만드세요" 같은 프롬프트를 시도해보세요. 메인 에이전트가 분석·계획을 처리하고 task 툴을 통해 차트 생성을 visualizer 서브에이전트에 위임해요.

설정에서 트레이싱을 활성화했다면 LangSmith에서 실행을 열어보세요. visualizer에 대한 task 호출, 자체 툴 루프가 있는 별도의 하위 실행, 슈퍼바이저로 반환되는 짧은 결과를 볼 수 있어요.

무엇을 구축했나 (What you built)

다음 미들웨어로 커스터마이즈된 에이전트를 구축했어요:

미들웨어 추가하는 것
FilesystemMiddleware + LangSmithSandbox 격리된 파일시스템 + execute
SummarizationMiddleware 자동 컨텍스트 압축
SkillsMiddleware 요구 시 로드되는 도메인 지식
TodoListMiddleware + SubAgentMiddleware 병렬 시각화 서브에이전트

이것은 createDeepAgent와 같은 기반이에요: 정확히 무엇이 포함되는지 제어할 수 있도록 수동으로 조립한 것이에요.

가능성은 여기서 끝나지 않아요: 구성 가능한 기능의 전체 목록은 사전 구축 미들웨어를, 모든 구성 옵션은 create_agent 레퍼런스를 참고하세요.

사전 조립 버전으로 작업하려면 Deep Agents 커스터마이즈를 참고하세요. createDeepAgent를 사용한 전체 데이터 분석 예제는 데이터 분석을 참고하세요.

출처: 문서

본문

이 가이드는 create_agent과 Deep Agents 미들웨어를 사용해 데이터 분석 에이전트를 처음부터 구축해요. 최소 에이전트 → 샌드박스 백엔드(LangSmithSandbox + FilesystemMiddleware) → 컨텍스트 관리(SummarizationMiddleware) → 스킬(SkillsMiddleware) → 병렬 시각화 서브에이전트(TodoListMiddleware + SubAgentMiddleware) 순서로 조립하며, 최종 스택은 create_deep_agent이 기본으로 조립하는 것과 동일해요.

더 알아보기 (Learn more)