Sidekick app intents: after switching between two intents of the same app, the first tool call goes to the previous surface ("Tool not found" / "connection disconnected")

Our app has two admin.app.intent.render extensions: application/loyalty-program with the tool apply_change, and application/email with apply_email_change. Each one registers its tool with shopify.tools.register() in the panel’s mount effect. Sidekick calls the tool through invoke_app_intent, and the call is held until the merchant presses Save.

Repro (≈100 %, dev store, app built with CLI 4.8.3):

  1. In one Sidekick conversation, ask for a loyalty change. The intent opens, the tool call arrives within 10 ms of registration, and the merchant saves.
  2. In the same conversation, ask for an email change. The email intent opens, and its tool is registered right away (we trace this).
  3. The tool call never reaches the new surface. Sidekick reports:
    • Tool apply_email_change not found, when each extension’s tools.json lists only its own tool;
    • connection disconnected, when both extensions declare both tools in a shared tools.json and every surface registers both.
  4. Sending the same request again is delivered to the new surface immediately.

What we ruled out:

  • intents.response.ok() sent immediately, ok() sent 1 s after the tool answer, intents.response.closed(), and no response at all: the result is the same in every case.
  • No tool call reaches the previous surface either, even though it is still mounted and has the other tool registered.
  • Registering earlier (at module evaluation or in render): calls are not delivered at all, 0 of 5.
  • It looks as if the host keeps the previous intent surface “active”: it checks the call against that surface’s manifest and dispatches it there, after its connection is already closed.

Questions:

  1. Is a single conversation expected to switch between two intents of one app? If yes, how should an extension end its surface so that the next intent becomes active? ok() and closed() don’t do it.
  2. Is there a supported way to have one surface serve several intent types, or should apps keep one intent per app?

We can share timestamps and EXT versions for any run.

1 Like