We tested the frontend agent.session lifecycle in a local Anna App development environment and found several issues that may affect both development and real usage:
- Expired sessions cannot be deleted and continue to occupy the active session quota.
- The session expiration time appears to be calculated from creation time, not refreshed by later activity.
- After restarting the local
anna-app devserver, an existingapp_session_uuidcannot be used again, even before it expires.
Test Background
We created a dedicated Anna App demo named test-session-app to test the session lifecycle.
This demo only uses the frontend raw RPC APIs. It does not use the high-level helper.
The core calls are:
await anna.agent.session.create({ submode: "auto" });
await anna.agent.session.run({
app_session_uuid,
content,
});
await anna.agent.session.delete({
app_session_uuid,
});
For session.run, we handle streaming using the raw RPC flow: first call agent.session.run to get { stream_id, run_id }, then listen to rpc.stream events and collect frames by stream_id.
The page keeps a list of currently held sessions and persists app_session_uuid values to localStorage, so we can test whether the same session can still be used after page refresh or local dev server restart.
We only persist app_session_uuid. We do not persist app_session_token, because the frontend API does not expose it.
Issue 1: Expired sessions cannot be deleted, causing active session quota to remain occupied
Reproduction steps:
- Start the test app in a local
anna-app devenvironment. - Create 5 agent sessions.
- Before they expire, run “clean up all”. All 5 sessions can be deleted successfully and return
{ deleted: true }. - Create another 5 sessions.
- Wait longer than the returned
expires_in: 600seconds. - Try to call
session.deletefor these 5 sessions. - All delete requests fail. After that, creating a new session returns HTTP 429, saying the active session limit for the same app/executa has been reached.
Relevant logs:
session.create result
{"app_session_uuid":"aps_p4olz6jalwla7olqvldelp","expires_in":600}
session.delete failed
{
"app_session_uuid":"aps_p4olz6jalwla7olqvldelp",
"message":"HTTP 401: {\"detail\":{\"code\":-32001,\"errorCode\":\"APP_NOT_GRANTED\",\"message\":\"invalid app_session_token: Signature has expired.\"}}"
}
session.create failed
session.mint failed: HTTP 429
{"detail":"dev mode: 已达同一 app/executa 活跃 session 上限 (5);请先 delete 旧 session 或 revoke 后重试。"}
Actual behavior:
After a session expires, session.delete fails because the token has expired. However, these sessions still count toward the active session limit, so no new sessions can be created.
Expected behavior:
Expired sessions should satisfy at least one of these behaviors:
- Expired sessions should be automatically released from the active session quota.
session.delete/ revoke should still be able to release the session after the app session token expires.- There should be a cleanup/revoke API that does not depend on an expired app session token.
- If expired sessions still count toward quota, this behavior should be clearly documented, including the server-side cleanup timing.
The current issue is that the session has expired and can no longer be used by the client, but it also cannot be deleted, while the server still counts it as active. This can leave the local dev environment stuck until an unknown server-side cleanup happens or some external management tool is used.
Issue 2: Session expiration appears to be fixed from creation time, not refreshed after use
Reproduction steps:
- Create a session. It returns
expires_in: 600. - About 5 minutes later, call
session.run. The request succeeds and the stream returns normally. - About another 5 minutes later, call
session.delete. session.deletefails because the token has expired.
Relevant logs:
[15:29:00] session.create result
{"app_session_uuid":"aps_tzm343vlftwifvyygrf5mc","expires_in":600}
[15:34:25] session.run started
{"app_session_uuid":"aps_tzm343vlftwifvyygrf5mc"}
[15:34:37] session.run completed
[15:40:29] session.delete started
{"app_session_uuid":"aps_tzm343vlftwifvyygrf5mc"}
[15:40:31] session.delete failed
"invalid app_session_token: Signature has expired."
Actual behavior:
After session.run succeeds, the session lifetime is not extended. It still expires roughly 10 minutes after creation.
We would like to confirm the intended official semantics here.
If expires_in is a fixed TTL, then the current behavior is understandable, but the documentation should clearly state that an agent session expires based on session.create time, and later session.run calls do not refresh the lifetime.
If the intended behavior is closer to an active session or idle timeout, then we would expect a successful session.run to refresh the session lifetime. Otherwise, in long-running or multi-turn interaction scenarios, a session may expire while the user is still actively using it.
Also, session.create currently returns expires_in, but we do not see updated TTL or expiry information after later runs. If the TTL is fixed, it would be useful to expose expires_at so the frontend can display and reason about expiration accurately.
Issue 3: After restarting local anna-app dev, the same app_session_uuid cannot be used again
Reproduction steps:
- Create a session and get its
app_session_uuid. - Restart the local
anna-app devbackend before the session expires. - The frontend restores the saved
app_session_uuidfromlocalStorage. - Call
session.run. - The call fails with
no cached session.
Relevant logs:
session.create result
{"app_session_uuid":"aps_ob6mvxdr33robcdhhwffoo","expires_in":600}
session.run started
{"app_session_uuid":"aps_ob6mvxdr33robcdhhwffoo"}
session.run failed
{"message":"no cached session"}
After checking the local @anna-ai/cli harness implementation, our understanding is that anna-app dev keeps an in-memory mintedAgent map from app_session_uuid to app_session_token.
Both session.run and session.delete depend on this in-memory cache to retrieve the token. Once the local dev server restarts, the map is lost. Even if the server-side session has not expired yet, the frontend cannot continue using it with only the app_session_uuid.
If this is an intended limitation, it would be helpful to document it clearly:
app_session_uuidalone is not a resumable credential.- The frontend cannot restore a session across dev harness restarts using only
app_session_uuid. - The session object returned by
runtime.agent.session({ submode: "auto" })is only valid within the current runtime/harness lifecycle. - If cross-refresh, cross-process, or cross-program session reuse is needed, an official
session.resume/recover API or another safe persistence mechanism is required.
Suspected Causes
Based on the observed behavior, there may be two separate causes:
- Server-side active session quota release seems to depend on explicit delete/revoke, but delete depends on a still-valid
app_session_token. Once the token expires, the client loses permission to delete the session, while the server-side active quota is not released. - The local dev harness only stores
app_session_uuid -> app_session_tokenin memory. It does not persist this mapping, and it does not appear to have a way to recover the token from the server using onlyapp_session_uuid. Therefore, restarting the local dev server makes existing session UUIDs unusable.
Questions for the Anna team
- Is
expires_infor agent sessions a fixed TTL or an idle timeout? - Should a successful
session.runrefresh the session expiration time? - Should expired sessions continue to count toward the active session quota?
- If the session token has expired, how should the client release that session?
- Are there plans to provide a
session.resume,session.revoke, or management cleanup API so an app can recover or release a session byapp_session_uuid? - In local
anna-app dev, isapp_session_uuidintended to be reusable across dev server restarts?
Impact
These behaviors affect how agent sessions can be integrated in practice:
- The frontend cannot reliably hold sessions for longer workflows.
- Once a session expires, it may become impossible to release manually.
- The local dev environment can easily hit the active session limit and get stuck.
- Persisting only
app_session_uuidis not enough to restore a session. - Multi-session testing, page refresh recovery, multi-turn workflows, and long editing sessions are all affected.
Could the Anna team confirm whether these behaviors are expected? If they are expected, we would appreciate clearer documentation and recommended practices. If they are not expected, the highest-priority issue seems to be that expired sessions cannot be released but still occupy active session quota.