Firme di pensiero

Le firme del pensiero sono rappresentazioni criptate del processo di pensiero interno del modello e vengono utilizzate per preservare il contesto del ragionamento nelle interazioni multi-turno. Quando utilizzi modelli di pensiero (come le serie Gemini 3 e 2.5), l'API potrebbe restituire un campo thoughtSignature all'interno delle parti di contenuti della risposta (ad es. text o functionCall).

Come regola generale, se ricevi una firma del pensiero nella risposta di un modello, devi restituirla esattamente come l'hai ricevuta quando invii la cronologia della conversazione nel turno successivo. Quando utilizzi Gemini 3 Pro, devi restituire le firme del pensiero durante la chiamata di funzione, altrimenti riceverai un errore di convalida (codice di stato 4xx).

Come funziona

L'immagine seguente mostra il significato di "turno" e "passaggio" in relazione alla chiamata di funzione nell'API Gemini. Un "turno" è un singolo scambio completo in una conversazione tra un utente e un modello. Un "passo" è un'azione o un'operazione più granulare eseguita dal modello, spesso nell'ambito di un processo più ampio per completare un turno.

Diagramma dei turni e dei passaggi della chiamata di funzione

Questo documento si concentra sulla gestione della chiamata di funzione per Gemini 3 Pro. Consulta la sezione Comportamento del modello per le discrepanze con la versione 2.5.

Gemini 3 Pro restituisce le firme del pensiero per tutte le risposte del modello (risposte dell'API) con una chiamata di funzione. Le firme dei pensieri vengono visualizzate nei seguenti casi:

  • Quando ci sono chiamate di funzioni parallele, la prima parte della chiamata di funzione restituita dalla risposta del modello avrà una firma di pensiero.
  • Quando ci sono chiamate di funzioni sequenziali (multistep), ogni chiamata di funzione avrà una firma e devi restituire tutte le firme.
  • Le risposte del modello senza una chiamata di funzione restituiranno una firma di pensiero all'interno dell'ultima parte restituita dal modello.

La seguente tabella fornisce una visualizzazione delle chiamate di funzioni in più passaggi, combinando le definizioni di turni e passaggi con il concetto di firme introdotto sopra:

Svolta

Step

Richiesta utente

Risposta del modello

FunctionResponse

1

1

request1 = user_prompt FC1 + signature FR1

1

2

request2 = request1 + (FC1 + signature) + FR1 FC2 + signature FR2

1

3

request3 = request2 + (FC2 + signature) + FR2 text_output

(no FCs)

Nessuno

Firme nelle parti di chiamata di funzione

Quando Gemini genera un functionCall, si basa sul thought_signature per elaborare correttamente l'output dello strumento nel turno successivo.

  • Comportamento:
    • Chiamata di funzione singola: la parte functionCall conterrà un thought_signature.
    • Chiamate di funzione parallele: se il modello genera chiamate di funzione parallele in una risposta, il thought_signature viene allegato solo alla prima parte functionCall. Le parti functionCall successive nella stessa risposta non contengono una firma.
  • Requisito: devi restituire questa firma esattamente nella parte in cui è stata ricevuta quando invii di nuovo la cronologia della conversazione.
  • Convalida: viene applicata una convalida rigorosa a tutte le chiamate di funzione all'interno del turno corrente . (È richiesto solo il turno attuale; non eseguiamo la convalida dei turni precedenti)
    • L'API esamina la cronologia (dal più recente al meno recente) per trovare il messaggio Utente più recente che contenga contenuti standard (ad es. text) ( che sarebbe l'inizio del turno corrente). Questa operazione be sarà un functionResponse.
    • Tutti i turni del modello functionCall che si verificano dopo questo messaggio di utilizzo specifico sono considerati parte del turno.
    • La prima parte functionCall di ogni passaggio del turno corrente deve includere il relativo thought_signature.
    • Se ometti un thought_signature per la prima parte functionCall in qualsiasi passaggio del turno corrente, la richiesta non andrà a buon fine e verrà visualizzato un errore 400.
  • Se non vengono restituite firme corrette, ecco come si verifica l'errore
    • gemini-3-pro-preview: Se non includi le firme, verrà visualizzato un errore 400. Il testo sarà del tipo:
      • Nella chiamata alla funzione <Function Call> nel blocco di contenuti <index of contents array> manca un thought_signature. Ad esempio, la chiamata alla funzione FC1 nel blocco di contenuti 1. non include thought_signature.

Esempio di chiamata di funzione sequenziale

Questa sezione mostra un esempio di più chiamate di funzioni in cui l'utente pone una domanda complessa che richiede più attività.

Vediamo un esempio di chiamata di funzione a più turni in cui l'utente pone una domanda complessa che richiede più attività: "Check flight status for AA100 and book a taxi if delayed".

Svolta

Step

Richiesta utente

Risposta del modello

FunctionResponse

1

1

request1="Check flight status for AA100 and book a taxi 2 hours before if delayed." FC1 ("check_flight") + signature FR1

1

2

request2 = request1 + FC1 ("check_flight") + signature + FR1 FC2("book_taxi") + signature FR2

1

3

request3 = request2 + FC2 ("book_taxi") + signature + FR2 text_output

(no FCs)

None

Il seguente codice illustra la sequenza nella tabella precedente.

Turno 1, passaggio 1 (richiesta dell'utente)

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
        }
      ]
    }
  ],
  "tools": [
    {
      "functionDeclarations": [
        {
          "name": "check_flight",
          "description": "Gets the current status of a flight",
          "parameters": {
            "type": "object",
            "properties": {
              "flight": {
                "type": "string",
                "description": "The flight number to check"
              }
            },
            "required": [
              "flight"
            ]
          }
        },
        {
          "name": "book_taxi",
          "description": "Book a taxi",
          "parameters": {
            "type": "object",
            "properties": {
              "time": {
                "type": "string",
                "description": "time to book the taxi"
              }
            },
            "required": [
              "time"
            ]
          }
        }
      ]
    }
  ]
}

Turno 1, passaggio 1 (risposta del modello)

{
"content": {
        "role": "model",
        "parts": [
          {
            "functionCall": {
              "name": "check_flight",
              "args": {
                "flight": "AA100"
              }
            },
            "thoughtSignature": "<Signature A>"
          }
        ]
  }
}

Turno 1, passaggio 2 (risposta dell'utente - invio degli output dello strumento) Poiché questo turno dell'utente contiene solo un functionResponse (nessun testo nuovo), siamo ancora al Turno 1. Dobbiamo preservare <Signature_A>.

{
      "role": "user",
      "parts": [
        {
          "text": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
        }
      ]
    },
    {
        "role": "model",
        "parts": [
          {
            "functionCall": {
              "name": "check_flight",
              "args": {
                "flight": "AA100"
              }
            },
            "thoughtSignature": "<Signature A>" //Required and Validated
          }
        ]
      },
      {
        "role": "user",
        "parts": [
          {
            "functionResponse": {
              "name": "check_flight",
              "response": {
                "status": "delayed",
                "departure_time": "12 PM"
                }
              }
            }
        ]
}

Turno 1, passaggio 2 (modello) Il modello ora decide di prenotare un taxi in base all'output dello strumento precedente.

{
      "content": {
        "role": "model",
        "parts": [
          {
            "functionCall": {
              "name": "book_taxi",
              "args": {
                "time": "10 AM"
              }
            },
            "thoughtSignature": "<Signature B>"
          }
        ]
      }
}

Turno 1, passaggio 3 (utente - output dello strumento di invio) Per inviare la conferma della prenotazione del taxi, dobbiamo includere le firme per TUTTE le chiamate di funzione in questo ciclo (<Signature A> + <Signature B>).

{
      "role": "user",
      "parts": [
        {
          "text": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
        }
      ]
    },
    {
        "role": "model",
        "parts": [
          {
            "functionCall": {
              "name": "check_flight",
              "args": {
                "flight": "AA100"
              }
            },
            "thoughtSignature": "<Signature A>" //Required and Validated
          }
        ]
      },
      {
        "role": "user",
        "parts": [
          {
            "functionResponse": {
              "name": "check_flight",
              "response": {
                "status": "delayed",
                "departure_time": "12 PM"
              }
              }
            }
        ]
      },
      {
        "role": "model",
        "parts": [
          {
            "functionCall": {
              "name": "book_taxi",
              "args": {
                "time": "10 AM"
              }
            },
            "thoughtSignature": "<Signature B>" //Required and Validated
          }
        ]
      },
      {
        "role": "user",
        "parts": [
          {
            "functionResponse": {
              "name": "book_taxi",
              "response": {
                "booking_status": "success"
              }
              }
            }
        ]
    }
}

Esempio di chiamata di funzione parallela

Vediamo un esempio di chiamata di funzione parallela in cui l'utente chiede "Check weather in Paris and London" per vedere dove il modello esegue la convalida.

Svolta

Step

Richiesta utente

Risposta del modello

FunctionResponse

1

1

request1="Controlla il meteo a Parigi e Londra"

FC1 ("Parigi") + firma

FC2 ("Londra")

FR1

1

2

richiesta 2 = richiesta 1 + FC1 ("Parigi") + firma + FC2 ("Londra")

text_output

(nessuna FC)

Nessuno

Il seguente codice illustra la sequenza nella tabella precedente.

Turno 1, passaggio 1 (richiesta dell'utente)

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "Check the weather in Paris and London."
        }
      ]
    }
  ],
  "tools": [
    {
      "functionDeclarations": [
        {
          "name": "get_current_temperature",
          "description": "Gets the current temperature for a given location.",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city name, e.g. San Francisco"
              }
            },
            "required": [
              "location"
            ]
          }
        }
      ]
    }
  ]
}

Turno 1, passaggio 1 (risposta del modello)

{
  "content": {
    "parts": [
      {
        "functionCall": {
          "name": "get_current_temperature",
          "args": {
            "location": "Paris"
          }
        },
        "thoughtSignature": "<Signature_A>"// INCLUDED on First FC
      },
      {
        "functionCall": {
          "name": "get_current_temperature",
          "args": {
            "location": "London"
          }// NO signature on subsequent parallel FCs
        }
      }
    ]
  }
}

Turno 1, passaggio 2 (risposta dell'utente - invio degli output dello strumento) Dobbiamo conservare <Signature_A> nella prima parte esattamente come ricevuto.

[
  {
    "role": "user",
    "parts": [
      {
        "text": "Check the weather in Paris and London."
      }
    ]
  },
  {
    "role": "model",
    "parts": [
      {
        "functionCall": {
          "name": "get_current_temperature",
          "args": {
            "city": "Paris"
          }
        },
        "thought_signature": "<Signature_A>" // MUST BE INCLUDED
      },
      {
        "functionCall": {
          "name": "get_current_temperature",
          "args": {
            "city": "London"
          }
        }
      } // NO SIGNATURE FIELD
    ]
  },
  {
    "role": "user",
    "parts": [
      {
        "functionResponse": {
          "name": "get_current_temperature",
          "response": {
            "temp": "15C"
          }
        }
      },
      {
        "functionResponse": {
          "name": "get_current_temperature",
          "response": {
            "temp": "12C"
          }
        }
      }
    ]
  }
]

Firme in parti non functionCall

Gemini potrebbe anche restituire thought_signatures nella parte finale della risposta nelle parti non di chiamata di funzione.

  • Comportamento: la parte finale dei contenuti (text, inlineData…) restituita dal modello può contenere un thought_signature.
  • Consiglio: la restituzione di queste firme è consigliata per garantire che il modello mantenga un ragionamento di alta qualità, soprattutto per istruzioni complesse o workflow con agente simulato.
  • Convalida: l'API non applica rigorosamente la convalida. Se li ometti, non riceverai un errore di blocco, anche se il rendimento potrebbe peggiorare.

Testo/Ragionamento nel contesto (nessuna convalida)

Turno 1, passaggio 1 (risposta del modello)

{
  "role": "model",
  "parts": [
    {
      "text": "I need to calculate the risk. Let me think step-by-step...",
      "thought_signature": "<Signature_C>" // OPTIONAL (Recommended)
    }
  ]
}

Turno 2, passaggio 1 (utente)

[
  { "role": "user", "parts": [{ "text": "What is the risk?" }] },
  {
    "role": "model", 
    "parts": [
      {
        "text": "I need to calculate the risk. Let me think step-by-step...",
        // If you omit <Signature_C> here, no error will occur.
      }
    ]
  },
  { "role": "user", "parts": [{ "text": "Summarize it." }] }
]

Firme per la compatibilità con OpenAI

I seguenti esempi mostrano come gestire le firme di pensiero per un'API di completamento della chat utilizzando la compatibilità con OpenAI.

Esempio di chiamata di funzione sequenziale

Questo è un esempio di chiamata di più funzioni in cui l'utente pone una domanda complessa che richiede più attività.

Vediamo un esempio di chiamata di funzione a più turni in cui l'utente chiede Check flight status for AA100 and book a taxi if delayed e puoi vedere cosa succede quando l'utente pone una domanda complessa che richiede più attività.

Svolta

Step

Richiesta utente

Risposta del modello

FunctionResponse

1

1

request1="Check the weather in Paris and London" FC1 ("Paris") + signature

FC2 ("London")

FR1

1

2

request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") text_output

(no FCs)

None

Il seguente codice esamina la sequenza specificata.

Turno 1, passaggio 1 (richiesta dell'utente)

{
  "model": "google/gemini-3-pro-preview",
  "messages": [
    {
      "role": "user",
      "content": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "check_flight",
        "description": "Gets the current status of a flight",
        "parameters": {
          "type": "object",
          "properties": {
            "flight": {
              "type": "string",
              "description": "The flight number to check."
            }
          },
          "required": [
            "flight"
          ]
        }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "book_taxi",
        "description": "Book a taxi",
        "parameters": {
          "type": "object",
          "properties": {
            "time": {
              "type": "string",
              "description": "time to book the taxi"
            }
          },
          "required": [
            "time"
          ]
        }
      }
    }
  ]
}

Turno 1, passaggio 1 (risposta modello)

{
      "role": "model",
        "tool_calls": [
          {
            "extra_content": {
              "google": {
                "thought_signature": "<Signature A>"
              }
            },
            "function": {
              "arguments": "{\"flight\":\"AA100\"}",
              "name": "check_flight"
            },
            "id": "function-call-1",
            "type": "function"
          }
        ]
    }

Turno 1, passaggio 2 (risposta dell'utente - invio degli output dello strumento)

Poiché questo turno dell'utente contiene solo un functionResponse (nessun testo nuovo), siamo ancora al Turno 1 e dobbiamo conservare <Signature_A>.

"messages": [
    {
      "role": "user",
      "content": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
    },
    {
      "role": "model",
        "tool_calls": [
          {
            "extra_content": {
              "google": {
                "thought_signature": "<Signature A>" //Required and Validated
              }
            },
            "function": {
              "arguments": "{\"flight\":\"AA100\"}",
              "name": "check_flight"
            },
            "id": "function-call-1",
            "type": "function"
          }
        ]
    },
    {
      "role": "tool",
      "name": "check_flight",
      "tool_call_id": "function-call-1",
      "content": "{\"status\":\"delayed\",\"departure_time\":\"12 PM\"}"                 
    }
  ]

Turno 1, passaggio 2 (modello)

Il modello ora decide di prenotare un taxi in base all'output precedente dello strumento.

{
"role": "model",
"tool_calls": [
{
"extra_content": {
"google": {
"thought_signature": "<Signature B>"
}
            },
            "function": {
              "arguments": "{\"time\":\"10 AM\"}",
              "name": "book_taxi"
            },
            "id": "function-call-2",
            "type": "function"
          }
       ]
}

Turno 1, passaggio 3 (utente - invio dell'output dello strumento)

Per inviare la conferma della prenotazione del taxi, dobbiamo includere le firme per TUTTE le chiamate di funzione in questo ciclo (<Signature A> + <Signature B>).

"messages": [
    {
      "role": "user",
      "content": "Check flight status for AA100 and book a taxi 2 hours before if delayed."
    },
    {
      "role": "model",
        "tool_calls": [
          {
            "extra_content": {
              "google": {
                "thought_signature": "<Signature A>" //Required and Validated
              }
            },
            "function": {
              "arguments": "{\"flight\":\"AA100\"}",
              "name": "check_flight"
            },
            "id": "function-call-1d6a1a61-6f4f-4029-80ce-61586bd86da5",
            "type": "function"
          }
        ]
    },
    {
      "role": "tool",
      "name": "check_flight",
      "tool_call_id": "function-call-1d6a1a61-6f4f-4029-80ce-61586bd86da5",
      "content": "{\"status\":\"delayed\",\"departure_time\":\"12 PM\"}"                 
    },
    {
      "role": "model",
        "tool_calls": [
          {
            "extra_content": {
              "google": {
                "thought_signature": "<Signature B>" //Required and Validated
              }
            },
            "function": {
              "arguments": "{\"time\":\"10 AM\"}",
              "name": "book_taxi"
            },
            "id": "function-call-65b325ba-9b40-4003-9535-8c7137b35634",
            "type": "function"
          }
        ]
    },
    {
      "role": "tool",
      "name": "book_taxi",
      "tool_call_id": "function-call-65b325ba-9b40-4003-9535-8c7137b35634",
      "content": "{\"booking_status\":\"success\"}"
    }
  ]

Esempio di chiamata di funzione parallela

Vediamo un esempio di chiamata di funzione parallela in cui l'utente chiede "Check weather in Paris and London" e puoi vedere dove il modello esegue la convalida.

Svolta

Step

Richiesta utente

Risposta del modello

FunctionResponse

1

1

request1="Check the weather in Paris and London" FC1 ("Paris") + signature

FC2 ("London")

FR1

1

2

request 2 = request1 + FC1 ("Paris") + signature + FC2 ("London") text_output

(no FCs)

None

Ecco il codice per scorrere la sequenza specificata.

Turno 1, passaggio 1 (richiesta dell'utente)

{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "Check the weather in Paris and London."
        }
      ]
    }
  ],
  "tools": [
    {
      "functionDeclarations": [
        {
          "name": "get_current_temperature",
          "description": "Gets the current temperature for a given location.",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {
                "type": "string",
                "description": "The city name, e.g. San Francisco"
              }
            },
            "required": [
              "location"
            ]
          }
        }
      ]
    }
  ]
}

Turno 1, passaggio 1 (risposta modello)

{
"role": "assistant",
        "tool_calls": [
          {
            "extra_content": {
              "google": {
                "thought_signature": "<Signature A>" //Signature returned
              }
            },
            "function": {
              "arguments": "{\"location\":\"Paris\"}",
              "name": "get_current_temperature"
            },
            "id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01",
            "type": "function"
          },
          {
            "function": {
              "arguments": "{\"location\":\"London\"}",
              "name": "get_current_temperature"
            },
            "id": "function-call-335673ad-913e-42d1-bbf5-387c8ab80f44",
            "type": "function" // No signature on Parallel FC
          }
        ]
}

Turno 1, passaggio 2 (risposta dell'utente - invio degli output dello strumento)

Devi conservare <Signature_A> nella prima parte esattamente come l'hai ricevuto.

"messages": [
    {
      "role": "user",
      "content": "Check the weather in Paris and London."
    },
    {
      "role": "assistant",
        "tool_calls": [
          {
            "extra_content": {
              "google": {
                "thought_signature": "<Signature A>" //Required
              }
            },
            "function": {
              "arguments": "{\"location\":\"Paris\"}",
              "name": "get_current_temperature"
            },
            "id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01",
            "type": "function"
          },
          {
            "function": { //No Signature
              "arguments": "{\"location\":\"London\"}",
              "name": "get_current_temperature"
            },
            "id": "function-call-335673ad-913e-42d1-bbf5-387c8ab80f44",
            "type": "function"
          }
        ]
    },
    {
      "role":"tool",
      "name": "get_current_temperature",
      "tool_call_id": "function-call-f3b9ecb3-d55f-4076-98c8-b13e9d1c0e01",
      "content": "{\"temp\":\"15C\"}"
    },    
    {
      "role":"tool",
      "name": "get_current_temperature",
      "tool_call_id": "function-call-335673ad-913e-42d1-bbf5-387c8ab80f44",
      "content": "{\"temp\":\"12C\"}"
    }
  ]

Domande frequenti

  1. Come faccio a trasferire la cronologia da un modello diverso a Gemini 3 Pro con una parte di chiamata di funzione nel turno e nel passaggio attuali? Devo fornire parti di chiamate di funzione che non sono state generate dall'API e quindi non hanno una firma di pensiero associata?

    Sebbene l'inserimento di blocchi di chiamate di funzioni personalizzate nella richiesta sia fortemente sconsigliato, nei casi in cui non è possibile evitarlo, ad esempio fornire informazioni al modello su chiamate di funzioni e risposte eseguite in modo deterministico dal client o trasferire una traccia da un modello diverso che non include firme di pensiero, puoi impostare le seguenti firme fittizie di "context_engineering_is_the_way_to_go" o "skip_thought_signature_validator" nel campo della firma di pensiero per saltare la convalida.

  2. Invio chiamate di funzioni parallele e risposte interleaved e l'API restituisce un errore 400. Perché?

    Quando l'API restituisce chiamate di funzioni parallele "FC1 + firma, FC2", la risposta dell'utente prevista è "FC1 + firma, FC2, FR1, FR2". Se sono interlacciati come "FC1 + firma, FR1, FC2, FR2", l'API restituirà un errore 400.

  3. Durante lo streaming e quando il modello non restituisce una chiamata di funzione, non riesco a trovare la firma del pensiero

    Durante una risposta del modello che non contiene un FC con una richiesta di streaming, il modello può restituire la firma del pensiero in una parte con un contenuto di testo vuoto. È consigliabile analizzare l'intera richiesta finché il modello non restituisce finish_reason.

Comportamento della firma del pensiero per serie di modelli

I modelli Gemini 3 Pro e Gemini 2.5 si comportano in modo diverso con le firme del pensiero nelle chiamate di funzione:

  • Se in una risposta sono presenti chiamate di funzioni,
    • Gemini 3 Pro avrà sempre la firma nella prima parte della chiamata di funzione. La restituzione di questa parte è obbligatoria.
    • Gemini 2.5 avrà la firma nella prima parte (indipendentemente dal tipo). La restituzione di questa parte è facoltativa.
  • Se in una risposta non sono presenti chiamate di funzioni,
    • Gemini 3 Pro avrà la firma nell'ultima parte se il modello genera un pensiero.
    • Gemini 2.5 non avrà una firma in nessuna parte.

Per il comportamento della firma del pensiero dei modelli Gemini 2.5, consulta la pagina Pensiero.