에이전트

에이전트 (Agents)

에이전트는 주어진 작업이 완료될 때까지 모델이 툴을 호출하는 루프예요.

A harness is everything around that loop: the prompt, the tools, and any middleware that shapes the model's behavior. harness는 루프 주변의 모든 것이에요: 프롬프트, 툴, 그리고 모델의 행동을 형성하는 모든 미들웨어.

**에이전트 = 모델 + Harness** harness의 역할: 주어진 작업에 대해 올바른 시점에 모델에게 올바른 컨텍스트를 전달하는 것.

create_agent는 매우 구성 가능한 harness예요. 가장 단순하게는 이렇게 만들 수 있어요:

```ts Google import { createAgent } from "langchain"; var agent = createAgent({ model: "google-genai:gemini-3.6-flash", tools }); ``` ```ts OpenAI var agent = createAgent({ model: "openai:gpt-5.5", tools }); ``` ```ts Anthropic var agent = createAgent({ model: "anthropic:claude-sonnet-5", tools }); ``` ```ts OpenRouter var agent = createAgent({ model: "openrouter:z-ai/glm-5.2", tools }); ``` ```ts Fireworks var agent = createAgent({ model: "fireworks:accounts/fireworks/models/glm-5p2", tools }); ``` ```ts Baseten var agent = createAgent({ model: "baseten:zai-org/GLM-5.2", tools }); ``` ```ts Ollama var agent = createAgent({ model: "ollama:north-mini-code-1.0", tools }); ```

여기에 더해 model=, tools=, system_prompt= 파라미터로 기본 사항을 직접 구성할 수 있어요. 더 고급 기능을 위해 미들웨어로 harness를 확장하세요.

[Deep Agents](/oss/javascript/deepagents/overview)는 `create_agent` 위에 구축되며 계획, 파일시스템 툴, 서브에이전트, 메모리 같은 흔히 유용한 기능이 이미 조립되어 제공돼요. harness를 직접 구성해야 할 때 `create_agent`를 사용하세요.

핵심 컴포넌트 (Core components)

모델 (Model)

모델 식별자 문자열("provider:model") 또는 초기화된 모델 인스턴스를 전달해 에이전트의 모델을 선택하세요. 파라미터, 제공자 설정, 동적 모델 선택은 모델을 참고하세요.

툴 (Tools)

에이전트에 툴을 제공하려면 어떤 Python 호출 가능 객체, LangChain 툴, 또는 툴 dict를 전달하세요. 툴 정의, 컨텍스트 접근, 동적 툴 선택은 을 참고하세요.

import { tool } from "langchain";
import * as z from "zod";

var search = tool(({ query }) => `Results for: ${query}`, {
  name: "search",
  description: "Search for information",
  schema: z.object({ query: z.string() }),
});

var agent = createAgent({ model: "google-genai:gemini-3.6-flash", tools: [search] });
var agent = createAgent({ model: "openai:gpt-5.5", tools: [search] });
var agent = createAgent({ model: "anthropic:claude-sonnet-5", tools: [search] });
var agent = createAgent({ model: "openrouter:z-ai/glm-5.2", tools: [search] });
var agent = createAgent({ model: "fireworks:accounts/fireworks/models/glm-5p2", tools: [search] });
var agent = createAgent({ model: "baseten:zai-org/GLM-5.2", tools: [search] });
var agent = createAgent({ model: "ollama:north-mini-code-1.0", tools: [search] });

시스템 프롬프트 (System prompt)

에이전트가 작업에 접근하는 방식을 형성해요. 시스템 프롬프트 파라미터는 문자열이나 SystemMessage를 받아요. 런타임의 동적 프롬프트를 위해 미들웨어를 사용하세요.

var agent = createAgent({
  model: "google-genai:gemini-3.6-flash",
  tools,
  systemPrompt: "You are a helpful assistant. Be concise and accurate.",
});

구조화된 출력 (Structured output)

response_format=로 에이전트에서 검증된 스키마를 반환하세요. 전략과 예제는 구조화된 출력을 참고하세요.

const Answer = z.object({ summary: z.string(), confidence: z.number() });

const result = await agent.invoke({
  messages: [{ role: "user", content: "Summarize AI trends" }],
  responseFormat: Answer,
});

result.structuredResponse; // { summary: ..., confidence: ... }

에이전트 상태 (Agent state)

모든 에이전트는 현재 대화 기록과 툴·미들웨어가 필요로 하는 커스텀 필드를 담는 AgentState 객체로 실행 컨텍스트를 관리해요.

기본 필드:

필드 타입 설명
messages BaseMessage[] 현재 스레드의 전체 대화 기록. 추가 전용(append-only)이에요: 새 메시지가 추가되며 교체되지 않아요.

AgentState는 모든 node-style 미들웨어 훅(beforeModel, afterModel 등)에 전달되는 타입이기도 해요. 훅은 현재 상태를 받고 병합할 업데이트 객체를 반환할 수 있어요.

커스텀 필드를 추가하려면 미들웨어에서 stateSchema(StateSchema 또는 Zod 객체)로 상태 스키마를 정의하세요:

import { createAgent, createMiddleware } from "langchain";
import { StateSchema } from "@langchain/langgraph";

const MyState = new StateSchema({
  userId: z.string(),
  callCount: z.number().default(0),
});

const stateMiddleware = createMiddleware({
  name: "StateExtension",
  stateSchema: MyState, // [!code highlight]
});

const agent = createAgent({
  tools: [],
  middleware: [stateMiddleware],
});

전체 세부 사항, 예제, 미들웨어 수준 상태 스키마는 단기 메모리커스텀 미들웨어를 참고하세요.

호출 (Invocation)

LangSmith로 이 루프의 각 단계를 추적하고 툴 호출을 디버깅하며 에이전트 출력을 평가하세요. 설정하려면 tracing quickstart를 따르세요. 또한 LangSmith Engine을 설정해 트레이스를 모니터링하고 문제를 감지하며 수정을 제안받는 것을 권장해요.

메시지로 에이전트를 호출할 수 있어요. 내부적으로는 에이전트의 State에 업데이트를 전달해요. 모든 에이전트는 상태에 메시지 시퀀스를 포함하므로, 에이전트를 호출하려면 새 메시지와 함께 thread_id를 전달해 에이전트가 대화 기록을 유지·재개할 수 있게 해요:

import { AIMessage } from "@langchain/core/messages";
import { MemorySaver } from "@langchain/langgraph";

const agent = createAgent({
  model: "openai:gpt-5.5",
  tools: [...tools],
  checkpointer: new MemorySaver(),
});

const config = { configurable: { thread_id: crypto.randomUUID() } };

let result = await agent.invoke(
  {
    messages: [
      { role: "user", content: "What's the weather in San Francisco?" },
    ],
  },
  config,
);

// A follow-up turn on the same conversation: reuse the same thread_id to keep history
result = await agent.invoke(
  { messages: [{ role: "user", content: "What about tomorrow?" }] },
  config,
);

thread_id로 대화 기록을 유지하려면 에이전트가 체크포인터로 구성되어야 해요. LangSmith 배포 시 체크포인터가 자동으로 프로비저닝돼요. 로컬에서는 create_agent(..., checkpointer=InMemorySaver())처럼 명시적으로 전달하세요.

툴·미들웨어에 실행별 구성(사용자 ID, API 키, 기능 플래그 등)을 전달해야 한다면 config와 함께 context로 전달하세요. 해당 데이터의 형태를 contextSchema로 정의하고 runtime.context로 접근하세요:

const contextSchema = z.object({
  user_id: z.string(),
});

const agent = createAgent({
  model: "openai:gpt-5.5",
  tools,
  contextSchema,
});

const result = await agent.invoke(
  { messages: [{ role: "user", content: "..." }] },
  { configurable: { thread_id: crypto.randomUUID() }, context: { user_id: "user-123" } },
);

thread_id대화(메시지 기록, 체크포인트)를 범위로 하고, context는 툴·미들웨어가 호출 시 읽는 실행별 데이터를 전달해요. 둘 다 함께 전달되는 것이 일반적이에요. 더 자세한 내용은 툴 컨텍스트Runtime을 참고하세요.

스트리밍 (Streaming)

invoke는 실행 끝에 최종 응답을 반환해요. 에이전트가 여러 툴 호출을 실행하면 사용자는 완료 전에 진행 상황 업데이트가 필요할 때가 많아요. 스트리밍을 사용해 중간 메시지와 툴 활동을 발생 즉시 표시하세요.

const stream = await agent.streamEvents(
  {
    messages: [
      {
        role: "user",
        content: "Search for AI news and summarize the findings",
      },
    ],
  },
  { version: "v3" },
);

for await (const snapshot of stream.values) {
  // Each snapshot contains the full state at that point
  const latestMessage = snapshot.messages.at(-1);
  if (latestMessage?.content) {
    if (latestMessage.type === "human") {
      console.log(`User: ${latestMessage.content}`);
    } else if (latestMessage.type === "ai") {
      console.log(`Agent: ${latestMessage.content}`);
    }
  } else if (latestMessage?.tool_calls?.length) {
    const toolCallNames = latestMessage.tool_calls.map((tc) => tc.name);
    console.log(`Calling tools: ${toolCallNames.join(", ")}`);
  }
}

스트리밍 모드, 이벤트 유형, UI 패턴은 Streaming을 참고하세요.

Harness 구성 (Configure the harness)

create_agent는 매우 확장 가능해요. 미들웨어는 커스터마이징의 기본 요소예요: 각 조각이 하나의 관심사를 처리하고, 올바른 시점에 에이전트 루프에 연결되며, 다른 것과 자유롭게 결합돼요. 사용 사례에 필요한 것만 사용하고 나머지는 건너뛰세요.

일반적인 패턴은 일급(일등) 미들웨어로 사전 구축돼 있어요. 그 외는 커스텀 미들웨어로 만들 수 있어요.

에이전트가 복잡한 작업을 수행함에 따라 몇 가지 핵심 영역에서 지원이 필요해요. 미들웨어 생태계는 다음을 제공해요:

  • 실행 환경 (Execution environment) — 툴, 파일시스템, 샌드박스, 코드 실행
  • 컨텍스트 관리 (Context management) — 요약, 메모리, 스킬, 프롬프트 캐싱
  • 계획·위임 (Planning and delegation) — 병렬·격리 작업을 위한 할 일 목록과 서브에이전트
  • 결함 허용 (Fault tolerance) — 재시도, 폴백, 호출 한도
  • 가드레일 (Guardrails) — PII 탐지와 콘텐츠 제어
  • 스티어링 (Steering) — 영향력 큰 작업 전 사람의 승인 (human-in-the-loop)

create_deep_agent는 장기 실행 코딩·리서치 작업(파일시스템, 요약, 서브에이전트, 프롬프트 캐싱이 기본 포함)을 위해 이 스택을 사전 조립해요. 전체 사전 구축 harness는 Deep Agents를 참고하세요.

실행 환경 (Execution environment)

에이전트는 텍스트를 생성하는 것보다 조치를 취할 수 있을 때 특히 유용해요. 실행 환경은 에이전트에게 작업 공간을 제공해요: 호출 가능한 툴, 턴에 걸쳐 파일을 읽고 쓰는 파일시스템, 스크립트·셸 명령을 실행하는 코드 실행.

import { createFilesystemMiddleware, StateBackend } from "deepagents";

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

FilesystemMiddleware, 샌드박스, 인터프리터를 참고하세요.

컨텍스트 관리 (Context management)

모든 모델 호출에는 고정된 컨텍스트 윈도우가 있어요. 에이전트가 실행되면 그 윈도우는 누적된 기록, 툴 결과, 중간 단계로 채워져요. 요약은 오버플로 발생 전에 기록을 압축하고, 메모리는 시작 시 영구적 지침을 로드해 지식을 세션 간 전달하며, 스킬은 모든 것을 미리 로드하는 대신 요구에 따라 도메인 지식을 표시해요.

import {
  StateBackend,
  createFilesystemMiddleware,
  createSkillsMiddleware,
  createSummarizationMiddleware,
} from "deepagents";

var backend = new StateBackend();
const model = "google-genai:gemini-3.6-flash";

var agent = createAgent({
  model,
  tools: [search],
  middleware: [
    createFilesystemMiddleware({ backend }),
    createSummarizationMiddleware({ model, backend }),
    createSkillsMiddleware({ backend, sources: ["./skills/"] }),
  ],
});

SummarizationMiddleware, MemoryMiddleware, 스킬, 컨텍스트 엔지니어링을 참고하세요.

계획과 위임 (Planning and delegation)

복잡한 작업은 하나의 컨텍스트 윈도우가 감당할 수 있는 범위를 초과하는 경우가 많아요. 위임은 메인 에이전트가 작업을 조각으로 나누고 각자 격리된 컨텍스트에서 실행되는 서브에이전트에 맡기고, 실행보다 조정에 집중할 수 있게 해요. 작업은 병렬로 실행될 수 있고, 메인 에이전트의 컨텍스트는 깨끗하게 유지돼요.

import { createAgent, todoListMiddleware, tool } from "langchain";
import { createSubAgentMiddleware } from "deepagents";

var search = tool(({ query }) => `Search results for: ${query}`, {
  name: "search",
  description: "Search for a query and return a short summary.",
  schema: z.object({ query: z.string() }),
});

var agent = createAgent({
  model: "openai:gpt-5.5",
  tools: [search],
  middleware: [
    todoListMiddleware(),
    createSubAgentMiddleware({
      defaultModel: "anthropic:claude-sonnet-4-6",
      defaultTools: [],
      subagents: [
        {
          name: "researcher",
          description: "Searches and returns a structured summary.",
          systemPrompt:
            "Use the search tool to research the question and summarize key points.",
          tools: [search],
          model: "google-genai:gemini-3.6-flash",
          middleware: [],
        },
      ],
    }),
  ],
});

서브에이전트를 참고하세요.

에이전트 이름 지정 (Name your agent)

선택적으로 에이전트에 식별자를 사용하세요. 특히 다중 에이전트 시스템에서 에이전트를 서브그래프로 임베드할 때 유용해요.

var agent = createAgent({
  model: "openai:gpt-5.5",
  tools,
  name: "research_assistant",
});

결함 허용 (Fault tolerance)

프로덕션 에이전트는 개발에서 거의 나타나지 않는 실패(레이트 한도, 모델 타임아웃, 일시적 API 오류)를 만나요. 결함 허용 미들웨어는 이를 인프라 수준에서 처리하므로 툴과 비즈니스 로직이 매 호출마다 try/catch를 둘 필요가 없어요.

import {
  createAgent,
  modelRetryMiddleware,
  tool,
  toolRetryMiddleware,
} from "langchain";

var agent = createAgent({
  model: "openai:gpt-5.5",
  tools: [search],
  middleware: [
    modelRetryMiddleware({ maxRetries: 3 }),
    toolRetryMiddleware({ maxRetries: 2 }),
  ],
});

modelRetryMiddleware, toolRetryMiddleware, 사전 구축 미들웨어를 참고하세요.

가드레일 (Guardrails)

어떤 정책은 프롬프트에 담을 수 없어요 — 모델이 무엇을 하든 결정적으로 시행되어야 해요. 가드레일은 데이터가 에이전트 루프를 통과할 때 가로채, 툴 결과가 모델 컨텍스트에 도달하기 전에 규정 준수 규칙이나 콘텐츠 정책을 적용해요.

import { createAgent, piiMiddleware, tool } from "langchain";

var agent = createAgent({
  model: "openai:gpt-5.5",
  tools: [search],
  middleware: [piiMiddleware("email")],
});

piiMiddleware, 사전 구축 미들웨어를 참고하세요.

스티어링 (Steering)

완전 자율이 항상 적절한 것은 아니에요. 스티어링은 파괴적인 쓰기, 비용이 큰 API 호출, 판단이 필요한 모든 것 앞의 특정 결정 지점에 사람을 배치할 수 있게 해요 — 에이전트를 재구성하지 않고도요. 에이전트가 멈추고 기다리면, 사람이 승인·편집·거부하고, 실행이 계속돼요.

import { createAgent, humanInTheLoopMiddleware, tool } from "langchain";

var agent = createAgent({
  model: "openai:gpt-5.5",
  tools: [search],
  middleware: [humanInTheLoopMiddleware({ interruptOn: { writeFile: true } })],
});

humanInTheLoopMiddleware, Human-in-the-loop을 참고하세요.

미들웨어 리소스 (Middleware resources)

출처: 문서

본문

이 페이지는 LangChain 에이전트 개념을 소개해요. 에이전트는 create_agent로 만드는 모델+harness로, 본문은 호출 루프 주변의 프롬프트·툴·미들웨어를 다뤄요. 핵심 컴포넌트(모델·툴·시스템 프롬프트·구조화된 출력·에이전트 상태), 호출(thread_id·checkpointer·context), 스트리밍, 그리고 harness 구성(실행 환경, 컨텍스트 관리, 계획·위임, 결함 허용, 가드레일, 스티어링, 미들웨어 리소스)을 설명해요.

더 알아보기 (Learn more)