Skip to content

fix: run Composio meta tools in a per-conversation tool-router session#1004

Open
milovate wants to merge 2 commits into
masterfrom
fix/composio-manage-connections
Open

fix: run Composio meta tools in a per-conversation tool-router session#1004
milovate wants to merge 2 commits into
masterfrom
fix/composio-manage-connections

Conversation

@milovate

Copy link
Copy Markdown
Collaborator

COMPOSIO_* tools require a Composio tool-router session, so persist composio_session_id on Conversation and route meta-tool calls through composio.use while keeping app tools on tools.execute.

Q/A checklist

  • I have tested my UI changes on mobile and they look acceptable
  • I have tested changes to the workflows in both the API and the UI
  • I have done a code review of my changes and looked at each line of the diff + the references of each function I have changed
  • My changes have not increased the import time of the server
How to check import time?

time python -c 'import server'

You can visualize this using tuna:

python3 -X importtime -c 'import server' 2> out.log && tuna out.log

To measure import time for a specific library:

$ time python -c 'import pandas'

________________________________________________________
Executed in    1.15 secs    fish           external
   usr time    2.22 secs   86.00 micros    2.22 secs
   sys time    0.72 secs  613.00 micros    0.72 secs

To reduce import times, import libraries that take a long time inside the functions that use them instead of at the top of the file:

def my_function():
    import pandas as pd
    ...

Legal Boilerplate

Look, I get it. The entity doing business as “Gooey.AI” and/or “Dara.network” was incorporated in the State of Delaware in 2020 as Dara Network Inc. and is gonna need some rights from me in order to utilize my contributions in this PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Dara Network Inc can use, modify, copy, and redistribute my contributions, under its choice of terms.

@milovate

Copy link
Copy Markdown
Collaborator Author

@codex review

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds meta-tool routing to Composio integration. It introduces a session-id cache key and three utilities: is_composio_meta_tool() detects meta tools by slug prefix, get_or_create_composio_tool_router_session_id() creates or retrieves cached tool-router sessions, and render_composio_meta_tool_scope_warning() validates scope consistency and renders warnings. ComposioLLMTool.call() now branches execution—meta tools route through tool-router sessions via session.execute(), while non-meta tools use the existing composio.tools.execute() path. The UI imports and renders the scope-warning widget in the functions input section.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: running Composio meta tools in a per-conversation tool-router session, which directly reflects the core implementation details in the changeset.
Description check ✅ Passed The description provides a clear summary of the changes and includes the required Q/A checklist and legal boilerplate from the template, though all checklist items remain unchecked.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@milovate

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor

cursor Bot commented Jun 11, 2026

Copy link
Copy Markdown

