Skip to content

feat(core): add request context for per-user entity settings#6457

Merged
0xbbjoker merged 4 commits into
developfrom
feat/entity-settings-context
Feb 4, 2026
Merged

feat(core): add request context for per-user entity settings#6457
0xbbjoker merged 4 commits into
developfrom
feat/entity-settings-context

Conversation

@0xbbjoker
Copy link
Copy Markdown
Contributor

@0xbbjoker 0xbbjoker commented Feb 3, 2026

Summary

  • Adds RequestContext using AsyncLocalStorage to propagate per-request entity settings
  • Enables runtime methods to access the originating entity context without explicit parameter passing
  • Includes helper methods: withEntityContext(), getRequestContext(), getEntitySettings()

Test plan

  • Unit tests for RequestContext class
  • Integration tests for runtime context propagation

🤖 Generated with Claude Code


Note

Medium Risk
Changes AgentRuntime.getSetting() resolution to prefer request-scoped entity settings (including null as an explicit override), which can affect how secrets/config are sourced in multi-tenant flows. Uses global AsyncLocalStorage state in Node, so regressions would show up as mis-scoped settings across concurrent requests if misused.

Overview
Introduces a new request-scoped RequestContext API (runWithRequestContext, getRequestContext, and a pluggable IRequestContextManager) to propagate per-entity settings through async execution.

Adds a Node.js implementation backed by AsyncLocalStorage and initializes it from index.node.ts, while exporting the new utilities from both index.ts and index.node.ts.

Updates AgentRuntime.getSetting() to check requestCtx.entitySettings first (treating undefined as fallthrough and null as an explicit return) and return entity values without decryptSecret, with new unit/integration tests covering async propagation, concurrency isolation, and precedence over character settings/secrets.

Written by Cursor Bugbot for commit a0e2d2d. This will update automatically on new commits. Configure here.

Greptile Overview

Greptile Summary

This PR adds RequestContext infrastructure to enable per-entity settings in multi-tenant deployments, allowing multiple users to share a single agent runtime while maintaining isolated settings (API keys, OAuth tokens, etc.).

Key Changes:

  • New RequestContext interface and runWithRequestContext() API for propagating per-request entity settings
  • AsyncLocalStorage-based implementation for Node.js (request-context.node.ts) ensuring proper async context isolation
  • Modified runtime.getSetting() to check request context first before falling back to character settings
  • Comprehensive test coverage (28 tests) covering context isolation, concurrency, priority, and integration with runtime

Design:

  • Follows OpenTelemetry ContextManager pattern (consistent with existing streaming-context.ts)
  • NoopContextManager fallback ensures backward compatibility
  • Entity settings are pre-decrypted, avoiding duplicate decryption
  • Clear priority chain: entity settings → character settings → null

Testing:

  • Unit tests verify context isolation across 10 concurrent requests
  • Integration tests confirm proper getSetting() behavior and priority
  • Edge cases covered: null vs undefined, nested contexts, error propagation

Issue Found:

  • package.json version changed to local development version (1.0.0-local.1768325621) - must be reverted before merge

Confidence Score: 4/5

  • Safe to merge after reverting package.json version change
  • High-quality implementation with excellent test coverage and clear design patterns. The only issue is the unintentional version change in package.json which must be fixed. Code follows project conventions, includes comprehensive documentation, and all new tests pass.
  • packages/core/package.json needs version reverted to 1.7.2-alpha.1

Important Files Changed

Filename Overview
packages/core/package.json Version changed to local development version (1.0.0-local.1768325621), should be reverted before merge
packages/core/src/request-context.ts Well-designed context management pattern following OpenTelemetry style, with comprehensive documentation and type safety
packages/core/src/runtime.ts Added request context check to getSetting() with proper fallback chain and clear comments

Sequence Diagram

sequenceDiagram
    participant User as User/Entity
    participant Server as Server/Handler
    participant RC as RequestContext
    participant ALS as AsyncLocalStorage
    participant Runtime as AgentRuntime
    participant DB as Database

    User->>Server: Send message/request
    Note over Server: Fetch entity settings
    Server->>DB: Query entity settings for userId
    DB-->>Server: Return settings Map
    
    Server->>RC: runWithRequestContext(context, fn)
    Note over RC: context = {entityId, agentId, entitySettings}
    RC->>ALS: storage.run(context, fn)
    Note over ALS: Store context in AsyncLocalStorage
    
    ALS->>Runtime: Execute fn() → runtime.handleMessage()
    Runtime->>Runtime: getSetting(key)
    Runtime->>RC: getRequestContext()
    RC->>ALS: storage.getStore()
    ALS-->>RC: Return active context
    RC-->>Runtime: Return context
    
    alt Entity setting exists
        Runtime-->>Runtime: Return entitySettings.get(key)
        Note over Runtime: Pre-decrypted, return as-is
    else Fallback to character settings
        Runtime-->>Runtime: Check character.settings/secrets
        Note over Runtime: Apply decryption if needed
    end
    
    Runtime-->>Server: Complete message processing
    Server-->>User: Send response
    
    Note over ALS: Context automatically cleared after fn() completes

Loading

0xbbjoker and others added 2 commits February 3, 2026 15:18
Implements AsyncLocalStorage-based request context that allows:
- Per-request entity settings that override agent settings
- getSetting() now checks request context first
- runWithRequestContext() and getRequestContext() APIs

This enables multi-tenant runtime sharing where each user's
settings (API keys, OAuth tokens) are isolated per-request.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 3, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/entity-settings-context

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


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.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Feb 3, 2026

Claude finished @0xbbjoker's task in 1m 23s —— View job


Reviewing PR #6457: feat(core): add request context for per-user entity settings

  • Gather context and read changed files
  • Check for security issues
  • Verify test coverage
  • Validate TypeScript types
  • Check for tool/framework compliance
  • Review code patterns and architecture
  • Provide review feedback

✅ APPROVED

This is a well-implemented feature that adds request context for per-user entity settings using AsyncLocalStorage. The implementation is clean, follows existing patterns (similar to streaming-context.ts), and has comprehensive test coverage.

Summary

Category Status
Security ✅ No hardcoded keys, no injection risks
Tests ✅ 771 lines of tests using bun:test
TypeScript ✅ Proper types, no any
Framework ✅ Uses bun only
Patterns ✅ Follows existing architecture

What's Good

  1. Clean Architecture: Follows the OpenTelemetry ContextManager pattern, consistent with existing streaming-context.ts
  2. Proper Async Isolation: Uses Node.js AsyncLocalStorage for correct context propagation across async operations
  3. Backward Compatible: NoopContextManager ensures graceful fallback when context is not set
  4. Comprehensive Tests:
    • request-context.test.ts (324 lines) - Tests context propagation, isolation, edge cases
    • runtime-request-context.test.ts (447 lines) - Tests getSetting() integration, priority, multi-tenant isolation
  5. Security: Entity settings bypass decryptSecret since they're pre-decrypted during prefetch (correctly handled in tests)
  6. Clear Documentation: Well-documented interfaces with usage examples

Minor Suggestions

💡 SUGGESTION: Consider adding a browser implementation stub → packages/core/src/request-context.browser.ts similar to streaming-context.browser.ts for consistency. The NoopContextManager works, but an explicit browser file documents the intent.

💡 SUGGESTION: The EntitySettingValue type allows null for explicit unset. Consider documenting this behavior in the runtime JSDoc for getSetting():

// In runtime.ts getSetting():
// - undefined in entitySettings map = fall through to agent settings
// - null in entitySettings map = explicitly unset, return null

Code Quality Notes

  • No any types used ✅
  • Proper use of workspace:* for internal dependencies ✅
  • Uses bun:test exclusively ✅
  • No npm/pnpm/jest/vitest usage ✅
  • Clean separation between interface (request-context.ts) and Node implementation (request-context.node.ts)

The implementation correctly prioritizes entity settings > character settings > character secrets > environment, which aligns with the multi-tenant use case described in the PR.

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread packages/core/package.json
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Feb 3, 2026

Claude finished @0xbbjoker's task in 55s —— View job


Reviewing PR #6457: feat(core): add request context for per-user entity settings

  • Gather context and read changed files
  • Check for security issues
  • Verify test coverage
  • Validate TypeScript types
  • Check for tool/framework compliance
  • Review code patterns and architecture
  • Provide review feedback

✅ APPROVED

This is a well-designed feature that adds request context for per-entity settings using AsyncLocalStorage, enabling multi-tenant use of a shared agent runtime.

Summary

Category Status
Security ✅ No hardcoded keys, no injection risks, entity settings pre-decrypted
Tests ✅ 771 lines of tests using bun:test (28+ test cases)
TypeScript ✅ Proper types, no any, well-defined interfaces
Framework ✅ Uses bun only, workspace:* for internal deps
Patterns ✅ Follows existing OpenTelemetry ContextManager pattern

What's Good

  1. Clean Architecture: Follows the existing streaming-context.ts pattern with IRequestContextManager interface and platform-specific implementations
  2. Proper Async Isolation: Uses Node.js AsyncLocalStorage for correct context propagation across concurrent async operations
  3. Backward Compatible: NoopContextManager ensures graceful fallback when context is not set
  4. Comprehensive Tests:
    • request-context.test.ts - Tests context propagation, isolation, nesting, concurrency (10 parallel requests)
    • runtime-request-context.test.ts - Tests getSetting() integration, priority chain, decryption bypass
  5. Correct Priority: Entity settings → character settings → character secrets → null
  6. Well Documented: Comprehensive JSDoc with usage examples

Implementation Details

  • packages/core/src/request-context.ts:667-681 - getSetting() correctly checks entity settings first with proper undefined vs null handling
  • Entity settings bypass decryptSecret() since they're pre-decrypted during prefetch (verified by tests at runtime-request-context.test.ts:150-175)
  • NoopContextManager ensures existing code without context continues to work

Verified

  • ✅ No any types
  • ✅ Uses bun:test exclusively
  • ✅ No npm/pnpm/jest/vitest
  • ✅ Package version is correct (1.7.3-alpha.1)
  • ✅ No breaking changes - purely additive
  • ✅ Follows existing patterns from streaming-context.ts

Minor Suggestions

💡 SUGGESTION: Consider adding a browser implementation stub (request-context.browser.ts) similar to streaming-context.browser.ts for explicit documentation of browser behavior → Currently relies on NoopContextManager fallback which works, but explicit file documents intent.

💡 SUGGESTION: Consider documenting the null vs undefined behavior inline in runtime.ts:getSetting() → The comment is good but could be more explicit about null being an explicit unset.


Note: Previous review comment mentioned package.json version change to 1.0.0-local.1768325621 - this appears to have been fixed. Current version is 1.7.3-alpha.1 which is correct.

@0xbbjoker 0xbbjoker merged commit 5d0f2b6 into develop Feb 4, 2026
17 of 19 checks passed
@0xbbjoker 0xbbjoker deleted the feat/entity-settings-context branch February 4, 2026 12:50
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