Skip to content

Investigation trace: reasoning can store host output unbounded #50

Closed

Description

@shipmill-romamo

Found while reviewing #45 (merged as c2dda49). Neither blocked the merge.

  1. The trace's reasoning can store host output, with no size limit. Before Keep each model turn's raw trace in the stream and the record #45 the investigation record kept the agent's steps but never tool results. spec.trace[].reasoning now keeps the model's reasoning_content verbatim, and a model's reasoning often quotes the host output it just read (log lines, df output, config fragments). So host output reaches the record indirectly, and nothing bounds its length (tool text to the model is capped at TOOL_TEXT_LIMIT, tool names at TOOL_NAME_LIMIT, the ids now at REPLY_ID_LIMIT). Decide whether the record caps reasoning (and the turn text) at a limit like the others, and whether the "names and hashes only" rule from the secrets guide should apply to it
  2. An invalid tool-call argument string is kept raw in the trace while the step stores {}. When the model writes arguments that aren't valid JSON, the step records {} but trace.toolCalls[].arguments keeps the raw string. That is arguably the point of a raw trace, but the two parts of one record then disagree; worth one line in the schema description saying which is authoritative

Code: sdk/src/cloudfall/investigation.py (_turn, _call_text), config/schemas/v1/agent-investigation.schema.json.

Activity

  1. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    Triage: waits on your decision below. Filed from the review of #45; both points are real on main (c2dda49), and the first one changes what the investigation record stores (config/schemas/v1/agent-investigation.schema.json), so it goes through the design gate before anyone builds it.

    Plan once decided: cap trace[].reasoning and the turn text in _turn like the other limits, with maxLength in the schema so a longer value is refused rather than stored; add one line to the toolCalls[].arguments schema description saying the step's parsed {} is what ran and the raw string is only the model's text.

  2. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    @romamo Decision needed: should the investigation record cap the model's reasoning it keeps in spec.trace, now that the reasoning can quote host output?

    1. Cap it at 8000 characters per turn, like TOOL_TEXT_LIMIT (recommended): the record stays bounded and keeps the part of the reasoning the hosted demo shows; a very long reasoning is cut, with the cut marked
    2. Keep it whole: the record shows exactly what the model thought, at the cost of unbounded record size and host output (log lines, config fragments) stored in the record
    3. Drop reasoning from the record and keep it only in the stream: the record stays at "what the agent did", and the "what it thought" answer from Keep each model turn's raw trace in the stream and the record #45 is lost

    Reply here with a number or your own answer; shipmill takes this up on the tick after your reply.

  3. romamo commented on Oct 9, 2026

    @romamo
    Collaborator

    1 — cap the reasoning kept in spec.trace at 8000 characters per turn, like TOOL_TEXT_LIMIT, with the cut marked

    (decision by @romamo, given in chat; posted by Claude on his behalf)

  4. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    Triage: implement, taking up the answer above (option 1), recorded as D-4 in #51.

    Plan: _turn caps each turn's reasoning kept in spec.trace at 8000 characters (the TOOL_TEXT_LIMIT value), with the cut marked, and the schema gets a matching maxLength so a longer value is refused rather than stored. The turn text gets the same cap. Point 2: one line in the toolCalls[].arguments schema description saying the step's parsed arguments are what ran and the raw string is only the model's text.

    #44 also changes investigation.py and the same schema; the same implementer builds both on separate branches.

  5. removed
    needs-decisionA shipmill session asked a question here; waits for a reply
    on Oct 9, 2026
  6. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    PR: #52. Each turn's reasoning and text in the trace keep at most 8000 characters (TRACE_TEXT_LIMIT), cut from the front with the same [first N characters cut] mark as the tool-output cap, so the model's conclusion stays; the schema has maxLength: 8000 on both. The stream's turn event is capped the same way, so stream and record agree. The toolCalls[].arguments description now says the parsed arguments are what ran. Older records still load: nothing re-validates stored investigation records.

  7. romamo commented on Oct 9, 2026

    @romamo
    Collaborator

    Decision by @romamo, given in chat; posted by Claude on his behalf.

    1. Cap the reasoning kept in spec.trace at 8000 characters per turn, like TOOL_TEXT_LIMIT, with the cut marked.

  8. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    Released in v0.6.0rc9.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions