OpenAI 호환 API와 JSON Schema 검증을 활용한 n8n 휴먼 승인 워크플로
OpenAI 호환 API로 구조화된 데이터를 추출하고, 결과를 JSON Schema에 맞춰 검증한 뒤, 민감한 도구가 실행되기 전에 사람의 승인을 요구하는 n8n 워크플로를 구축합니다.
목차
결정: 추출이 아니라 작업을 승인하세요
송장, 지원 티켓, 양식, 인바운드 요청에서는 필드를 추출하는 일 자체보다 그 이후에 일어나는 일이 위험한 경우가 많습니다. 고객 레코드를 생성하거나, 상태를 변경하거나, 외부 메시지를 보내거나, 데이터를 삭제하는 작업이 이에 해당합니다.
따라서 견고한 n8n 설계는 다음 세 가지 관문을 사용합니다.
- 추출: OpenAI 호환 API가 구조화된 데이터를 반환합니다.
- 검증: n8n이 데이터가 JSON Schema를 준수하는지 확인합니다.
- 승인: 사람이 승인한 후에만 n8n AI Agent가 중대한 영향을 미치는 도구를 호출할 수 있습니다.
이렇게 하면 형식이 잘못된 데이터가 검토자에게 전달되는 것을 막고, 승인된 실행을 모델 출력과 분리할 수 있습니다.
OneMux는 하나의 OpenAI 호환 API를 통해 주요 AI 모델에 액세스할 수 있도록 제공합니다. 엔드포인트와 선택한 모델의 문서에 n8n 구성에 필요한 요청 형식과 매개변수 지원이 명시되어 있다면 이를 모델 액세스 경로로 사용할 수 있습니다. 이 글에서는 OneMux와 n8n의 통합이 테스트되었다고 주장하지 않습니다.
사전 요구 사항
다음이 필요합니다.
- HTTP Request, Code, 그리고 해당하는 경우 AI Agent 노드에 액세스할 수 있는 n8n 인스턴스
- n8n 설정에서 지원하는 승인 채널(예: n8n Chat, Slack, Telegram, 이메일 또는 기타 문서화된 채널)
- OpenAI 호환 API 액세스. OneMux를 사용하는 경우 OneMux 빠른 시작 가이드부터 확인하고, 현재 엔드포인트, 인증 방식, 모델 식별자, 지원되는 요청 매개변수를 OneMux 문서에서 확인하세요.
- 추출하려는 객체를 설명하는 JSON Schema
- 사람의 검토 없이 실행되어서는 안 되는 대상 도구(예: CRM 업데이트 또는 메시지 전송 작업)
모든 OpenAI 호환 엔드포인트가 모든 구조화된 출력 기능을 지원한다고 가정하지 마세요. response_format, JSON Schema, 도구 호출, 그리고 선택한 특정 모델에 대한 지원 여부를 확인하세요. OneMux 모델 디렉터리를 통해 사용 가능한 모델 옵션을 검토할 수 있지만, 그것만으로 특정 n8n 노드 구성에 대한 지원이 입증되는 것은 아닙니다.
권장 n8n 워크플로
실용적인 워크플로에서는 다음 노드를 사용할 수 있습니다.
- Webhook 또는 다른 트리거가 원문을 수신합니다.
- HTTP Request가 호환 모델 엔드포인트로 텍스트를 전송합니다.
- Code가 반환된 객체를 파싱하고 검증합니다.
- IF가 유효하지 않은 결과를 오류 또는 수동 수정 경로로 보냅니다.
- AI Agent가 검증된 객체를 받고 중대한 영향을 미치는 도구에 액세스합니다.
- Human review가 해당 도구 실행 전에 워크플로를 일시 중지합니다.
- Approved tool이 레코드를 작성하거나 메시지를 보냅니다.
추출 요청에는 워크플로에 필요한 필드만 요청해야 합니다. 지원 요청을 위한 간단한 예시 스키마는 다음과 같습니다.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": ["category", "priority", "summary", "customer_email"],
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "account", "other"]
},
"priority": {
"type": "string",
"enum": ["low", "normal", "high", "urgent"]
},
"summary": {
"type": "string",
"minLength": 1
},
"customer_email": {
"type": "string",
"format": "email"
}
}
}
OpenAI 호환 요청 구성
HTTP Request 노드에서는 제공업체 문서에 안내된 기본 URL과 인증 방법을 사용하세요. 계정과 리전에 맞는 URL인지 확인하지 않았다면 제공업체별 URL을 하드코딩하지 마세요.
아래 요청 형식은 예시일 뿐입니다. response_format 및 JSON Schema 구조가 허용되는지는 선택한 엔드포인트, 모델, n8n 구성에 따라 달라집니다.
{
"model": "YOUR_DOCUMENTED_MODEL_ID",
"messages": [
{
"role": "system",
"content": "Extract the requested fields. Do not guess missing values. Return only an object matching the supplied schema."
},
{
"role": "user",
"content": "{{$json.source_text}}"
}
],
"temperature": 0,
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "support_request",
"strict": true,
"schema": {
"type": "object",
"additionalProperties": false,
"required": ["category", "priority", "summary", "customer_email"],
"properties": {
"category": {"type": "string"},
"priority": {"type": "string"},
"summary": {"type": "string"},
"customer_email": {"type": "string"}
}
}
}
}
}
이 예시에서는 의도적으로 플레이스홀더 모델 ID를 사용합니다. 선택한 엔드포인트와 호환된다고 문서에 명시된 모델을 선택하세요. 엄격한 JSON Schema 출력을 사용할 수 없다면, 검증 경로에서 규격을 준수하지 않는 응답을 안전하게 거부할 수 있는 경우에만 지원되는 JSON 모드를 사용하세요. JSON 모드만으로는 스키마 검증과 동일하지 않습니다.
실행 전에 응답 검증
제공업체마다 응답에서 생성된 콘텐츠를 배치하는 필드가 다를 수 있습니다. 파서를 작성하기 전에 n8n에서 실제 응답 하나를 확인하세요. 다음 Code 노드는 모델이 message.content에 JSON 문자열을 반환했다고 가정합니다. 실제로 받는 응답에 맞게 경로를 조정하세요.
const raw = $json.choices?.[0]?.message?.content;
if (typeof raw !== 'string') {
throw new Error('Model response did not contain message.content as a string');
}
let extracted;
try {
extracted = JSON.parse(raw);
} catch (error) {
throw new Error('Model returned invalid JSON');
}
const required = ['category', 'priority', 'summary', 'customer_email'];
const missing = required.filter((key) => extracted[key] === undefined || extracted[key] === '');
const validCategory = ['billing', 'technical', 'account', 'other'].includes(extracted.category);
const validPriority = ['low', 'normal', 'high', 'urgent'].includes(extracted.priority);
const validEmail = typeof extracted.customer_email === 'string' &&
/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(extracted.customer_email);
if (missing.length || !validCategory || !validPriority || !validEmail) {
throw new Error('Extracted object failed application validation');
}
return [{ json: { extracted } }];
프로덕션 환경에서는 n8n 배포 환경에서 허용되는 경우 이 간단한 검사를 유지 관리되는 JSON Schema 검증기로 교체하세요. 요청에 사용하는 스키마와 검증에 적용하는 스키마는 함께 버전 관리해야 합니다. 다운스트림 시스템에서 개정판을 구분해야 한다면 출력에 스키마 버전을 추가하세요.
AI Agent 도구에 사람의 승인 추가
검증된 객체를 AI Agent의 컨텍스트로 사용하세요. 광범위한 데이터베이스 액세스 대신 CreateSupportTicket과 같이 범위가 제한된 도구를 Agent에 제공하세요. AI Agent의 Tools Panel에서 해당 도구에 대한 사람의 검토를 구성합니다.
n8n 문서에 따르면 Agent가 검토가 필요한 도구를 시도하면 워크플로가 일시 중지됩니다. 검토자는 호출을 승인하여 제안된 입력으로 도구가 실행되도록 하거나, 이를 거부하여 작업을 취소할 수 있습니다. n8n은 기본 제공 채팅 인터페이스와 Slack, Telegram, Discord, Teams, 이메일, WhatsApp, Google Chat, Outlook 이메일 등의 통합을 포함해 여러 승인 채널을 지원합니다. 현재 설정 단계와 채널 세부 정보는 공식 n8n 휴먼 인 더 루프 문서에서 확인하세요.
유용한 승인 메시지에는 제안된 작업과 매개변수가 표시되어야 합니다.
The AI wants to use {{ $tool.name }} with the following parameters:
{{ JSON.stringify($tool.parameters, null, 2) }}
소스 문서에서는 이 검토 컨텍스트에 $tool.name과 $tool.parameters를 사용한다고 설명합니다. 검토자가 추가 컨텍스트를 필요로 하는 경우 원래 요청이나 티켓 참조를 포함하고, 메시지를 읽기 쉽게 유지하세요.
또한 Agent 시스템 프롬프트에서 검토 동작을 설명해야 합니다.
The CreateSupportTicket tool requires human approval. If approval is denied, do not retry automatically. Tell the user that the action was not completed and explain what information or correction is needed.
제한 사항 및 문제 해결
모델이 Markdown 또는 추가 텍스트를 반환하는 경우
엔드포인트가 전송한 구조화된 출력 매개변수를 지원하는지 확인하세요. 지원하지 않는다면 지원되지 않는 매개변수를 제거하고 지시를 구체화하며, Code 노드 검증을 강제 관문으로 유지하세요. 검증되지 않은 객체를 쓰기 도구로 절대 보내지 마세요.
n8n이 예상한 응답 필드를 찾지 못하는 경우
HTTP Request 출력을 확인하고 파서를 업데이트하세요. OpenAI 호환 API는 요청 규칙을 공유할 수 있지만 응답 세부 정보와 지원되는 매개변수는 서로 다를 수 있습니다.
승인 요청이 너무 모호한 경우
범위가 제한된 도구를 사용하고 승인 메시지에 $tool.name과 $tool.parameters를 포함하세요. 검토자에게 “이 요청을 처리하세요”와 같이 불투명한 지시를 승인하도록 요청하지 마세요.
거부된 도구 호출로 인해 루프가 발생하는 경우
Agent 시스템 프롬프트에 명시적인 거부 동작을 추가하고, 거부 시 작업 경로를 종료하거나 추가 확인 단계로 라우팅하도록 워크플로를 구성하세요. n8n 문서에서는 승인이 필요한 도구와 거부에 대해 Agent가 어떻게 응답해야 하는지를 설명할 것을 권장합니다.
검토자가 잘못된 데이터를 승인하는 경우
스키마가 유효하다고 해서 의미적으로 올바르다는 뜻은 아닙니다. 원문 발췌, 추출된 필드, 의도한 작업을 함께 표시하세요. 영향이 큰 워크플로에서는 검토자가 민감한 필드를 별도로 확인하도록 요구하세요.
결론
구조화된 추출을 위한 가장 안전한 n8n 패턴은 “모델이 직접 작성하도록 두는 것”이 아닙니다. 제약된 객체로 추출하고, 이를 검증한 다음, 외부 세계를 변경하는 도구 앞에 사람의 승인을 배치하세요. OpenAI 호환 API는 모델 액세스를 간소화할 수 있고, n8n은 오케스트레이션과 승인 제어 기능을 제공합니다. OneMux를 사용할 때는 문서에 안내된 호환 엔드포인트와 모델 매개변수를 사용하고, 자체 환경에서 구성을 검증하며, 지원되지 않는 구조화된 출력 기능을 중단하거나 별도로 검증된 응답 경로로 대체해야 하는 신호로 취급하세요.
FAQ
n8n에서 OneMux를 OpenAI 호환 API로 사용할 수 있나요?
OneMux 엔드포인트와 선택한 모델이 n8n 구성에 필요한 요청 형식과 매개변수를 지원한다면 가능성이 있습니다. 이 글에서는 OneMux와 n8n의 통합이 테스트되었다고 주장하지 않습니다. 현재 엔드포인트, 인증 방식, 모델 ID, 구조화된 출력 지원 여부를 OneMux 문서에서 확인하세요.
사람의 승인은 JSON Schema 검증 전과 후 중 언제 이루어져야 하나요?
일반적으로 검증 후에 이루어져야 합니다. 검토자는 형식이 잘못되었거나 불완전한 모델 출력이 아니라 구조적으로 유효한 제안 작업을 확인해야 합니다. 검증이 값의 의미적 정확성을 보장하는 것은 아니므로 검토자는 추출된 필드를 원문과 비교해야 할 수도 있습니다.
JSON 모드가 응답이 내 스키마와 일치함을 보장하나요?
아니요. JSON 모드는 일반적으로 JSON 형식을 다루지만 모든 속성, 유형, 열거형 또는 필수 필드 제약 조건을 보장하지는 않습니다. 가능한 경우 지원되는 JSON Schema 응답 형식을 사용하고, 중대한 영향을 미치는 도구를 호출하기 전에 n8n에서 동일한 스키마를 독립적으로 적용하세요.
어떤 n8n 도구에 사람의 승인을 요구해야 하나요?
외부 커뮤니케이션을 보내거나, 레코드를 수정하거나, 데이터를 삭제하거나, 구매를 진행하거나, 되돌릴 수 없거나 가치가 큰 기타 작업을 트리거하는 도구를 우선 대상으로 삼으세요. 위험도와 규정 준수 요구 사항에 따라 읽기 전용 도구에는 동일한 수준의 검토가 필요하지 않을 수 있습니다.
검토자가 n8n 도구 호출을 거부하면 어떻게 되나요?
n8n 문서에 따르면 작업이 취소되고 AI에 거부 사실이 전달됩니다. Agent 프롬프트에서 자동으로 재시도하지 말고 사용자에게 알리거나 대안을 제안하거나 추가 정보를 요청하도록 지시해야 합니다.
관련 글
Guides
사람의 승인과 테스트 검증을 포함한 n8n 코드 변경 워크플로 구축
저장소 변경안을 제안하고, 사람이 쓰기 작업을 승인한 뒤, 결과 커밋을 테스트로 검증하는 n8n 워크플로를 설계합니다.
Guides
Human Approval과 OpenAI-Compatible API를 활용한 n8n 문서 Q&A 워크플로 구축
OneMux를 통해 문서 출처를 표시하고, 필요한 경우 사람의 승인을 거치며, 조건부로 호환되는 OpenAI 스타일 모델 엔드포인트에 연결하는 실용적인 n8n 설계를 소개합니다.
Guides
GPT 6.1 Terra 비용 및 컨텍스트 가이드: 신뢰할 수 있는 JSON 추출
OneMux에서 JSON Schema 검증을 활용한 구조화 추출 시 GPT 6.1 Terra의 작업 비용을 추정하고 컨텍스트, 재시도, 출력 토큰을 제한하는 방법을 알아봅니다.
Guides
도구 호출, 사람 승인, 실행 제한을 적용한 LangGraph 고객 지원 에이전트 구축
고객 지원 분류를 위한 실용적인 LangGraph 패턴을 살펴봅니다. 요청을 라우팅하고 조회 도구를 호출하며, 환불을 사람의 승인 대기 상태로 일시 중지하고 그래프 실행 범위를 제한하는 방법을 다룹니다.