Skip to content

Adopt upstream's subagent attribution once pingdotgg#5219 lands #20

Description

@Dillpickleschmidt

Part of #1

Question

Add the subagent attribution edge to T3's model, so subagent work is distinguishable from main-agent work in the event store.

Decided in Close the agent-lenses data gap — see that ticket for the full reasoning. This ticket executes it (the map's Notes carry execution).

Resized by measurement

Measure the fidelity of forwarded subagent tool payloads proved subagent content arrives only as complete assistant/user messages — 0 of 32 stream_event messages carried a parent_tool_use_id. T3 emits tool items only from the stream_event path, and handleAssistantMessage drops every tool_use block but ExitPlanMode (ClaudeAdapter.ts:2522).

So this is not "stop discarding a field." T3 must start emitting tool items for subagent blocks, from the complete-message path, attributed. Payload fidelity is confirmed full (paths, commands, multi-KB results), so the data is all there.

The change:

  • Add optional top-level parentToolCallId?: string to ItemLifecyclePayload (packages/contracts/src/providerRuntime.ts:404) — the id of the launching tool call, never a thread id, never a T3-invented agent id.
  • Emit tool lifecycle items for subagent tool_use / tool_result blocks in handleAssistantMessage, populating parentToolCallId from the message's parent_tool_use_id. These blocks are on the wire today and dropped.
  • Do not double-emit for the main agent. Main-agent tool blocks appear on both paths; T3 takes them from stream_event and ignores the complete message. Only blocks with a non-null parent_tool_use_id may be emitted from the complete-message path.
  • Subagent messages carry no streaming deltas, so these items are emitted complete rather than started-then-updated. Confirm that suits the item lifecycle.
  • Leave forwardSubagentText off. Mindwalk's Event is 100% tool-derived; no scene renders subagent prose.
  • Verify it survives projectActivityPayload — it should, untouched, since the projection spreads ...payload and rewrites only data (ActivityPayloadProjection.ts:195-201). No widening of the six-key whitelist.

Scope boundary — server-side only, and no suppression. Subagent items are allowed to appear in chat. They are ordinary tool-lifecycle items, so they join the per-turn work log group that already collapses by default (expandedWorkGroupIds, MessagesTimeline.tsx:224; auto-expanded only for the latest turn, line 1289), with run-length collapsing in session-logic.ts. The assistant message body is untouched, so nothing bloats. No ChatView or mobile change is needed — this ticket is entirely server-side.

Accepted consequence: a Task's interior appears as a flat run of entries inside the turn's work log, in arrival order, rather than nested under its launch row. Nesting it properly is a product feature and stays fog.

No backfill. Threads already in the event store keep their flattened, unattributed subagent calls. The id was never written down.

Out of scope here: the other four providers. Codex and OpenCode attribution is unmeasured, Cursor/Grok emit no collab_agent_tool_call at all. When a provider does gain an edge, its adapter resolves whatever it has (e.g. a Codex parent thread id) to the launching call id itself.

Activity

  1. Dillpickleschmidt commented on Aug 2, 2026

    @Dillpickleschmidt
    OwnerAuthor

    Parked: superseded by upstream PR pingdotgg#5219 — adopt, don't invent

    The dev flagged that upstream has native subagent support incoming, and it checks out: pingdotgg/t3code#5219 ("native subagent & workflow observability", t3dotgg, WIP, extensively live-tested, active as of 2026-08-02), designed to be field-compatible with the orchestration-v2 series (pingdotgg#4779 et al.).

    It contains this ticket's entire deliverable, done upstream: additive tool attribution (agentId / parentToolUseId) on task and tool payloads, ClaudeAdapter resolving parent_tool_use_id on tool events, zero migrations, riding the same event-sourced activity path our trace projection reads. It also covers Codex (live-probed collab fleets), which this ticket scoped out, and ports its own Agents right-panel — upstream's answer to the mindwalk AgentsPanel we skipped.

    Building this now would have collided twice:

    1. Our parentToolCallId beside their parentToolUseId in the same contracts — a guaranteed merge conflict in exactly the files this fork swears to barely touch.
    2. This ticket's "no suppression — subagent items appear in the work log" is the opposite of feat: native subagent & workflow observability pingdotgg/t3code#5219's quiet timeline, which re-homes agent-attributed rows to the panel and folds lifecycle rows into a spawn CTA. Upstream's merge would have reversed our visible behaviour.

    What this ticket becomes when pingdotgg#5219 merges into the fork: a mapping pass, not an ingest change. TraceProjection.ts's lens gate already reads an optional parentToolCallId off the payload and treats absence as "main" (includedByLens); it points at upstream's field name instead. #21's graph derivation likewise reads upstream's linkage. No fork-owned ingest, no contract edits.

    Blocked on: pingdotgg#5219 merging upstream, then an upstream merge into this fork.

  2. changed the title [-]Persist the subagent attribution edge[/-] [+]Adopt upstream's subagent attribution once pingdotgg#5219 lands[/+] on Aug 2, 2026
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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions