Repository navigation
Description
Summary
Severity: High/Medium
Area: Gemini adapter
Affected files: agentkit/llm/gemini.py:159-169
Suggested branch: fix/gemini-thought-part-leak
Suggested PR title: fix(gemini): exclude thought parts from the model answer
This is finding AUDIT-06 of 18 from a consolidated audit of agentkit/. It is deliberately self-contained so it can be fixed on its own branch with its own PR.
Related findings: Related: AUDIT-05.
AUDIT-06 — High/Medium — Gemini thought parts are appended to the answer
File — agentkit/llm/gemini.py:159-169
candidates = getattr(raw_response, "candidates", None)
if candidates:
candidate = candidates[0]
if candidate.content and candidate.content.parts:
for part in candidate.content.parts:
if getattr(part, "text", None):
text_parts.append(part.text)
if getattr(part, "function_call", None):Why this is a bug
types.Part has a thought flag (google-genai 2.25 Part.thought). The loop never checks it, so internal reasoning text is concatenated into LLMResponse.text, which becomes the assistant turn content (agent.py:210-215), the persisted history, and the final_answer returned to the API client.
Reproduced
part = Part(text="SECRET CHAIN OF THOUGHT", thought=True)
adapter LLMResponse.text == "SECRET CHAIN OF THOUGHT"
Pass cases
- A part with
thought=Trueis never included inLLMResponse.text/final_answer/ persisted assistant content. - A part with
thought=Falseand text is still returned normally (no regression). - A part carrying both
thought=Trueand afunction_callstill yields the tool call (and itsthought_signature) — the call is not lost. - A regression test asserts the API's
answerfield contains no thought text for a Gemini response containing a thought part.
Definition of done (per AGENTS.md)
- New/updated unit and integration tests covering the pass cases above, all passing (
pytest). -
ruff check .,ruff format --check .andmypy agentkitclean. - Docstrings updated where behaviour changed;
docs/PROGRESS.mdupdated (status, PR link, commit count, notes). - A new ADR in
docs/DECISIONS.mdif an architectural decision was made. - Branch pushed and PR opened (never commit directly to
main).
Baseline at the time of writing: pytest is green on main (all tests pass; tests/real/* skipped unless AGENTKIT_REAL_INFRA=1).
Activity
getdownandcode commentedon Oct 20, 2026
Audit index (18 separate issues, fix one by one)
Each issue is self-contained: current code, reproduction, pass cases, suggested branch and PR title. Reference the relevant one with
Fixes #NNin your PR.HamzaKhanBUIC commentedon Oct 20, 2026
Opened PR with fix and regression tests: #78
Summary of Resolution
uff\ check & format clean, \mypy\ clean.