Skipping Bugbot: Unable to authenticate your request. Please make sure Bugbot is properly installed and configured for this repository.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d84ab5b05

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread functions/composio_tools.py Outdated
Comment on lines +304 to +305
convo = Conversation.objects.get(
id=api_hashids.decode(conversation_id)[0]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Verify the active conversation before reusing its session

This lookup trusts the conversation_id copied from gui.session_state["variables"], but in the bots API path request overrides are merged after the system variables (daras_ai_v2/bots.py:514-516), so a client can send a different variables.conversation_id than the already-validated request conversation. When a COMPOSIO_* tool runs in that scenario, this code will read/reuse/save the Composio session on that unrelated Conversation (or fail if the id is invalid), mixing tool-router workbench/auth state across conversations. Use the validated active conversation ID or verify the decoded conversation matches it before persisting/reusing the session.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@functions/composio_tools.py`:
- Around line 302-316: Wrap the caught exception and re-raise the UserError with
the original exception chained so tracebacks are preserved: change the except
block that catches (IndexError, Conversation.DoesNotExist) around
Conversation.objects.get(...) / api_hashids.decode(conversation_id) to capture
the exception (e) and use "raise UserError(f'Conversation with
id={conversation_id} not found') from e" instead of raising without chaining.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 94fb6000-4e6e-4873-8e3f-d9c642faee87

📥 Commits

Reviewing files that changed from the base of the PR and between 19934e2 and 7d84ab5.

📒 Files selected for processing (4)
  • bots/migrations/0121_conversation_composio_session_id.py
  • bots/models/convo_msg.py
  • daras_ai_v2/base.py
  • functions/composio_tools.py

Comment thread functions/composio_tools.py Outdated
Comment on lines +302 to +316
if conversation_id:
try:
convo = Conversation.objects.get(
id=api_hashids.decode(conversation_id)[0]
)
except (IndexError, Conversation.DoesNotExist):
raise UserError(f"Conversation with id={conversation_id} not found")
if convo.composio_session_id:
return convo.composio_session_id
session = composio.create(
user_id=user_id, manage_connections=manage_connections
)
convo.composio_session_id = session.session_id
convo.save(update_fields=["composio_session_id"])
return session.session_id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Chain the exception for better error context.

When re-raising as UserError, chain the original exception to preserve the traceback for debugging.

Proposed fix
         try:
             convo = Conversation.objects.get(
                 id=api_hashids.decode(conversation_id)[0]
             )
         except (IndexError, Conversation.DoesNotExist):
-            raise UserError(f"Conversation with id={conversation_id} not found")
+            raise UserError(f"Conversation with id={conversation_id} not found") from None

Using from None explicitly suppresses the chained exception when the original is not meaningful to callers (IndexError from decode is an implementation detail).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if conversation_id:
try:
convo = Conversation.objects.get(
id=api_hashids.decode(conversation_id)[0]
)
except (IndexError, Conversation.DoesNotExist):
raise UserError(f"Conversation with id={conversation_id} not found")
if convo.composio_session_id:
return convo.composio_session_id
session = composio.create(
user_id=user_id, manage_connections=manage_connections
)
convo.composio_session_id = session.session_id
convo.save(update_fields=["composio_session_id"])
return session.session_id
if conversation_id:
try:
convo = Conversation.objects.get(
id=api_hashids.decode(conversation_id)[0]
)
except (IndexError, Conversation.DoesNotExist):
raise UserError(f"Conversation with id={conversation_id} not found") from None
if convo.composio_session_id:
return convo.composio_session_id
session = composio.create(
user_id=user_id, manage_connections=manage_connections
)
convo.composio_session_id = session.session_id
convo.save(update_fields=["composio_session_id"])
return session.session_id
🧰 Tools
🪛 Ruff (0.15.15)

[warning] 308-308: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@functions/composio_tools.py` around lines 302 - 316, Wrap the caught
exception and re-raise the UserError with the original exception chained so
tracebacks are preserved: change the except block that catches (IndexError,
Conversation.DoesNotExist) around Conversation.objects.get(...) /
api_hashids.decode(conversation_id) to capture the exception (e) and use "raise
UserError(f'Conversation with id={conversation_id} not found') from e" instead
of raising without chaining.

Source: Linters/SAST tools

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
functions/inbuilt_tools.py (1)

329-343: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Serialize reset with session creation.

Lines 329-343 update Conversation.composio_session_id, but the create path in functions/composio_tools.py protects the same row with transaction.atomic() + select_for_update(). Without taking that same lock here, a reset racing with a meta-tool call can clear a freshly created router session id after composio.create(...) returns, orphaning the external session and violating the per-conversation lifecycle this PR is introducing.

Proposed fix
+from django.db import transaction
 from django.core.exceptions import ValidationError
 from django.utils import timezone
 ...
     def call(self) -> dict:
         from bots.models import Conversation
         from routers.bots_api import api_hashids

         try:
-            convo = Conversation.objects.get(
-                id=api_hashids.decode(self.conversation_id)[0]
-            )
+            with transaction.atomic():
+                convo = Conversation.objects.select_for_update().get(
+                    id=api_hashids.decode(self.conversation_id)[0]
+                )
+                convo.reset_at = timezone.now()
+                convo.composio_session_id = ""
+                convo.save(update_fields=["reset_at", "composio_session_id"])
         except (IndexError, Conversation.DoesNotExist):
             return {
                 "success": False,
                 "error": (
                     f"Conversation not found for conversation_id={self.conversation_id}. "
                     "Please call this tool from an active deployment."
                 ),
             }
-        convo.reset_at = timezone.now()
-        convo.composio_session_id = ""
-        convo.save(update_fields=["reset_at", "composio_session_id"])
         return {"success": True}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@functions/inbuilt_tools.py` around lines 329 - 343, The reset path in
inbuilt_tools.py must acquire the same DB lock as composio.create to avoid
races: wrap the Conversation lookup and update in a transaction.atomic() block
and fetch the row with select_for_update() (i.e., replace
Conversation.objects.get(...) with
Conversation.objects.select_for_update().get(...)) before setting convo.reset_at
and convo.composio_session_id and saving; keep the same
IndexError/Conversation.DoesNotExist handling around the locked get so you still
return the same error when absent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@functions/inbuilt_tools.py`:
- Around line 329-343: The reset path in inbuilt_tools.py must acquire the same
DB lock as composio.create to avoid races: wrap the Conversation lookup and
update in a transaction.atomic() block and fetch the row with
select_for_update() (i.e., replace Conversation.objects.get(...) with
Conversation.objects.select_for_update().get(...)) before setting convo.reset_at
and convo.composio_session_id and saving; keep the same
IndexError/Conversation.DoesNotExist handling around the locked get so you still
return the same error when absent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: de4f64e4-b1ef-44d2-98b3-fe843fca8641

📥 Commits

Reviewing files that changed from the base of the PR and between 7d84ab5 and 39f6469.

📒 Files selected for processing (2)
  • functions/composio_tools.py
  • functions/inbuilt_tools.py

@milovate milovate self-assigned this Jun 12, 2026
@milovate milovate requested a review from devxpy June 12, 2026 00:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@functions/composio_tools.py`:
- Around line 118-121: Don’t fall back to a stale function["slug"] when the row
has a URL that no longer points at a tool: call
get_external_tool_slug_from_url(url) and only use function.get("slug") when the
URL is missing/empty; if the URL exists but yields no slug, treat the row as
having no composio slug. Update the composio_tool_slug assignment logic (the
composio_tool_slug variable, get_external_tool_slug_from_url, and the
is_composio_meta_tool check) so you only consult the stored slug when there is
no URL to resolve.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 28e873e0-6dc6-4061-a519-c8c6c2ac72c7

📥 Commits

Reviewing files that changed from the base of the PR and between 39f6469 and 13d2148.

📒 Files selected for processing (2)
  • functions/base_llm_tool.py
  • functions/composio_tools.py

Comment on lines +118 to +121
composio_tool_slug = get_external_tool_slug_from_url(
function.get("url") or ""
) or function.get("slug")
if not composio_tool_slug or not is_composio_meta_tool(composio_tool_slug):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid classifying rows from stale slug state.

get_external_tool_slug_from_url(...) or function.get("slug") can treat a non-tool row as a Composio meta tool if the dict still carries an older slug. The editor in functions/base_llm_tool.py refreshes fn["slug"] only when the current URL resolves to a tool, and its non-tool branch does not clear that field, so this warning can fire after the row stops pointing at /tools/.

Suggested change
-        composio_tool_slug = get_external_tool_slug_from_url(
-            function.get("url") or ""
-        ) or function.get("slug")
+        url = function.get("url") or ""
+        composio_tool_slug = get_external_tool_slug_from_url(url)
+        if not composio_tool_slug and not url:
+            composio_tool_slug = function.get("slug")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
composio_tool_slug = get_external_tool_slug_from_url(
function.get("url") or ""
) or function.get("slug")
if not composio_tool_slug or not is_composio_meta_tool(composio_tool_slug):
url = function.get("url") or ""
composio_tool_slug = get_external_tool_slug_from_url(url)
if not composio_tool_slug and not url:
composio_tool_slug = function.get("slug")
if not composio_tool_slug or not is_composio_meta_tool(composio_tool_slug):
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@functions/composio_tools.py` around lines 118 - 121, Don’t fall back to a
stale function["slug"] when the row has a URL that no longer points at a tool:
call get_external_tool_slug_from_url(url) and only use function.get("slug") when
the URL is missing/empty; if the URL exists but yields no slug, treat the row as
having no composio slug. Update the composio_tool_slug assignment logic (the
composio_tool_slug variable, get_external_tool_slug_from_url, and the
is_composio_meta_tool check) so you only consult the stored slug when there is
no URL to resolve.

@devxpy

devxpy commented Jun 12, 2026

Copy link
Copy Markdown
Member

having a conversation_id means that this only works for deployments? I think the COMPOSIO_SEARCH_TOOLS will return a session_id so we can just use that in-process inside the celery task

milovate and others added 2 commits June 12, 2026 13:39
Route COMPOSIO_* tools through composio.create/use + session.execute so
meta-tool chains work within a single run, while app tools keep the
existing tools.execute path. Warn in the builder when Composio meta tools
use mixed scopes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@milovate milovate force-pushed the fix/composio-manage-connections branch from 13d2148 to 81cc2c3 Compare June 12, 2026 08:20

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
functions/composio_tools.py (1)

113-116: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid stale-slug fallback when URL is present but no longer resolves to a tool.

get_external_tool_slug_from_url(url) or function.get("slug") at Lines 113-116 can classify a non-tool row as meta if slug is stale. Only fall back to stored slug when URL is empty.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@functions/composio_tools.py` around lines 113 - 116, The code currently falls
back to function.get("slug") even when a URL is present but no longer resolves;
change the logic so you only use get_external_tool_slug_from_url(url) when url
is non-empty and only fall back to the stored slug when the URL is empty.
Concretely: retrieve url = function.get("url") or "" ; if url is non-empty call
get_external_tool_slug_from_url(url) and assign composio_tool_slug from that
result; otherwise assign composio_tool_slug = function.get("slug"); then call
is_composio_meta_tool(composio_tool_slug) as before. This prevents classifying
rows as meta based on a stale stored slug when the URL exists but doesn't
resolve.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@functions/composio_tools.py`:
- Around line 138-142: The cached COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY is shared
across all callers causing sessions to be reused when user_id changes; update
the caching to partition by caller identity (e.g., include user_id or a caller
scope in the key) before reading/writing gui.session_state so each user_id gets
its own stored session_id; in the function that calls composio.create and
interacts with gui.session_state (the block that checks
COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY, calls composio.create(user_id=...,
manage_connections=...), and assigns session.session_id) build a composite key
(like f"{COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY}:{user_id}" or a per-scope map) to
read/assign the correct session_id and fall back to creating a new session when
no matching keyed entry exists.

---

Duplicate comments:
In `@functions/composio_tools.py`:
- Around line 113-116: The code currently falls back to function.get("slug")
even when a URL is present but no longer resolves; change the logic so you only
use get_external_tool_slug_from_url(url) when url is non-empty and only fall
back to the stored slug when the URL is empty. Concretely: retrieve url =
function.get("url") or "" ; if url is non-empty call
get_external_tool_slug_from_url(url) and assign composio_tool_slug from that
result; otherwise assign composio_tool_slug = function.get("slug"); then call
is_composio_meta_tool(composio_tool_slug) as before. This prevents classifying
rows as meta based on a stale stored slug when the URL exists but doesn't
resolve.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 43ae4080-2102-4aba-ae89-2ba163c5e980

📥 Commits

Reviewing files that changed from the base of the PR and between 13d2148 and 81cc2c3.

📒 Files selected for processing (2)
  • functions/base_llm_tool.py
  • functions/composio_tools.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • functions/base_llm_tool.py

Comment on lines +138 to +142
if session_id := gui.session_state.get(COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY):
return session_id
session = composio.create(user_id=user_id, manage_connections=manage_connections)
gui.session_state[COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY] = session.session_id
return session.session_id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Session cache is not partitioned by caller identity/scope.

At Line 138, the cached COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY is reused for all later calls in the same GUI session, even if user_id changes. That can route meta-tool execution through the wrong tool-router session and mix identities across runs/conversations.

Suggested fix
-COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY = "__composio_tool_router_session_id__"
+COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY = "__composio_tool_router_session_id__"

 def get_or_create_composio_tool_router_session_id(
     composio: Composio,
     *,
     user_id: str,
     redirect_url: str,
 ) -> str:
     manage_connections = {"enable": True, "callback_url": redirect_url}
-
-    if session_id := gui.session_state.get(COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY):
-        return session_id
+    key = f"{COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY}:{user_id}"
+    if session_id := gui.session_state.get(key):
+        return session_id
     session = composio.create(user_id=user_id, manage_connections=manage_connections)
-    gui.session_state[COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY] = session.session_id
+    gui.session_state[key] = session.session_id
     return session.session_id
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@functions/composio_tools.py` around lines 138 - 142, The cached
COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY is shared across all callers causing
sessions to be reused when user_id changes; update the caching to partition by
caller identity (e.g., include user_id or a caller scope in the key) before
reading/writing gui.session_state so each user_id gets its own stored
session_id; in the function that calls composio.create and interacts with
gui.session_state (the block that checks COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY,
calls composio.create(user_id=..., manage_connections=...), and assigns
session.session_id) build a composite key (like
f"{COMPOSIO_TOOL_ROUTER_SESSION_ID_KEY}:{user_id}" or a per-scope map) to
read/assign the correct session_id and fall back to creating a new session when
no matching keyed entry exists.

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.

2 participants