Skip to content

AUDIT-06 — High/Medium — Gemini thought parts are appended to the answer #63

Closed

Description

@getdownandcode

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=True is never included in LLMResponse.text / final_answer / persisted assistant content.
  • A part with thought=False and text is still returned normally (no regression).
  • A part carrying both thought=True and a function_call still yields the tool call (and its thought_signature) — the call is not lost.
  • A regression test asserts the API's answer field 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 . and mypy agentkit clean.
  • Docstrings updated where behaviour changed; docs/PROGRESS.md updated (status, PR link, commit count, notes).
  • A new ADR in docs/DECISIONS.md if 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

  1. getdownandcode commented on Oct 20, 2026

    @getdownandcode
    OwnerAuthor

    Audit index (18 separate issues, fix one by one)

    ID Issue Severity
    AUDIT-01 #58 Critical
    AUDIT-02 #59 Critical
    AUDIT-03 #60 High
    AUDIT-04 #61 High
    AUDIT-05 #62 High
    AUDIT-06 #63 High/Medium
    AUDIT-07 #64 Medium-High
    AUDIT-08 #65 Medium-High
    AUDIT-09 #66 Medium-High
    AUDIT-10 #67 Medium-High
    AUDIT-11 #68 Medium
    AUDIT-12 #69 Medium
    AUDIT-13 #70 Medium
    AUDIT-14 #71 Medium
    AUDIT-15 #72 Medium
    AUDIT-16 #73 Medium
    AUDIT-17 #74 Low
    AUDIT-18 #75 Low/Deployment

    Each issue is self-contained: current code, reproduction, pass cases, suggested branch and PR title. Reference the relevant one with Fixes #NN in your PR.

  2. HamzaKhanBUIC commented on Oct 20, 2026

    @HamzaKhanBUIC

    Opened PR with fix and regression tests: #78

    Summary of Resolution

    • In \�gentkit/llm/gemini.py, updated candidate content parsing to check \if getattr(part, 'text', None) and not getattr(part, 'thought', False): text_parts.append(part.text).
    • Preserved tool calls and \ hought_signature\ extraction on parts with both \ hought=True\ and a \ unction_call.
    • Added unit and API endpoint regression tests in \ ests/unit/test_audit_regressions.py\ and \ ests/unit/test_gemini_adapter.py.
    • All tests passing,
      uff\ check & format clean, \mypy\ clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions