feat(platform): user context template variables for agent prompts#835
Conversation
…ate variables
Add user environment context (timezone, language, coordinates, location) from
the browser to the agent system prompt template resolution. Introduces
{{user.timezone}}, {{user.language}}, {{user.coordinates}}, {{user.location}},
and {{user_instruction}} template variables. The user_instruction variable
generates a complete user context block including name, email, role, org,
timezone, language, location, and current time.
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
📝 WalkthroughWalkthroughThis PR adds user context collection and propagation throughout the chat system. A new Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@services/platform/app/features/chat/hooks/use-user-context.ts`:
- Around line 74-115: Add a short comment near the useEffect/getCurrentPosition
block noting that coordinates are included in prompts sent to the LLM, then
reduce precision before storing/sending by rounding latitude/longitude (e.g., to
2 decimal places) prior to building coords, calling setLocation, and persisting
to localStorage (references: useEffect, navigator.geolocation.getCurrentPosition
callback, setLocation, LOCATION_CACHE_KEY, getCachedLocation, isNearby); ensure
isNearby still compares with the same rounded precision or adjust it accordingly
so cached proximity checks remain consistent.
- Around line 90-92: The fetch call in use-user-context.ts that calls Nominatim
(`fetch(`https://nominatim.openstreetmap.org/reverse?...`)`) lacks required
headers; update the request in the function where reverse geocoding is performed
to include a proper User-Agent (or Referer) header (ideally including your app
name and contact/email) by passing a second argument to fetch with a headers
object (e.g., headers: { 'User-Agent': 'MyApp/1.0 (contact@example.com)' } ) so
the Nominatim API compliance requirement is met and requests aren't blocked or
rate-limited.
In `@services/platform/convex/lib/agent_response/resolve_template_variables.ts`:
- Line 192: The assignment userRole: memberRole ?? undefined is redundant
because memberRole is already typed string | undefined; update the object in
resolve_template_variables (the location setting userRole) to directly use
userRole: memberRole (remove the `?? undefined`), ensuring no behavior change
and simplifying the code.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 91db8128-ba74-4a69-a674-9c3a227a8c02
📒 Files selected for processing (9)
services/platform/app/features/chat/components/chat-interface.tsxservices/platform/app/features/chat/hooks/use-send-message.tsservices/platform/app/features/chat/hooks/use-user-context.tsservices/platform/convex/custom_agents/unified_chat.tsservices/platform/convex/lib/agent_chat/internal_actions.tsservices/platform/convex/lib/agent_chat/start_agent_chat.tsservices/platform/convex/lib/agent_response/generate_response.tsservices/platform/convex/lib/agent_response/resolve_template_variables.tsservices/platform/convex/lib/agent_response/types.ts
| useEffect(() => { | ||
| if (!navigator.geolocation) return; | ||
|
|
||
| navigator.geolocation.getCurrentPosition( | ||
| async (pos) => { | ||
| const { latitude: lat, longitude: lng } = pos.coords; | ||
| const coords = `${lat}, ${lng}`; | ||
| const cached = getCachedLocation(); | ||
|
|
||
| if (cached && isNearby(lat, lng, cached)) { | ||
| setLocation({ coordinates: coords, address: cached.address }); | ||
| return; | ||
| } | ||
|
|
||
| setLocation({ coordinates: coords }); | ||
| try { | ||
| const res = await fetch( | ||
| `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&zoom=10`, | ||
| ); | ||
| const data = await res.json(); | ||
| const address = | ||
| typeof data.display_name === 'string' | ||
| ? data.display_name | ||
| : undefined; | ||
| const result = { coordinates: coords, address }; | ||
| setLocation(result); | ||
| localStorage.setItem( | ||
| LOCATION_CACHE_KEY, | ||
| JSON.stringify({ lat, lng, ...result }), | ||
| ); | ||
| } catch { | ||
| localStorage.setItem( | ||
| LOCATION_CACHE_KEY, | ||
| JSON.stringify({ lat, lng, coordinates: coords }), | ||
| ); | ||
| } | ||
| }, | ||
| () => { | ||
| // User denied or geolocation unavailable | ||
| }, | ||
| ); | ||
| }, []); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider privacy implications of precise geolocation.
The hook requests high-accuracy geolocation (getCurrentPosition defaults to enableHighAccuracy: false, but still provides precise coordinates) and sends these coordinates to the backend where they're included in LLM prompts. While this enables useful location-aware features, consider:
- Adding a comment documenting that coordinates flow to the LLM
- Using coarser coordinates (e.g., rounding to 2 decimal places ~1km precision) before sending to backend
This is a privacy-by-design consideration rather than a blocking issue.
💡 Optional: Round coordinates for privacy
const { latitude: lat, longitude: lng } = pos.coords;
- const coords = `${lat}, ${lng}`;
+ // Round to ~1km precision for privacy
+ const roundedLat = Math.round(lat * 100) / 100;
+ const roundedLng = Math.round(lng * 100) / 100;
+ const coords = `${roundedLat}, ${roundedLng}`;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/platform/app/features/chat/hooks/use-user-context.ts` around lines
74 - 115, Add a short comment near the useEffect/getCurrentPosition block noting
that coordinates are included in prompts sent to the LLM, then reduce precision
before storing/sending by rounding latitude/longitude (e.g., to 2 decimal
places) prior to building coords, calling setLocation, and persisting to
localStorage (references: useEffect, navigator.geolocation.getCurrentPosition
callback, setLocation, LOCATION_CACHE_KEY, getCachedLocation, isNearby); ensure
isNearby still compares with the same rounded precision or adjust it accordingly
so cached proximity checks remain consistent.
| const res = await fetch( | ||
| `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&zoom=10`, | ||
| ); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
OpenStreetMap Nominatim usage policy User-Agent requirement
💡 Result:
OpenStreetMap’s public Nominatim instance (nominatim.openstreetmap.org) requires that every request include a valid HTTP Referer or a custom User-Agent header that identifies your application—generic/stock User-Agents set by common HTTP libraries are not acceptable (and may lead to blocking). (operations.osmfoundation.org)
This requirement is part of the Nominatim Usage Policy for the public service (it does not automatically apply to Nominatim instances you run yourself or that third parties run). (operations.osmfoundation.org)
Citations:
- 1: https://operations.osmfoundation.org/policies/nominatim/?utm_source=openai
- 2: https://operations.osmfoundation.org/policies/nominatim/?utm_source=openai
Add User-Agent header for Nominatim API compliance.
OpenStreetMap's public Nominatim API requires requests to include a valid Referer or User-Agent header. Without it, requests may be blocked or rate-limited.
Proposed fix
const res = await fetch(
`https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&zoom=10`,
+ {
+ headers: {
+ 'User-Agent': 'TalePlatform/1.0 (https://tale-project.io)',
+ },
+ },
);📝 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.
| const res = await fetch( | |
| `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&zoom=10`, | |
| ); | |
| const res = await fetch( | |
| `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&zoom=10`, | |
| { | |
| headers: { | |
| 'User-Agent': 'TalePlatform/1.0 (https://tale-project.io)', | |
| }, | |
| }, | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/platform/app/features/chat/hooks/use-user-context.ts` around lines
90 - 92, The fetch call in use-user-context.ts that calls Nominatim
(`fetch(`https://nominatim.openstreetmap.org/reverse?...`)`) lacks required
headers; update the request in the function where reverse geocoding is performed
to include a proper User-Agent (or Referer) header (ideally including your app
name and contact/email) by passing a second argument to fetch with a headers
object (e.g., headers: { 'User-Agent': 'MyApp/1.0 (contact@example.com)' } ) so
the Nominatim API compliance requirement is met and requests aren't blocked or
rate-limited.
| organizationName: orgResult?.name, | ||
| userName: userResult?.name, | ||
| userEmail: needsUserEmail ? userResult?.email : undefined, | ||
| userRole: memberRole ?? undefined, |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Minor: Redundant nullish coalescing.
memberRole is already typed as string | undefined, so ?? undefined is a no-op.
Suggested simplification
- userRole: memberRole ?? undefined,
+ userRole: memberRole,📝 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.
| userRole: memberRole ?? undefined, | |
| userRole: memberRole, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/platform/convex/lib/agent_response/resolve_template_variables.ts` at
line 192, The assignment userRole: memberRole ?? undefined is redundant because
memberRole is already typed string | undefined; update the object in
resolve_template_variables (the location setting userRole) to directly use
userRole: memberRole (remove the `?? undefined`), ensuring no behavior change
and simplifying the code.
…rofile to workflow LLM steps
Rename the template variable {{humanInputContext}} → {{userAnswers}} for clarity,
and introduce {{userProfile}} which injects user identity context (name, email,
role, organization) into workflow LLM prompts. Also rename {{user_instruction}} →
{{user_profile}} in the chat template variable system for consistency.
Add build_workflow_user_profile helper that reuses shared fetch/format functions
from resolve_template_variables. Update contract and red-flag-dd workflow configs
to use the new variable names and add optional language input for contract output.
…t to example workflows
Append {{userProfile}} to LLM system prompts across contract-comparison, red-flag-dd, and folder-document-analysis workflows. Add language input parameter to folder-document-analysis for explicit output language control.
Summary
{{user.timezone}},{{user.language}},{{user.coordinates}},{{user.location}}, and{{user_instruction}}{{user_instruction}}variable generates a complete user context block including name, email, role, organization, timezone, language, location, and current timeTest plan
useUserContexthook returns correct browser timezone and languageuseSendMessage→chatWithAgentmutation →startAgentChat→generateAgentResponse{{user.timezone}}, etc.) resolve correctly in agent instructions{{user_instruction}}produces a well-formatted user context blockuserContextis undefined (optional field)fetchMemberRolecorrectly retrieves the user's organization roleSummary by CodeRabbit