openclaw - 💡(How to fix) Fix [Feature]: Allow agent() RPC to honor caller-supplied sessionId when agentId is provided [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#51532Fetched 2026-04-08 01:09:57
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
commented ×1cross-referenced ×1

When calling agent({ sessionId, agentId }) without sessionKey, the caller's sessionId is silently discarded because agentId triggers automatic sessionKey derivation (agent:<agentId>:main), which then overwrites resolvedSessionId. This makes it impossible for plugins to manage independent sessions (not tracked in sessions.json) for non-main agents.

Root Cause

When calling agent({ sessionId, agentId }) without sessionKey, the caller's sessionId is silently discarded because agentId triggers automatic sessionKey derivation (agent:<agentId>:main), which then overwrites resolvedSessionId. This makes it impossible for plugins to manage independent sessions (not tracked in sessions.json) for non-main agents.

RAW_BUFFERClick to expand / collapse

Summary

When calling agent({ sessionId, agentId }) without sessionKey, the caller's sessionId is silently discarded because agentId triggers automatic sessionKey derivation (agent:<agentId>:main), which then overwrites resolvedSessionId. This makes it impossible for plugins to manage independent sessions (not tracked in sessions.json) for non-main agents.

Problem to solve

We're building a "Topics" feature — user-initiated independent conversations managed entirely by our plugin, outside OpenClaw's sessionKey system. For the main agent, calling agent({ sessionId: <uuid> }) without agentId or sessionKey works perfectly: the caller's sessionId is respected, no sessions.json entry is created, and the .jsonl transcript is written to the main agent's sessions directory.

However, this pattern cannot be extended to non-main agents. When we pass agentId to route to a specific agent, resolveExplicitAgentSessionKey() (src/config/sessions/main-session.ts:40-49) always derives agent:<agentId>:main as the sessionKey. This causes agent.ts line 350's if (requestedSessionKey) block to execute, which overwrites the caller's sessionId at line 420 and writes to sessions.json — defeating the purpose of plugin-managed sessions.

The current behavior matrix:

Call patternCaller's sessionIdsessions.jsonAgent routed to
agent({ sessionId: uuid })RespectedNot writtenmain (default)
agent({ sessionId: uuid, agentId: "foo" })DiscardedWrittenfoo

Proposed solution

When agent() receives both sessionId and agentId but no sessionKey, respect the caller's sessionId and route to the specified agent without deriving a sessionKey or writing to sessions.json.

One possible approach: in agent.ts, when requestedSessionKeyRaw is undefined but both sessionId and agentId are provided, skip the resolveExplicitAgentSessionKey() fallback. The agent routing can still use agentId to resolve the correct sessions directory and agent config, but without entering the sessionKey-based session management path.

Expected behavior after the change:

Call patternCaller's sessionIdsessions.jsonAgent routed to
agent({ sessionId: uuid })RespectedNot writtenmain (default)
agent({ sessionId: uuid, agentId: "foo" })RespectedNot writtenfoo
agent({ agentId: "foo" })N/AWrittenfoo (unchanged)

Impact

This would enable plugins to manage independent sessions for any agent, not just main. Our plugin currently has to restrict its Topics feature to the main agent only due to this limitation. Other plugins building similar features (conversation branching, sandboxed sessions, etc.) would also benefit.

Additional information

Our design document with full analysis is available at: https://github.com/coclaw/coclaw/blob/main/docs/designs/topic-management.md (see the "Current version constraint: main agent only" section and the research doc referenced therein for a detailed description of this limitation).

Relevant source locations in OpenClaw:

  • src/gateway/server-methods/agent.ts:289-294 — sessionKey fallback derivation
  • src/gateway/server-methods/agent.ts:350-420 — sessionKey branch that overwrites sessionId
  • src/config/sessions/main-session.ts:40-49resolveExplicitAgentSessionKey always returns a key when agentId is truthy

Reported by the CoClaw team. This issue was discovered while developing @coclaw/openclaw-coclaw, a CoClaw channel plugin for OpenClaw.

extent analysis

Fix Plan

To fix this issue, we need to modify the agent() function to respect the caller's sessionId when both sessionId and agentId are provided, but no sessionKey is given.

Here are the steps:

  • Modify the agent.ts file to check if both sessionId and agentId are provided, but requestedSessionKeyRaw is undefined.
  • If the condition is met, skip the resolveExplicitAgentSessionKey() fallback and use the provided sessionId and agentId to route to the correct agent without deriving a sessionKey or writing to sessions.json.

Example code:

// agent.ts
if (sessionId && agentId && !requestedSessionKeyRaw) {
  // Skip sessionKey derivation and use provided sessionId and agentId
  const agentConfig = getAgentConfig(agentId);
  const sessionsDirectory = getSessionsDirectory(agentConfig);
  // Use sessionId and sessionsDirectory to handle the request
} else {
  // Existing code to handle other cases
}

Verification

To verify that the fix worked, test the agent() function with different call patterns and check the results:

  • Call agent({ sessionId: uuid }) and verify that the caller's sessionId is respected and no entry is written to sessions.json.
  • Call agent({ sessionId: uuid, agentId: "foo" }) and verify that the caller's sessionId is respected, no entry is written to sessions.json, and the request is routed to the correct agent.
  • Call agent({ agentId: "foo" }) and verify that the behavior remains unchanged.

Extra Tips

  • Make sure to update the documentation and design documents to reflect the changes made to the agent() function.
  • Consider adding tests to cover the new behavior and ensure that it works as expected in different scenarios.
  • If other plugins are using the agent() function, consider notifying them of the changes and providing guidance on how to use the updated function.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING