Skip to content

Sub-agent child tool-call arguments are not persisted in turn-state snapshots, so reloaded child tool cards lose their input #5987

Description

@YellowSnnowmann

Summary

After a reload, a sub-agent's child tool-call cards render without their input: the turn-state snapshot never persists the child call's arguments, so the frontend mapper has nothing to restore.

Problem

Live, subagent_tool_call carries args and the row shows the tool input (and a degraded generic tool name can be given a search label from query). After a thread reload the same cards come back from the persisted snapshot with no input at all.

Neither persisted shape carries the payload (app/src/types/turnState.ts):

export interface PersistedSubagentToolCall {
  callId; toolName; status; iteration?; elapsedMs?; outputChars?;
  displayName?; detail?; failure?; output?;      // no args / input
}
// PersistedSubagentTranscriptItem, kind: 'tool'
{ iteration?; callId; toolName; status; elapsedMs?; outputChars?; displayName?; detail?; failure? }

The only args field in that file is PersistedToolTimelineEntry.argsBuffer, which belongs to the parent timeline. So subagentToolCallFromPersisted assigning no args (app/src/store/chatRuntimeSlice.ts, subagentActivityFromPersisted) is not a mapper bug — the data never leaves the core.

Repro: delegate to a sub-agent that calls a tool with visible arguments → let it finish → reload the thread → expand the sub-agent card → the child tool row has no input.

Solution

Rust: persist the child call's arguments in the turn-state mirror (src/openhuman/threads/turn_state/ — where subagent_tool_call events are written into the snapshot's subagent.toolCalls), as an optional field mirroring the parent's argsBuffer semantics (bounded size). Frontend: add the optional field to PersistedSubagentToolCall / the transcript tool item and copy it through in subagentToolCallFromPersisted — a one-line change once the field exists.

Acceptance criteria

  • Repro gone — child tool rows keep their input across a reload; a degraded tool name still derives its search label from the restored query.
  • Regression safety — Rust snapshot round-trip test covers the new field; Vitest covers subagentActivityFromPersisted restoring args.
  • Diff coverage ≥ 80% — the fix PR meets the changed-lines coverage gate (Vitest + cargo-llvm-cov, enforced by .github/workflows/ci-lite.yml).
  • Older snapshots without the field still load (additive, optional).

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugreact-uiReact app work in app/src: pages, components, providers, store, and UX.rust-coreCore Rust runtime in src/: CLI, core_server, shared infrastructure.

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions