Skip to content

fix: do not hold an AIR load replay until the CLI starts - #1433

Merged
nikita-ashihmin merged 1 commit into
agentclientprotocol:mainfrom
nikita-ashihmin:nikita.ashikhmin/subagent-model-load-latency
Oct 26, 2026
Merged

nikita-ashihmin merged 1 commit into
agentclientprotocol:mainfrom
nikita-ashihmin:nikita.ashikhmin/subagent-model-load-latency

Conversation

@nikita-ashihmin

@nikita-ashihmin nikita-ashihmin commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

#1432 made an AIR session/load replay wait for the CLI start before it sent the children's models. So the end of every such replay (loadReplayEnd and the children's subagent_state_update) came only after the CLI started, also for a history without subagents.

  • The replay no longer waits. It sends each child's model as the replay reaches it. During a load the session's model list is not known yet, so the model goes as its id.
  • After the load response, each replayed child whose model the list maps to another entry gets that entry. In the AIR form, this also applies to a child that the replay already ended: it is a more exact snapshot of the same configuration. In the RFD form, the current states after the load response carry the entry, as before.
  • modelEntryFor and modelDisplayName keep their results per model list. reportModel skips a model only when the client already got it, so a failed publication does not block the next report.
  • The buffer of a child that is not announced yet keeps only the latest model report, so model reports do not crowd out the child's output. Other configuration updates wait as they are.
  • A failed load replay forgets its replayed child models.
  • AIR: the runtime forgets the configuration of an ended child.

Validation

  • npm run build, npm run check

  • npm run test:run, two runs: 3323 passed, 30 skipped.

  • src/tests/acp-scenarios.test.ts, 30 runs in 6 parallel workers: no failure.

  • New tests: the load end event before the CLI start, with and without subagents (both fail on main); the post-load refinement through the load path, in both forms; a retry after a failed model update; the buffer; the cleanup; the memo after a list change.

  • Microbenchmark of 10,000 child responses over 200 children, with 51 models:

    before after
    modelEntryFor, last entry 12.16 µs 0.23 µs
    modelEntryFor, no match 64.60 µs 0.08 µs
    reportModel, AIR 13.66 µs 4.03 µs
    reportModel, RFD 12.80 µs 3.23 µs

Related

agentclientprotocol#1432 made an AIR `session/load` replay wait for the CLI start before it
sent the children's models, so the end of every such replay
(`loadReplayEnd`, the children's `subagent_state_update`) came only after
the CLI started, also for a history without subagents.

- The replay never waits. It sends each child's model as the replay
  reaches it. A load lacks the session's model list during the replay,
  so the model goes as its id.
- After the load response, each replayed child whose model the list maps
  to another entry gets that entry, also when the replay ended the child.
- `modelEntryFor` and `modelDisplayName` keep their results per list, and
  `reportModel` skips a model that the child already has.
- The buffer of a child that is not announced keeps only its latest
  configuration update, so model reports do not crowd out its output.
- AIR: the runtime forgets the configuration of an ended child.
@nikita-ashihmin
nikita-ashihmin merged commit eb9d63e into agentclientprotocol:main Oct 26, 2026
2 checks passed
nikita-ashihmin added a commit to nikita-ashihmin/claude-agent-acp that referenced this pull request Oct 26, 2026
…pdate

- RFD: a load replay maps no model to the session's model list, which the
  CLI start brings later. The replay now still gets the session's models,
  so the current states after the load response map each child's model
  to the root entry, as before agentclientprotocol#1433.
- `reportModel` skips a model only when the client got it. A publication
  that failed does not block the next report.
- A failed load replay also forgets its replayed AIR child models.
- The buffer of a child that is not announced collapses only the model
  reports of `reportModel`. Any other configuration update waits as it is.
nikita-ashihmin added a commit that referenced this pull request Oct 26, 2026
…pdate (#1434)

## Summary

Follow-up to #1433, which was merged before these review fixes landed.

- **RFD child models after a load.** On a real `session/load` (session
not live in this process), #1433 also gave `RfdSubagentReplay` no model
list, so after the load response `currentStates` could not map a child's
model to the root session's `model` entry. RFD children kept the raw
model ID. The replay now reads the session's models when needed; only
the in-replay mapping is off while the load replays.
- **Retry after a failed publish.** `reportModel` skipped a model that
matched the stored options, which are written before the publish. A
failed publish then blocked every later report of the same model. It now
compares with the last model the client actually received.
- **Failed load replay.** The replayed child models are also dropped
when the replay itself fails.
- The buffer of an unannounced child collapses only model reports from
`reportModel`; other config updates stay as they are.

## Tests

- `replayRfd` gained a `load` option that replays like a real load;
"sends the model of each child's responses, and after the load response
only a changed entry" uses it (fails without the fix).
- A retry after a failed publish, for the RFD and AIR forms.
- "refines an ended AIR child's model" now goes through the load path.
- `npm run build`, `npm run check`, `npm run test:run`: 3323 passed, 30
skipped.

## Related

- Follow-up to #1433 and #1432
- RFD change:
agentclientprotocol/agent-client-protocol#2482
- RFD section: [Child
configuration](https://github.com/agentclientprotocol/agent-client-protocol/blob/main/docs/rfds/subagents.mdx#child-configuration)
- JetBrains issue:
[IJAI-4754](https://youtrack.jetbrains.com/issue/IJAI-4754)
benbrandt pushed a commit that referenced this pull request Oct 26, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.96.0](v0.95.0...v0.96.0)
(2026-10-26)


### Features

* report SendMessage delegations as linked session messages
([#1424](#1424))
([739dde3](739dde3))
* report the model of each native subagent
([#1432](#1432))
([c319e5e](c319e5e))


### Bug Fixes

* do not hold an AIR load replay until the CLI starts
([#1433](#1433))
([eb9d63e](eb9d63e))
* refine RFD child models after a load, and retry a failed model update
([#1434](#1434))
([9a8bf71](9a8bf71))
* send subagents' current state after a load response
([#1423](#1423))
([17a967b](17a967b))
* update to Claude Code 2.1.310
([#1435](#1435))
([2f3c6bb](2f3c6bb))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: acp-release-bot[bot] <246668977+acp-release-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant