Skip to content

🔧 update: inject sender userId into LLM context so owner is correctly identified via web dashboard#84

Open
Copilot wants to merge 3 commits into
devfrom
copilot/debug-tinyclaw-issue
Open

🔧 update: inject sender userId into LLM context so owner is correctly identified via web dashboard#84
Copilot wants to merge 3 commits into
devfrom
copilot/debug-tinyclaw-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 20, 2026

When the owner interacts through the web dashboard, the LLM was misidentifying them as a "friend" and refusing owner-only actions (e.g., changing the companion's name). The system prompt declared cli:owner as the owner userId, but no userId was ever passed alongside incoming messages — leaving the LLM to guess, and incorrectly infer that a web session couldn't be cli:owner.

Change

packages/core/src/loop.ts

  • Added sanitizeUserIdForPrompt() to strip backticks, square brackets, and newlines from userId before embedding it in any prompt, preventing a crafted userId from breaking the marker format or injecting additional instructions.
  • Sender identity is now appended directly to the system prompt for the turn rather than injected as a separate system message immediately before the user message. This ensures the identity covers the entire turn — including all tool-follow-up user messages — without needing per-message injection.
// Before
const messages: Message[] = [
  { role: 'system', content: systemPrompt },
  ...history,
  { role: 'system', content: `[Current message sender: userId = \`${userId}\`]` },
  { role: 'user', content: sanitizedMessage },
];

// After
const senderIdentityPrompt = `\n\n[Current message sender: userId = \`${sanitizeUserIdForPrompt(userId)}\`]`;
const messages: Message[] = [
  { role: 'system', content: systemPrompt + senderIdentityPrompt },
  ...history,
  { role: 'user', content: sanitizedMessage },
];

packages/core/tests/loop.test.ts

  • Added assertions that the [Current message sender: userId = ...] marker is present in the system prompt content and that the immediately following message is the user turn (no separate system entry in between).
  • Existing tool-summary at(-2) / at(-1) assertions remain correct and unchanged.

The userId passed here is resolved server-side from configManager.get('owner.ownerId'), so the LLM now has a ground-truth sender identity to match against the ownerId in the system prompt — regardless of which channel the message arrived through.

@warengonzaga warengonzaga changed the title fix: inject sender userId into LLM context so owner is correctly identified via web dashboard 🔧 update: inject sender userId into LLM context so owner is correctly identified via web dashboard May 20, 2026
@warengonzaga warengonzaga marked this pull request as ready for review May 20, 2026 11:54
Copilot AI review requested due to automatic review settings May 20, 2026 11:54
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the core agent loop prompt construction to explicitly provide the LLM with the current sender’s userId, so owner-vs-friend authority rules can be applied correctly when chatting via the web dashboard.

Changes:

  • Adds a system message marker ([Current message sender: userId = ...]) immediately before the incoming user message in the LLM message array.
  • Documents the rationale inline to reduce future regressions around owner identification.

Comment thread packages/core/src/loop.ts
Comment thread packages/core/src/loop.ts
Comment thread packages/core/src/loop.ts
Copilot AI and others added 2 commits May 20, 2026 12:03
Copilot AI requested a review from warengonzaga May 20, 2026 12:07
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.

3 participants