Anna official platform: `agent.session` intermittently hits token cache miss and stalled streams

I encountered two intermittent issues while testing Anna App agent.session behavior on the official platform. To isolate the problem from my production app logic, I created a minimal test project named test-session-app that only exercises the raw session APIs.

The test app uses this flow:

  1. Connect to the Anna runtime from the frontend.
  2. Call anna.agent.session.create({ submode: "auto" }).
  3. Use the returned app_session_uuid to call:
anna.agent.session.run({
  app_session_uuid,
  content,
})
  1. After session.run returns run_id and stream_id, the frontend listens for rpc.stream events and waits for stream frames and the final done signal for that stream_id.

The test app does not depend on business Executas or complex tool calls. It is mainly used to verify the raw lifecycle behavior of agent.session.create / run / delete.

I am currently observing two issues on the official platform.

Issue 1: session.create succeeds, but session.run sometimes fails with no cached app_session token

Sometimes session.create successfully returns an app_session_uuid, but a following session.run call fails with:

{
  "app_session_uuid": "aps_dqjimyk5veg3viruomd6cb",
  "message": "no cached app_session token; create a new session"
}

This looks like the platform returned the app_session_uuid to the app, but the app session token required by session.run was not cached successfully on the platform side, or the run request was routed to an instance that cannot access the corresponding token cache.

One clear symptom is:

  • Local testing with anna-app dev works correctly.
  • After uploading the app to the official platform, it initially worked for me.
  • When another user downloaded/used the same app, they hit no cached app_session token; create a new session.
  • After that, I also started seeing the same error when using the app again.

This suggests the issue may be related to multiple session requests, sessions from different users, platform instance switching, cache isolation, cache expiration, or concurrent requests.

Expected behavior: once session.create successfully returns a non-expired app_session_uuid, a following session.run using that app_session_uuid in the same app iframe should work reliably. If the app is not supposed to persist/use only app_session_uuid, it would be helpful for the documentation to clearly state what additional fields or lifecycle constraints are required.

Issue 2: session.run returns stream_id, but the stream sometimes stalls and never completes

Another issue is that session.run sometimes does not throw an error and does return both run_id and stream_id, but the stream does not continue afterward, or only the first event is received and then it hangs. No final done signal is received, so the app keeps waiting indefinitely.

Example test log:

[21:40:10] ok session.create 开始创建 raw agent session {"submode":"auto"}
[21:40:11] ok session.create 收到 session.create 结果 {"app_session_uuid":"aps_mtqvlo3j63euj6gndagzoy","expires_in":600,"submode":"auto","fixed_client_id":null,"granted_tools":[]}
[21:40:13] ok session.run 开始 raw session.run {"app_session_uuid":"aps_mtqvlo3j63euj6gndagzoy","source":"selected","content":"请用一句中文说明你收到了这个 session.run 请求,并返回当前可见的 session 上下文摘要。"}
[21:40:13] ok session.run 收到 session.run RPC 结果 {"run_id":"9b426a94-c904-4909-8bd1-7ae372f0a2e4","stream_id":"strm_2af38be6ac03400a"}

After this, the frontend waits for rpc.stream events for the returned stream_id, but never receives a complete result or completion signal. This looks like the run was successfully created on the platform side, but stream delivery, stream completion, or the underlying agent execution state was not properly propagated back to the app iframe.

Expected behavior:

  • If the run fails, the stream should emit a clear error frame, or the RPC call itself should fail.
  • If the run succeeds, the stream should deliver content and eventually emit done.
  • The app should not get into a state where run_id / stream_id has been returned, but no further result or terminal signal is ever delivered.

Impact

These two issues make it hard to reliably use agent.session in an Anna App:

  • The token cache miss can make a newly created session immediately unusable.
  • The stalled stream can leave the page in a long-running loading state, with no way for the user to know whether the model is slow, the platform failed, or the app itself has a bug.
  • The issues seem easier to trigger when multiple users use the same published app or when multiple sessions are created/run.

Initial hypotheses

Based on the observed behavior, I suspect the issue may be in the platform session management or stream routing layer:

  1. There may be a race condition between returning app_session_uuid from session.create and writing the internal app session token cache.
  2. session.run may sometimes be routed to an instance that does not have access to the corresponding app session token cache.
  3. Cache keys or isolation boundaries involving user id, client id, app id, iframe instance, or session id may be inconsistent across multiple users or multiple sessions.
  4. After session.run is created successfully, stream events may not always be routed back to the current app iframe, or abnormal termination may not emit an error/done frame.

These are only hypotheses based on the symptoms. I would appreciate confirmation of the intended platform-side lifecycle and caching behavior for agent.session.

Questions for the Anna team

  1. After session.create returns an app_session_uuid, should the app be able to call session.run using only that uuid within its valid lifetime?
  2. Is no cached app_session token; create a new session an expected error on the official platform? If yes, what is the recommended recovery strategy for apps?
  3. After session.run returns run_id / stream_id, does the platform guarantee that the stream will eventually emit either done or an error?
  4. Are there recommended app-side timeout, retry, or concurrency-control strategies for agent.session?
  5. If this is a platform bug, could the team investigate session token cache consistency and stream routing reliability in multi-user and multi-session scenarios?

Hi, and thanks so much for the incredibly detailed report — the minimal [test-session-app] repro and the timestamped logs made it very easy for us to pinpoint exactly what was happening. This is exactly the kind of feedback that helps us harden the platform. :folded_hands:

Here’s what we found and where things stand.

Issue 1 — [no cached app_session token; create a new session]

You diagnosed this almost perfectly. This was a real platform bug, not an app-side mistake.

On the official platform we run multiple server workers behind a load balancer. The short-lived capability token issued by [session.create] was being held in a per-worker location, so when a subsequent [session.run] happened to land on a different worker, that worker couldn’t see the token and returned the misleading “no cached app_session token” error. This is exactly why it was invisible under anna-app dev (single process), worked intermittently for you, and then showed up once traffic from another user shifted which worker handled each call.

This is now fixed. On a cache miss the platform re-derives the token directly from the durable session record (the [app_session_uuid] is committed before it’s ever returned to your app), so a valid, non-expired [app_session_uuid] will now work reliably for [session.run] regardless of which worker handles the request.

To answer your questions directly:

  1. Yes — within its valid lifetime, your app should be able to call [session.run] using only the [app_session_uuid]. The iframe is not expected to persist or manage the token itself.
  2. [no cached app_session token] was not intended behavior — it was the bug above and should no longer occur. The token is short-lived by design; to extend a long-lived session (e.g. after an iframe reload or a long-backgrounded tab) you can call [anna.agent.session.refresh({ app_session_uuid })], which re-mints the token and slides the session window using only the uuid. The one error you should treat as terminal is APP_SESSION_EXPIRED (-32017), where the recommended recovery is to create (or [refresh] a new session.

Issue 2 — [session.run] returns [run_id]/stream_id but the stream stalls

Also a valid catch, thank you. We’ve already landed fixes on the streaming path so that:

  • the background stream pump runs on its own lifecycle (it no longer gets torn down when the originating RPC returns), and
  • the stream always emits a terminal frame — on success a done, and on a run error an [error] frame followed by the terminal done — so your app shouldn’t get stuck in the “[run_id]/stream_id returned but nothing else ever arrives” state.

To your questions:

  1. On the normal path, once [session.run] returns, the stream is expected to deliver content and then emit done (or an [error] frame on failure).
  2. As a general best practice we’d still recommend an app-side timeout as a safety net around [session.run] (≈90s is a reasonable starting point, matching the SDK’s stream timeout), surfacing a retry/cancel affordance to the user rather than spinning indefinitely, and keeping runs on a single session serialized. This keeps the UX resilient regardless of model latency.

What to do on your side

Please make sure you’re on the latest CLI / runtime and re-test against the platform — the Issue 1 fix is server-side and live, so a fresh run of your [test-session-app] flow should no longer hit the token error. If you still see either symptom after updating, send us the [app_session_uuid], [run_id], and stream_id plus a rough timestamp and we’ll trace it directly.

Really appreciate you taking the time to isolate this so cleanly — it genuinely made the fix faster. Don’t hesitate to reach out anytime; reports like this make [agent.session] better for every Anna App developer. :rocket: