구조화된 출력을 사용하면 에이전트가 특정하고 예측 가능한 형식으로 데이터를 반환할 수 있습니다. 자연어 응답을 파싱하는 대신, 타입이 지정된 구조화된 데이터를 얻을 수 있습니다.
LangChain의 사전 구축된 ReAct 에이전트 createAgent는 구조화된 출력을 자동으로 처리합니다. 사용자가 원하는 구조화된 출력 스키마를 설정하면, 모델이 구조화된 데이터를 생성할 때 이를 캡처하고 검증한 후 에이전트 상태의 structuredResponse 키에 반환합니다.
type ResponseFormat = (
| ZodSchema < StructuredResponseT > // Zod 스키마
| Record < string , unknown > // JSON 스키마
)
const agent = createAgent ({
// ...
responseFormat: ResponseFormat | ResponseFormat []
})
에이전트가 구조화된 데이터를 반환하는 방식을 제어합니다. Zod 객체 또는 JSON 스키마를 제공할 수 있습니다. 기본적으로 에이전트는 도구 호출 전략을 사용하며, 이 경우 출력은 추가 도구 호출을 통해 생성됩니다. 특정 모델은 네이티브 구조화된 출력을 지원하며, 이 경우 에이전트가 해당 전략을 사용합니다.
ResponseFormat을 toolStrategy 또는 providerStrategy 함수 호출로 래핑하여 동작을 제어할 수 있습니다:
import { toolStrategy , providerStrategy } from "langchain" ;
const agent = createAgent ({
// 모델에서 지원하는 경우 제공자 전략 사용
responseFormat: providerStrategy ( z . object ({ ... }))
// 또는 도구 전략 강제 사용
responseFormat : toolStrategy ( z . object ({ ... }))
})
구조화된 응답은 에이전트의 최종 상태에서 structuredResponse 키에 반환됩니다.
Provider strategy
일부 모델 제공자는 API를 통해 네이티브로 구조화된 출력을 지원합니다(현재 OpenAI와 Grok만 해당). 이는 사용 가능한 경우 가장 신뢰할 수 있는 방법입니다.
이 전략을 사용하려면 ProviderStrategy를 구성하세요:
function providerStrategy < StructuredResponseT >(
schema : ZodSchema < StructuredResponseT > | JsonSchemaFormat
) : ProviderStrategy < StructuredResponseT >
구조화된 출력 형식을 정의하는 스키마입니다. 지원하는 형식:
Zod 스키마 : Zod 스키마
JSON 스키마 : JSON 스키마 객체
스키마 타입을 createAgent.responseFormat에 직접 전달하고 모델이 네이티브 구조화된 출력을 지원하는 경우, LangChain이 자동으로 ProviderStrategy를 사용합니다:
import * as z from "zod" ;
import { createAgent , providerStrategy } from "langchain" ;
const ContactInfo = z . object ({
name: z . string (). describe ( "사람의 이름" ),
email: z . string (). describe ( "사람의 이메일 주소" ),
phone: z . string (). describe ( "사람의 전화번호" ),
});
const agent = createAgent ({
model: "openai:gpt-5" ,
tools: tools ,
responseFormat: providerStrategy ( ContactInfo )
});
const result = await agent . invoke ({
messages: [{ "role" : "user" , "content" : "Extract contact info from: John Doe, [email protected] , (555) 123-4567" }]
});
result . structuredResponse ;
// { name: "John Doe", email: "[email protected] ", phone: "(555) 123-4567" }
제공자 네이티브 구조화된 출력은 모델 제공자가 스키마를 강제하기 때문에 높은 신뢰성과 엄격한 검증을 제공합니다. 사용 가능한 경우 이를 사용하세요.
제공자가 선택한 모델에 대해 네이티브로 구조화된 출력을 지원하는 경우, responseFormat: contactInfoSchema 대신 responseFormat: toolStrategy(contactInfoSchema)로 작성하는 것과 기능적으로 동일합니다. 두 경우 모두 구조화된 출력이 지원되지 않으면 에이전트가 도구 호출 전략으로 폴백합니다.
네이티브 구조화된 출력을 지원하지 않는 모델의 경우, LangChain은 도구 호출을 사용하여 동일한 결과를 달성합니다. 이는 도구 호출을 지원하는 모든 모델에서 작동하며, 대부분의 최신 모델이 이에 해당합니다.
이 전략을 사용하려면 ToolStrategy를 구성하세요:
function toolStrategy < StructuredResponseT >(
responseFormat :
| JsonSchemaFormat
| ZodSchema < StructuredResponseT >
| ( ZodSchema < StructuredResponseT > | JsonSchemaFormat )[]
options ?: ToolStrategyOptions
) : ToolStrategy < StructuredResponseT >
구조화된 출력 형식을 정의하는 스키마입니다. 지원하는 형식:
Zod 스키마 : Zod 스키마
JSON 스키마 : JSON 스키마 객체
options.toolMessageContent
구조화된 출력이 생성될 때 반환되는 도구 메시지의 커스텀 콘텐츠입니다.
제공되지 않으면 구조화된 응답 데이터를 표시하는 기본 메시지가 사용됩니다.
오류 처리 전략을 커스터마이즈하기 위한 선택적 handleError 매개변수를 포함하는 옵션 매개변수입니다.
true : 기본 오류 템플릿으로 모든 오류 처리 (기본값)
False : 재시도 없이 예외를 전파
(error: ToolStrategyError) => string | Promise<string> : 제공된 메시지로 재시도하거나 오류를 throw
Zod Schema
JSON Schema
Union Types
import * as z from "zod" ;
import { createAgent , toolStrategy } from "langchain" ;
const ProductReview = z . object ({
rating: z . number (). min ( 1 ). max ( 5 ). optional (),
sentiment: z . enum ([ "positive" , "negative" ]),
keyPoints: z . array ( z . string ()). describe ( "리뷰의 핵심 포인트. 소문자, 각 1-3 단어." ),
});
const agent = createAgent ({
model: "openai:gpt-5" ,
tools: tools ,
responseFormat: toolStrategy ( ProductReview )
})
result = agent . invoke ({
"messages" : [{ "role" : "user" , "content" : "Analyze this review: 'Great product: 5 out of 5 stars. Fast shipping, but expensive'" }]
})
console . log ( result . structuredResponse );
// { "rating": 5, "sentiment": "positive", "keyPoints": ["fast shipping", "expensive"] }
Custom tool message content
toolMessageContent 매개변수를 사용하면 구조화된 출력이 생성될 때 대화 기록에 나타나는 메시지를 커스터마이즈할 수 있습니다:
import * as z from "zod" ;
import { createAgent , toolStrategy } from "langchain" ;
const MeetingAction = z . object ({
task: z . string (). describe ( "완료해야 할 구체적인 작업" ),
assignee: z . string (). describe ( "작업 담당자" ),
priority: z . enum ([ "low" , "medium" , "high" ]). describe ( "우선순위 레벨" ),
});
const agent = createAgent ({
model: "openai:gpt-5" ,
tools: [],
responseFormat: toolStrategy ( MeetingAction , {
toolMessageContent: "액션 아이템이 캡처되어 회의록에 추가되었습니다!"
})
});
const result = await agent . invoke ({
messages: [{ "role" : "user" , "content" : "From our meeting: Sarah needs to update the project timeline as soon as possible" }]
});
console . log ( result );
/**
* {
* messages: [
* { role: "user", content: "From our meeting: Sarah needs to update the project timeline as soon as possible" },
* { role: "assistant", content: "액션 아이템이 캡처되어 회의록에 추가되었습니다!", tool_calls: [ { name: "MeetingAction", args: { task: "update the project timeline", assignee: "Sarah", priority: "high" }, id: "call_456" } ] },
* { role: "tool", content: "액션 아이템이 캡처되어 회의록에 추가되었습니다!", tool_call_id: "call_456", name: "MeetingAction" }
* ],
* structuredResponse: { task: "update the project timeline", assignee: "Sarah", priority: "high" }
* }
*/
toolMessageContent 없이는 다음과 같이 표시됩니다:
# console . log ( result );
/**
* {
* messages: [
* ...
* { role: "tool", content: "Returning structured response: {'task': 'update the project timeline', 'assignee': 'Sarah', 'priority': 'high'}", tool_call_id: "call_456", name: "MeetingAction" }
* ],
* structuredResponse: { task: "update the project timeline", assignee: "Sarah", priority: "high" }
* }
*/
Error handling
모델은 도구 호출을 통해 구조화된 출력을 생성할 때 실수를 할 수 있습니다. LangChain은 이러한 오류를 자동으로 처리하기 위한 지능형 재시도 메커니즘을 제공합니다.
Multiple structured outputs error
모델이 여러 구조화된 출력 도구를 잘못 호출하면, 에이전트는 @[ToolMessage]에 오류 피드백을 제공하고 모델에 재시도를 요청합니다:
import * as z from "zod" ;
import { createAgent , toolStrategy } from "langchain" ;
const ContactInfo = z . object ({
name: z . string (). describe ( "사람의 이름" ),
email: z . string (). describe ( "이메일 주소" ),
});
const EventDetails = z . object ({
event_name: z . string (). describe ( "이벤트 이름" ),
date: z . string (). describe ( "이벤트 날짜" ),
});
const agent = createAgent ({
model: "openai:gpt-5" ,
tools: [],
responseFormat: toolStrategy ([ ContactInfo , EventDetails ]),
});
const result = await agent . invoke ({
messages: [
{
role: "user" ,
content:
"Extract info: John Doe ([email protected] ) is organizing Tech Conference on March 15th" ,
},
],
});
console . log ( result );
/**
* {
* messages: [
* { role: "user", content: "Extract info: John Doe ([email protected] ) is organizing Tech Conference on March 15th" },
* { role: "assistant", content: "", tool_calls: [ { name: "ContactInfo", args: { name: "John Doe", email: "[email protected] " }, id: "call_1" }, { name: "EventDetails", args: { event_name: "Tech Conference", date: "March 15th" }, id: "call_2" } ] },
* { role: "tool", content: "Error: Model incorrectly returned multiple structured responses (ContactInfo, EventDetails) when only one is expected.\n Please fix your mistakes.", tool_call_id: "call_1", name: "ContactInfo" },
* { role: "tool", content: "Error: Model incorrectly returned multiple structured responses (ContactInfo, EventDetails) when only one is expected.\n Please fix your mistakes.", tool_call_id: "call_2", name: "EventDetails" },
* { role: "assistant", content: "", tool_calls: [ { name: "ContactInfo", args: { name: "John Doe", email: "[email protected] " }, id: "call_3" } ] },
* { role: "tool", content: "Returning structured response: {'name': 'John Doe', 'email': '[email protected] '}", tool_call_id: "call_3", name: "ContactInfo" }
* ],
* structuredResponse: { name: "John Doe", email: "[email protected] " }
* }
*/
Schema validation error
구조화된 출력이 예상 스키마와 일치하지 않으면, 에이전트가 구체적인 오류 피드백을 제공합니다:
import * as z from "zod" ;
import { createAgent , toolStrategy } from "langchain" ;
const ProductRating = z . object ({
rating: z . number (). min ( 1 ). max ( 5 ). describe ( "1-5 사이의 평점" ),
comment: z . string (). describe ( "리뷰 코멘트" ),
});
const agent = createAgent ({
model: "openai:gpt-5" ,
tools: [],
responseFormat: toolStrategy ( ProductRating ),
});
const result = await agent . invoke ({
messages: [
{
role: "user" ,
content: "Parse this: Amazing product, 10/10!" ,
},
],
});
console . log ( result );
/**
* {
* messages: [
* { role: "user", content: "Parse this: Amazing product, 10/10!" },
* { role: "assistant", content: "", tool_calls: [ { name: "ProductRating", args: { rating: 10, comment: "Amazing product" }, id: "call_1" } ] },
* { role: "tool", content: "Error: Failed to parse structured output for tool 'ProductRating': 1 validation error for ProductRating\nrating\n Input should be less than or equal to 5 [type=less_than_equal, input_value=10, input_type=int].\n Please fix your mistakes.", tool_call_id: "call_1", name: "ProductRating" },
* { role: "assistant", content: "", tool_calls: [ { name: "ProductRating", args: { rating: 5, comment: "Amazing product" }, id: "call_2" } ] },
* { role: "tool", content: "Returning structured response: {'rating': 5, 'comment': 'Amazing product'}", tool_call_id: "call_2", name: "ProductRating" }
* ],
* structuredResponse: { rating: 5, comment: "Amazing product" }
* }
*/
Error handling strategies
handleErrors 매개변수를 사용하여 오류 처리 방식을 커스터마이즈할 수 있습니다:
커스텀 오류 메시지:
const responseFormat = toolStrategy ( ProductRating , {
handleError: "1-5 사이의 유효한 평점과 코멘트를 제공해주세요."
)
// 오류 메시지는 다음과 같이 표시됩니다:
// { role: "tool", content: "1-5 사이의 유효한 평점과 코멘트를 제공해주세요." }
특정 예외만 처리:
import { ToolInputParsingException } from "@langchain/core/tools" ;
const responseFormat = toolStrategy ( ProductRating , {
handleError : ( error : ToolStrategyError ) => {
if ( error instanceof ToolInputParsingException ) {
return "1-5 사이의 유효한 평점과 코멘트를 제공해주세요." ;
}
return error . message ;
}
)
// 검증 오류만 기본 메시지로 재시도됩니다:
// { role: "tool", content: "Error: Failed to parse structured output for tool 'ProductRating': ...\n Please fix your mistakes." }
여러 예외 타입 처리:
const responseFormat = toolStrategy ( ProductRating , {
handleError : ( error : ToolStrategyError ) => {
if ( error instanceof ToolInputParsingException ) {
return "1-5 사이의 유효한 평점과 코멘트를 제공해주세요." ;
}
if ( error instanceof CustomUserError ) {
return "커스텀 사용자 오류입니다." ;
}
return error . message ;
}
)
오류 처리 없음:
const responseFormat = toolStrategy ( ProductRating , {
handleError: false // 모든 오류 발생
)