← 노드 한 장 전체#76 · Custom Code Tool
Custom Code Tool
할인 합계, AI가 맞혔다고 끝내면 안 되죠
이 글은 이런 분께AI Agent가 스스로 답한 것인지 연결된 코드 도구를 실제 호출했는지 확인하고 싶은 n8n 입문자

1분 영상은 @workflow.hanjang 에 순서대로 공개돼요
할인 합계, AI가 맞혔다고 끝내면 안 되죠.
직접 쓴 샘플 단가 50,000원·3개·할인 10%를 Custom Code Tool의 고정 JavaScript로 계산했습니다. 실제 query와 함수 response "135000"을 확인한 다음 AI 최종 답의 숫자와 대조했어요.
먼저 결과부터
실제 #74954: query={"unitPrice":50000,"quantity":3,"discountPercent":10}, 도구 response는 문자열 "135000". AI 답에도 135000원이 포함됐지만 지정한 짧은 형식은 지키지 않았습니다. gpt-4.1-mini·온도 0, provider 응답 2회(입력 633/출력 59/총 692토큰)를 모두 기록했습니다. single string 반환 요구는 실제 schema에서 확인했습니다. 공식 문서 https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolcode/
우리가 실제로 돌린 기록 · 실행 #74954 · 2026-10-30
우리가 실제로 돌린 기록 · 실행 #74954 · 2026-10-30
따라 하기
실제로 실행한 워크플로우를 바탕으로 정리했어요. 계정·식별자는 공개용 값으로 치환했고, 그 밖의 차이는 아래 주의사항에 표시했어요. n8n 캔버스에서 +를 눌러 노드를 순서대로 추가하고 같은 값을 넣으면 돼요. 빨간 제목이 이번 편의 주인공 노드예요. 표 왼쪽은 n8n 편집기에 보이는 칸 이름, 오른쪽은 다운로드 JSON의 설정값이에요. 직접 입력하기 번거로우면 JSON을 받아 ⋯ → Import from File로 가져오세요.
Step 1. Manual Trigger 노드 추가이름: Run manually
설정 없이 그대로 추가해요.
Step 2. AI Agent 노드 추가이름: AI Agent
| Source for Prompt (User Message) | Define below |
| Prompt (User Message) | 직접 작성한 가상 샘플입니다. 단가 50000원, 수량 3개, 할인 10%의 합계를 calculate_discount_total 도구로 정확히 한 번 계산하세요. 도구 입력 query는 {"unitPrice":50000,"quantity":3,"discountPercent":10} JSON 문자열이어야 합니다. 배송비와 추가 세금은 없다고 가정합니다. 도구 결과를 받은 뒤 숫자와 원만 포함한 최종 답을 하세요. 스스로 계산한 값을 도구 결과 대신 사용하지 마세요. |
| Options › System Message | 당신은 샘플 계산을 도구에 맡기는 실습 Agent입니다. 사용 가능한 도구는 calculate_discount_total입니다. 지시된 JSON 문자열을 도구에 보내고 관측한 도구 반환값만 최종 답에 사용하세요. 내부 사고 과정은 출력하지 마세요. |
| Options › Max Iterations | 3 |
| Options › Return Intermediate Steps | 꺼짐 |
| Options › Enable Streaming | 꺼짐 |
| Options › Force Tool Call on First Iteration | 켜짐 |
Step 3. OpenAI Chat Model 노드 추가이름: OpenAI Chat Model
| Model | gpt-4.1-mini |
| Options › Sampling Temperature | 0 |
| Options › Maximum Number of Tokens | 200 |
| Options › Max Retries | 0 |
Step 4. Code Tool 노드 추가이름: calculate_discount_total
| Description | 샘플 할인 합계를 고정 JavaScript 산술로 계산합니다. query는 unitPrice, quantity, discountPercent 숫자를 담은 JSON 문자열이어야 합니다. 예: {"unitPrice":50000,"quantity":3,"discountPercent":10}. 반환값은 합계 숫자의 문자열입니다. 배송비와 추가 세금은 포함하지 않습니다. |
| Language | JavaScript |
| JavaScript | // 직접 작성한 가상 샘플. JSON 숫자를 검증하고 고정 산술만 수행합니다.
const p = JSON.parse(query);
const unitPrice = Number(p.unitPrice);
const quantity = Number(p.quantity);
const discountPercent = Number(p.discountPercent);
if (!Number.isFinite(unitPrice) || unitPrice <= 0 || !Number.isInteger(quantity) || quantity <= 0 || !Number.isFinite(discountPercent) || discountPercent < 0 || discountPercent > 100) {
throw new Error('Invalid numeric inputs');
}
const total = unitPrice * quantity * (1 - discountPercent / 100);
if (!Number.isFinite(total)) throw new Error('Invalid total');
return String(total); |
| Specify Input Schema | 꺼짐 |
가져와서 쓸 때 확인할 것
- [실제 확인] 설치 표시 이름은 Code Tool, 공식 문서 이름은 Custom Code Tool이며 실제 type은 @n8n/n8n-nodes-langchain.toolCode입니다.
- [실제 확인] query JSON 문자열을 JSON.parse로 읽고 Number 유한수·범위 검사와 고정 산술만 수행했습니다. eval·동적 코드·모듈·파일·네트워크·실서비스 접근은 없습니다. 이는 Code Tool 자체의 일반 안전 보장이 아닙니다.
- [스키마 확인] JavaScript hint는 query 입력과 single string 반환을 요구합니다. 실제 response는 문자열 135000이었습니다. Specify Input Schema는 껐습니다.
- [실제 확인] 실제 도구 입력 {"unitPrice":50000,"quantity":3,"discountPercent":10}, 도구 실행 1회, AI 최종 출력 1 item을 확인했습니다. 최종 답만 맞았다는 이유로 도구 실행 성공을 추정하지 않았습니다.
- [실제 확인] 모델 provider 응답 기록은 tool_calls와 stop의 2회이며 323+369=692토큰(입력 633, 출력 59)을 모두 합산했습니다. Max Retries 0, 비용 추정 없음.
- [실제 한계] AI 답의 숫자는 도구 결과와 같지만 숫자와 원만 쓰라는 출력 형식은 지키지 않았습니다. 이 실패를 실제 AI 답 그대로 영상·실습에 보존했습니다.
- [한계] 이번 샘플의 배송비·추가 세금 없음 가정이며 통화 반올림·큰 수·상용 권한·오류 처리까지 구현한 계산기가 아닙니다. Number 변환 검사도 범용 보안 검증으로 일반화하지 않습니다.
- [공개 범위] Return Intermediate Steps 끔. 실제 query·함수 결과·최종 답·사용량만 공개 요약하고 thinking/사고 로그는 공개하지 않았습니다.
- YOUR_… 표시를 내 값으로 바꾸고, 계정이 필요한 서비스 노드만 자격 증명을 연결하세요. 그런 칸이나 노드가 없는 예제는 추가 계정 없이 실행할 수 있어요.
노드의 모든 옵션은 n8n 공식 문서에서 볼 수 있어요.