요약 답변
Gemini 3 및 이후 모델(gemini-4-argon, gemini-3.8-flash, gemini-3.1-pro-preview 등)에서 멀티턴 함수 호출을 실행할 때, thought signature(thoughtSignature)와 관련된 두 가지 유형의 400 오류가 발생하며, 각각 다른 해결 방법이 필요합니다:
OpenAI 호환
/v1/chat/completions 엔드포인트를 통해 호출하는 경우, 이 내용은 적용되지 않습니다: 게이트웨이가 서명을 관리하므로 표준 tool_calls / tool 메시지만 사용하시면 됩니다.
두 가지 오류 구분하기
누락된 서명
parts 배열 내 해당 인덱스가 명시되어 있습니다. 이는 Gemini 3 제품군에 대해 모델 제공업체가 적용하는 엄격한 규칙입니다: 현재 턴의 모든 functionCall 파트에는 반드시 서명이 포함되어야 합니다. 하나라도 누락되면 모든 라우트에서 400 오류로 실패하며, 재시도해도 해결되지 않습니다.
유효하지 않거나 손상된 서명
이 문제가 발생하는 원인
tools가 활성화되면 Gemini 3 모델은 각functionCall와(과) 동일한 파트에 암호화된 thoughtSignature을(를) 첨부하여 해당 단계의 추론 상태를 기록합니다. 다음 요청 시 모델이 추론 체인을 이어가려면 이 값이 필요하므로, 제공업체는 이 값을 변경 없이 그대로 다시 전송하도록 요구합니다.
누락: 클라이언트가 파트를 재구성함
가장 흔한 원인입니다. 커스텀 프레임워크나 미들웨어가 대화 기록을 조합할 때
functionCall의 name 및 args만 유지하고 형제 thoughtSignature을(를) 누락하거나, 스트리밍 청크를 재조합하면서 서명을 병합하지 않는 경우입니다.누락: 대화 기록이 압축되거나 재작성됨
클라이언트가 컨텍스트를 잘라내거나 요약했거나, 여러 파트를 하나로 병합하면서 서명이 함께 유실되었습니다.
유효하지 않음: 대화 도중 라우트가 변경됨
첫 번째 턴들은 라우트 A에서 처리되었으나 이후 턴들이 라우트 B로 전달되었고, 라우트 B가 라우트 A의 서명을 인식하지 못하는 경우입니다. 이러한 전환은 사용자가 그룹이나 키를 변경했거나 자동 장애 조치로 인해 발생할 수 있습니다.
유효하지 않음: 대화 도중 모델이 변경됨
동일한 대화 내에서 gemini-3.8-flash로 시작한 뒤 gemini-4-argon으로 전환하는 경우입니다. 서명은 모델 간에 호환되지 않습니다.
병렬 함수 호출의 경우 모델은 첫 번째
functionCall 파트에만 서명을 첨부합니다. 나머지 파트에는 원래 서명이 없으므로 임의로 생성하지 마십시오. 순차 호출(한 턴 내의 여러 단계)의 경우 모든 단계에 서명이 포함되어 있으며 모든 서명을 그대로 반환해야 합니다.해결 방법 1: 서명 누락, 클라이언트의 히스토리 재생 방식 변경
1
모델 응답 전체를 있는 그대로 다시 전달하십시오
공식
google-genai SDK를 사용하는 경우 단순히 contents.append(response.candidates[0].content)하면 되며, function_call 필드만 별도로 추출하지 마십시오. 직접 작성하는 REST 요청의 경우, 두 번째 요청의 contents에 있는 모델 턴은 다음과 같아야 합니다:thoughtSignature 및 functionCall은 두 개의 파트가 아니라 동일한 파트의 두 필드입니다.2
프레임워크나 미들웨어가 해당 필드를 제거하는지 확인하십시오
LangChain, 커스텀 에이전트 프레임워크, 또는 OpenAI-to-Gemini 변환 레이어를 사용하는 경우 두 번째 턴의 실제 요청 본문을 출력하여
thoughtSignature가 여전히 존재하는지 확인하십시오. 오류 메시지의 position N은 parts[N]이므로 해당 부분을 직접 확인하십시오.3
일부 모델이 이를 허용하는 것에 의존하지 마십시오
서명 누락을 얼마나 엄격하게 적용하는지는 모델과 라우트마다 다릅니다. 일부는 그대로 통과시키지만, 다른 일부는 400을 반환합니다. 동일한 코드가 gemini-3.8-flash에서는 항상 정상 작동하다가 gemini-4-argon에서 중단된다면, 서명이 애초에 전송된 적이 없었고 이전에는 단순히 묵인되었을 가능성이 높습니다. 제공업체가 요구하는 대로 서명을 반환해야 모든 모델에서 안정적으로 작동합니다.
해결 방법 2: 유효하지 않은 서명, 그대로 재전송하거나 새로 시작하기
1
그대로 한 번 재전송
APIYI 게이트웨이가 서명 400 오류를 수신하면 다른 경로로 자동 재시도하므로, 그대로 재전송하는 것만으로도 성공하는 경우가 많습니다. 변경할 필요는 없습니다.
2
여전히 400 오류 발생 시: 기록 턴에서 서명을 제거하고 재전송
thoughtSignature 필드를 대화 기록 내 모든 role: "model" 턴의 parts에서 제거한 후 재전송하십시오. 해당 턴들의 추론 컨텍스트가 손실되어 답변 품질이 약간 떨어질 수 있지만, 대화는 계속 이어갈 수 있습니다. 현재 턴은 절대 제거하지 말고 이전 기록 턴만 제거하십시오.3
또는 새 대화 시작하기
가장 간단하고 안정적인 방법입니다. 새 대화에서는 첫 번째 턴부터 모든 서명이 동일한 경로에서 생성됩니다.
4
대화당 하나의 모델, 하나의 키 사용
모델, 키 또는 그룹을 전환해야 할 때는 먼저 새 대화를 시작하십시오. 도구 호출 기록이 이미 있는 대화 내에서는 전환하지 마십시오.
OpenAI 호환 엔드포인트에서 서명 처리 불필요
/v1/chat/completions를 통해 Gemini를 호출할 때 tool_calls 메시지에는 서명 필드가 없습니다. 게이트웨이가 변환 과정에서 이를 저장하고 복원합니다. gemini-4-argon을 대상으로 한 테스트에서는 단일 호출, 두 개의 병렬 호출, 텍스트 및 호출 조합의 세 가지 형태 모두에서 2턴 대화가 성공했습니다. 표준 OpenAI 방식대로 tool_calls 및 tool 메시지를 반환하기만 하면 됩니다.
Codex와 같이 기본적으로
/v1/responses를 사용하는 클라이언트는 Gemini 모델이 아직 해당 엔드포인트를 지원하지 않으므로 채팅 프로토콜로 전환해야 합니다. Gemini 4 Argon 텍스트 생성을 참고하십시오.자주 묻는 질문
argon에서만 이 오류가 발생하고, flash는 항상 정상 작동했습니다. argon에 문제가 있는 것인가요?
argon에서만 이 오류가 발생하고, flash는 항상 정상 작동했습니다. argon에 문제가 있는 것인가요?
아닙니다. 서명을 반환하는 것은 전체 Gemini 3 제품군에 대한 제공자의 요구 사항입니다. 일부 모델의 라우트는 누락된 서명에 대해 비교적 관대할 뿐입니다. 엄격하게 검증하는 모델로 전환하면서 문제가 드러난 것일 뿐, 근본적인 원인은 클라이언트가 서명을 전혀 전송하지 않았기 때문입니다.
서명을 캐시하여 여러 대화에서 재사용할 수 있습니까?
서명을 캐시하여 여러 대화에서 재사용할 수 있습니까?
아닙니다. 서명은 해당 서명을 생성한 라우트 및 대화 컨텍스트 내에서만 유효합니다. 다른 대화로 복사하면 Invalid가 반환됩니다.
스트리밍 응답에서 서명은 어디에 있습니까?
스트리밍 응답에서 서명은 어디에 있습니까?
이를 전달하는 청크 내부의
functionCall와 동일한 파트에 있습니다. 스트림을 재조립할 때 히스토리에 다시 넣기 전에 이 필드를 functionCall와 함께 최종 모델 응답으로 병합하십시오.일반 텍스트 턴에도 서명이 필요합니까?
일반 텍스트 턴에도 서명이 필요합니까?
엄격하게 그렇지는 않습니다. 제공자는
functionCall 파트에 대해서만 서명을 엄격히 검증합니다. 텍스트 턴에서 서명이 누락되어도 400 오류가 발생하지는 않지만, 서명을 유지하면 추론 연속성에 도움이 되므로 전체 응답을 그대로 반환하십시오.관련 문서
Gemini Function Calling 가이드
서명 반환 방법을 포함한 전체 2턴 예제
Gemini 4 Argon 텍스트 생성
다중 턴 도구 호출 주의사항 및 클라이언트 설정
Claude의 Invalid Thinking Signature 오류는 어떻게 해결하나요?
Claude 측에서 발생하는 동일한 유형의 문제
다중 턴 대화 가이드
각 제공업체가 요구하는 대화 기록 반환 방식