| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 |
- ai에이전트
- 개발환경
- MCP
- 오픈모델
- AI 에이전트
- Android Studio
- OpenAI
- 클로드 API
- claudecode
- 바이브코딩
- 안드로이드
- 개발 생산성
- 클로드코드
- 무료 LLM
- LLM
- 카드 없이
- claude code
- 실무
- 무료 ai
- 안드로이드 스튜디오
- 무료로 시작하기
- AI 에이전트 개발
- 자동화
- AI 코딩
- Claude
- 개발자 도구
- Gemini
- ai 뉴스
- Android
- 홍드로이드
- Today
- Total
홍드로이드의 야매코딩
AI 도구 결과 돌려주기 — 순서만 바꿔도 오류가 납니다 본문

에이전트를 직접 만들면 반드시 거치는 고리가 있습니다. 모델이 「이 도구를 이런 값으로 불러 줘」라고 하면, 우리가 실제로 실행하고 그 결과를 돌려줍니다. 그리고 모델이 이어서 답을 만듭니다. 개념은 단순한데 AI 도구 결과 돌려주기에서 막히는 분이 많습니다.
이유는 넣는 자리와 순서가 정해져 있기 때문입니다. 어기면 400 오류가 나고, 오류 문구만 봐서는 뭘 고쳐야 할지 잘 안 보입니다. 그리고 문서가 별도 경고로 달아 둔 것이 하나 더 있는데, 이게 보안 관점에서 훨씬 중요합니다.
📌 30초 요약
- 도구 결과가 맨 앞이어야 합니다. 글을 앞에 두면 400 오류입니다.
- 사이에 다른 메시지를 끼울 수 없습니다. 도구 사용 바로 다음이어야 합니다.
- 서버 쪽 도구가 미완결이면 결과만 보내세요. 뒤에 글을 붙이면 턴이 일찍 끝납니다.
- 도구 결과는 대개 남이 쓴 글입니다. 웹페이지·메일·업로드 — 지시가 숨어 있을 수 있습니다.
- 오류는 상태 코드가 아니라 표시로 알립니다. 그리고 뭘 하라고 적어야 모델이 회복합니다.
① 순서가 정해져 있습니다
모델이 도구를 부르면 응답에 「도구 사용」 덩어리가 들어옵니다. 거기서 식별자·도구 이름·넘길 값 셋을 꺼내 실제로 실행한 뒤, 사용자 역할의 새 메시지로 결과를 돌려줍니다. 여기까지는 예상대로입니다.
문서가 「중요한 형식 요구사항」이라고 따로 묶어 둔 규칙이 셋 있습니다.
✗ 400 오류가 나는 형태
{
"role": "user",
"content": [
{ "type": "text", "text": "결과입니다:" }, ← 글이 앞에
{ "type": "tool_result", "tool_use_id": "..." }
]
}
✓ 맞는 형태
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "..." }, ← 결과가 먼저
{ "type": "text", "text": "다음은 뭘 할까요?" } ← 글은 뒤에
]
}
| 규칙 | 어기면 |
|---|---|
| 도구 결과는 도구 사용 바로 다음 메시지에 | 사이에 메시지를 끼우면 오류 |
| 결과 덩어리가 맨 앞, 글은 그 뒤에 | 글이 앞에 오면 400 |
| 부른 것마다 짝을 맞춰 돌려주기 | 짝 없는 호출이 있으면 오류 |
세 번째가 특히 헷갈립니다. 문서는 「도구 사용 식별자는 있는데 바로 뒤에 결과 덩어리가 없다」는 오류 문구를 그대로 인용하며, 그런 오류를 보면 형식부터 확인하라고 안내합니다. 도구 자체를 의심하다 시간을 버리기 쉬운 자리입니다.
참고로 이 구조는 다른 회사 방식과 다릅니다. 문서가 직접 비교하는데, 도구용 역할을 따로 두는 곳들과 달리 여기는 사용자·조수 두 역할 안에 도구가 섞여 들어가는 구조입니다. 다른 곳 코드를 그대로 옮기면 이 지점에서 걸립니다.
② 서버 쪽 도구가 섞이면 규칙이 더 좁아집니다
도구에는 두 종류가 있습니다. 우리가 실행하는 것과 서버가 알아서 실행하는 것. 후자는 결과가 응답에 그냥 들어와 있어서 우리가 손댈 게 없습니다.
문제는 둘이 한 응답에 섞여 올 때입니다. 서버 쪽 도구가 아직 안 끝난 상태로 우리 도구 호출과 함께 오는 경우가 있는데, 이때 규칙이 좁아집니다.
⚠️ 결과 덩어리만 보내야 합니다
아직 결과가 안 온 서버 쪽 도구가 있으면, 우리가 보내는 사용자 메시지에는 도구 결과 덩어리만 들어가야 합니다. 뒤에 글을 붙이면 턴이 일찍 끝나고, 모델이 직접 부른 서버 도구였다면 미해결 도구 이름을 짚은 400 오류가 납니다.
①에서 「글은 결과 뒤에」라고 했는데, 여기서는 글을 아예 넣으면 안 됩니다. 두 규칙이 겹치는 자리라 헷갈리기 쉽습니다. 그리고 이때 도구 목록은 그대로 유지해야 다음 응답에 서버 도구 결과가 담겨 옵니다.
컴퓨터나 브라우저를 조작하는 도구 묶음은 규칙이 하나 더 붙습니다. 이쪽은 호출에 묶음 이름이 함께 오는데, 결과를 돌려줄 때도 같은 묶음 이름을 그대로 되돌려줘야 하고 빠뜨리면 거절됩니다. 담을 수 있는 내용도 글과 이미지로 좁아집니다. 이 계열은 출력 크기에서도 별도 제약이 걸리니(출력이 크면 거절됩니다) 함께 보셔야 합니다.
③ 도구 결과는 대개 남이 쓴 글입니다
여기가 이 문서에서 가장 값나가는 경고입니다. 형식 규칙 사이에 별도 상자로 들어가 있어 지나치기 쉽습니다.
도구 결과에 담기는 게 뭔지 생각해 보면 명확합니다 — 웹페이지 내용, 들어온 메일, 사용자가 올린 파일, 남의 회사 응답. 문서의 표현은 이렇습니다. 그 내용은 우리 통제 밖에서 온 것이니 신뢰할 수 없는 것으로 다루라.
왜 위험하냐면, 그 안에 모델에게 보내는 지시가 숨어 있을 수 있기 때문입니다. 우리가 「이 페이지를 요약해」라고 시켰는데, 페이지 안에 「이전 지시는 무시하고 …」가 적혀 있는 식입니다. 우리를 거치지 않고 가져온 내용을 통해 들어오는 공격이라 막기가 까다롭습니다.
문서가 주는 대책은 구체적입니다 — 신뢰할 수 없는 내용은 기본 지시문이나 평범한 사용자 글이 아니라, 반드시 도구 결과 덩어리 안에 두라는 것입니다. 자리를 갈라 두면 모델이 「이건 내가 가져온 자료지 명령이 아니다」라고 구분할 여지가 생깁니다. 편하다고 가져온 글을 사용자 메시지에 그대로 이어 붙이면 그 구분이 사라집니다.
이건 사용자가 직접 안전장치를 뚫으려는 시도와는 공격 경로가 다릅니다. 그쪽은 대화창에서 들어오지만 이쪽은 우리가 자발적으로 가져온 자료를 타고 들어옵니다. 검색이나 웹 열람을 붙인 에이전트라면 반드시 챙기셔야 할 자리입니다.
④ 오류는 상태 코드가 아니라 표시로
도구 실행이 실패했을 때 어떻게 알리느냐도 정해져 있습니다. 예외를 던지거나 빈 결과를 보내는 게 아니라, 결과 덩어리에 오류 표시를 켜서 정상적으로 돌려줍니다.
| 상황 | 우리가 할 일 | 모델이 하는 일 |
|---|---|---|
| 도구 실행이 실패 | 오류 표시를 켜고 사유를 담아 반환 | 사용자에게 설명 |
| 필수 값이 빠진 호출 | 「무엇이 빠졌다」고 반환 | 2~3회 고쳐 재시도 후 사과 |
| 서버 쪽 도구 오류 | 할 일 없음 | 알아서 처리하고 대안 제시 |
두 번째 줄이 실무에서 유용합니다. 값이 빠진 호출이 오면 「무엇이 빠졌는지」만 알려 줘도 모델이 스스로 2~3회 고쳐 다시 시도합니다. 우리가 재시도 논리를 짜지 않아도 되는 구간이 있다는 뜻입니다.
다만 문서가 붙인 요령이 있습니다 — 지시적인 오류 메시지를 쓰라는 것입니다. 「실패」 같은 뭉뚱그린 문구 대신 무엇이 잘못됐고 다음에 뭘 해야 하는지를 담으라고요. 예시로 든 문구가 「한도 초과. 60초 뒤 재시도」입니다. 이 정도면 모델이 추측하지 않고 회복합니다.
값이 빠지는 문제를 아예 없애는 길도 있습니다. 도구 정의에 엄격 모드를 켜면 넘어오는 값이 우리가 정한 형태와 항상 맞는다고 문서가 보장합니다. 다만 도구를 많이 붙이면 그 자체가 고정비이니(켠다고 무조건 싸지지 않습니다) 켜는 김에 목록도 한 번 정리하시는 게 좋습니다.
⑤ 자주 묻는 질문 (FAQ)
Q. 이걸 직접 다 짜야 하나요?
아닙니다. 공식 라이브러리에 이 고리를 대신 돌려 주는 실행기가 있어서, 결과 형식과 재시도까지 알아서 처리합니다. 문서도 직접 다루는 방식은 「세밀한 제어가 필요할 때」 쓰라고 안내합니다. 다만 형식 규칙을 알아 두면 실행기가 뱉는 오류를 읽을 수 있습니다.
Q. 결과를 비워서 보내도 되나요?
됩니다. 내용 없이 식별자만 담은 결과도 유효한 형태로 문서에 예시가 있습니다. 반환값이 없는 동작을 실행했을 때 쓰는 형태입니다. 중요한 건 부른 것마다 짝이 맞는 것이지 내용이 채워지는 게 아닙니다.
Q. 결과에 이미지나 문서를 넣을 수 있나요?
넣을 수 있습니다. 글만이 아니라 이미지·문서·검색 결과 형태를 덩어리로 담을 수 있습니다. 다만 컴퓨터·브라우저 조작 도구 계열은 글과 이미지로 제한되니 그쪽은 따로 확인하세요.
Q. 400 오류가 났는데 뭘 먼저 볼까요?
순서대로 확인하세요. ① 결과 덩어리가 맨 앞에 있나 ② 도구 사용 바로 다음 메시지인가 ③ 부른 것마다 짝이 맞나 ④ 아직 안 끝난 서버 쪽 도구가 있는데 글을 같이 넣지 않았나 ⑤ 조작 도구라면 묶음 이름을 되돌려줬나. 대부분 이 다섯에서 걸립니다.
✨ 정리
도구 결과 돌려주기는 형식이 반, 태도가 반입니다. 형식은 외우면 됩니다 — 결과가 앞, 글은 뒤, 사이엔 아무것도. 태도 쪽이 더 중요한데, 도구가 가져온 글은 대개 남이 쓴 것이라는 사실입니다. 편하다고 사용자 메시지에 이어 붙이지 말고 결과 덩어리 안에 가둬 두세요. 자리를 갈라 두는 것만으로도 「자료」와 「명령」이 구분됩니다.
더 읽을거리: AI 개발 비용·도구 총정리 허브
출처: Anthropic 공식 문서 「Handle tool calls」(platform.claude.com, 2026년 9월 확인). 도구 결과가 도구 사용 바로 다음 메시지에 와야 한다는 점, 결과 덩어리가 내용 배열의 맨 앞이어야 하고 글은 그 뒤에 와야 한다는 점과 위반 시 400, 미완결 서버 도구가 있을 때는 결과 덩어리만 보내야 하며 글을 붙이면 턴이 일찍 끝나고 미해결 도구를 짚은 400이 난다는 점, 조작 도구 계열의 묶음 이름 반환 의무와 내용 제한, 도구 결과를 신뢰할 수 없는 내용으로 다루고 기본 지시문이나 사용자 글이 아니라 결과 덩어리 안에 두라는 경고, 오류 표시를 통한 오류 전달과 지시적 메시지 권고, 값이 빠진 호출에 대해 2~3회 자가 재시도 후 사과, 엄격 모드로 형태 일치를 보장한다는 설명, 서버 도구 오류는 우리가 처리하지 않아도 된다는 점, 실행기를 쓰면 이 고리를 대신 돌려 준다는 안내는 모두 해당 문서에 명시된 내용입니다. 「400 오류 점검 5단계」는 문서의 규칙들을 필자가 순서로 정리한 것이며 문서에 그런 목록이 있는 것은 아닙니다.
'AI & Vibe Coding' 카테고리의 다른 글
| Claude Code 설정 키 정리 — 파일별 적용 범위·폐기 키·기업 제한 (0) | 2026.09.09 |
|---|---|
| ChatGPT 이미지 2.5 출시 — 스케치 기능·API 가격·모델 비교 (1) | 2026.09.09 |
| 국가 AI 5조 프론티어 사업 — 돈은 섰는데 방식이 백지입니다 (0) | 2026.09.08 |
| AI 감사 기록 남기기 — 켜 둬도 대화 내용은 안 남습니다 (0) | 2026.09.08 |
| AI 고객상담 챗봇 만들기 — 기본 지시문에 다 넣으면 안 됩니다 (0) | 2026.09.08 |
