User & Conversations
Persist conversation history and enable personalized experiences
The user prop enables conversation persistence, personalization, and multi-device sync. Just pass in a user object with a unique id property.
User Object
Provide a user object to enable authenticated features.
<ArctenAgent
user={{
id: "user_123", // Required
email: "user@example.com",
name: "John Doe",
// Add any custom fields
}}
/>Required Fields
id (string, required): Unique identifier for the user. This is the only required field when providing a user object.
// Minimum required
<ArctenAgent
user={{ id: "user_123" }}
/>Optional Fields
You can include any additional fields that are relevant to your application:
<ArctenAgent
user={{
id: "user_123",
email: "john@example.com",
name: "John Doe",
plan: "premium",
role: "admin",
company: "Acme Corp",
metadata: {
signupDate: "2024-01-15",
lastLogin: "2024-03-20"
}
}}
/>Benefits of User Authentication
1. Conversation Persistence
Conversations are automatically saved and associated with the user.
export default function App() {
const user = {
id: "user_123",
email: "user@example.com"
};
return (
<ArctenAgent
user={user}
systemPrompt="You are a helpful assistant."
/>
);
}Users can:
- Resume conversations across sessions
- View conversation history
- Search through past conversations
- Switch between different conversation threads
2. Personalized Responses
The agent can access user context for tailored responses.
const user = {
id: "user_456",
name: "Sarah",
plan: "enterprise",
industry: "healthcare"
};
<ArctenAgent
user={user}
systemPrompt={`You are assisting ${user.name}, an ${user.plan} customer in the ${user.industry} industry. Provide relevant examples and recommendations based on their context.`}
/>3. Multi-Device Sync
Conversations sync automatically across all devices where the user is logged in.
4. User Context in Tools
Tools can access user information for personalized actions.
function getRecommendations(userId: string) {
// Use userId to fetch personalized recommendations
const userPrefs = database.getUserPreferences(userId);
return recommendations.generate(userPrefs);
}
<ArctenAgent
user={{ id: "user_789" }}
safeTools={[getRecommendations]}
/>Conversation Management
Recent Conversations
When a user object is provided, the agent automatically displays recent conversations in the sidebar.
<ArctenAgent
user={{ id: "user_123" }}
// Recent conversations appear automatically
/>Users can:
- View recent conversation titles
- Click to load a previous conversation
- Delete old conversations
- Start new conversations
New Conversations
Users can start a new conversation at any time using the "+" button in the agent header.
Conversation Context
Each conversation maintains its own context and history, allowing users to:
- Keep separate topics organized
- Return to specific discussions
- Maintain context within each conversation thread
Anonymous Users
If you don't provide a user object, the agent works in anonymous mode:
// Anonymous mode - no user object
<ArctenAgent
systemPrompt="You are a helpful assistant."
/>Anonymous mode behavior:
- No persistent conversation history
- No cross-device sync
Use anonymous mode when:
- Users are not logged in
- You don't need conversation persistence
- Privacy is a primary concern
- You're building a public-facing tool (unauthenticated page)
Integration Examples
With Next.js Auth
import { useSession } from "next-auth/react";
import { ArctenAgent } from "@arcteninc/core";
import "@arcteninc/core/styles";
export default function AuthenticatedApp() {
const { data: session } = useSession();
if (!session) {
return <div>Please log in</div>;
}
const user = {
id: session.user.id,
email: session.user.email,
name: session.user.name,
};
return (
<div className="flex h-screen">
<div className="flex-1 overflow-scroll">
{/* Your app */}
</div>
<ArctenAgent
user={user}
systemPrompt="You are a helpful assistant."
/>
</div>
);
}With Clerk
import { useUser } from "@clerk/nextjs";
import { ArctenAgent } from "@arcteninc/core";
import "@arcteninc/core/styles";
export default function App() {
const { user: clerkUser } = useUser();
if (!clerkUser) {
return <div>Loading...</div>;
}
const user = {
id: clerkUser.id,
email: clerkUser.primaryEmailAddress?.emailAddress,
name: clerkUser.fullName,
};
return (
<ArctenAgent
user={user}
systemPrompt="You are a helpful assistant."
/>
);
}With Supabase Auth
import { useSupabaseClient, useUser } from "@supabase/auth-helpers-react";
import { ArctenAgent } from "@arcteninc/core";
import "@arcteninc/core/styles";
export default function App() {
const supabaseUser = useUser();
if (!supabaseUser) {
return <div>Not authenticated</div>;
}
const user = {
id: supabaseUser.id,
email: supabaseUser.email,
};
return (
<ArctenAgent
user={user}
systemPrompt="You are a helpful assistant."
/>
);
}With Firebase Auth
import { useAuth } from "@/hooks/useAuth";
import { ArctenAgent } from "@arcteninc/core";
import "@arcteninc/core/styles";
export default function App() {
const { user: firebaseUser } = useAuth();
if (!firebaseUser) {
return <div>Please sign in</div>;
}
const user = {
id: firebaseUser.uid,
email: firebaseUser.email,
name: firebaseUser.displayName,
};
return (
<ArctenAgent
user={user}
systemPrompt="You are a helpful assistant."
/>
);
}Security Best Practices
Validate User Identity
In your token endpoint, verify that the requesting user matches the authenticated session:
import { verifyToken } from "@arcteninc/core/server";
import { getServerSession } from "next-auth";
export async function POST(req: NextRequest) {
const body = await req.json();
const { user } = body;
// Get authenticated session
const session = await getServerSession();
// Verify the user matches the session
if (!session || session.user.id !== user.id) {
return NextResponse.json(
{ error: "Unauthorized" },
{ status: 401 }
);
}
// Generate token
const tokenResponse = await verifyToken({
apiKey: process.env.ARCTEN_API_KEY!,
user,
});
return NextResponse.json(tokenResponse);
}Don't Trust Client Data
Never trust user data from the client without verification:
// ❌ Bad - trusting client data
const { user } = req.body;
const tokenResponse = await verifyToken({
apiKey: process.env.ARCTEN_API_KEY!,
user, // Unverified!
});
// ✅ Good - verify against session
const session = await getServerSession();
if (!session) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const user = {
id: session.user.id, // Verified from session
email: session.user.email,
};
const tokenResponse = await verifyToken({
apiKey: process.env.ARCTEN_API_KEY!,
user,
});Protect User Privacy
Only include necessary user information:
// ❌ Oversharing
const user = {
id: "user_123",
email: "user@example.com",
password: "...", // Never include sensitive data!
creditCard: "...", // Never include sensitive data!
ssn: "...", // Never include sensitive data!
};
// ✅ Appropriate
const user = {
id: "user_123",
email: "user@example.com",
name: "John Doe",
plan: "premium",
};Conversation Data Access
Conversation data is:
- Encrypted at rest
- Accessible only by the authenticated user
- Stored securely on Arcten servers
- Subject to your data retention policies
GDPR & Data Deletion
To delete a user's conversation data, contact Arcten support or use the API (coming soon).
Tips
- Always provide user.id: This is the only required field for authenticated mode
- Include relevant context: Add custom fields that help personalize the experience
- Validate authentication: Always verify user identity in your token endpoint
- Don't overshare: Only include non-sensitive user information
- Consider privacy: Use anonymous mode for public-facing tools
- Test multi-device sync: Verify conversations sync correctly across devices