Great question! You’re building a dynamic persona system - here’s how to approach it.
The Concept
Questionnaire Flow:
User answers questions → Agent stores in persona block → Agent references persona in responses
The agent “learns” about the user by always checking its persona block.
Step 1: Structure Your Questionnaire
Ask questions in a logical order:
# Example questionnaire
QUESTIONS = [
"What programming languages do you know?",
"Do you prefer concise or detailed explanations?",
"What's your experience level (beginner, intermediate, advanced)?",
"What kind of projects do you work on (web, mobile, data)?",
"Do you like code examples or text-only explanations?",
"What's your timezone?",
"Any specific topics you want to focus on (React, Python, algorithms, databases)?"
]
Step 2: Create a Persona Block
from letta_client import Letta
client = Letta(base_url="http://localhost:8283")
# Create agent
agent = client.agents.create(
name="personal-assistant",
model="anthropic/claude-sonnet-4-5-20250514",
embedding="openai/text-embedding-3-small",
)
# Create persona block
persona_block = client.blocks.create(
label="user_persona",
value="User profile not yet established. Ask questions to learn about user."
)
Attach to agent:
client.agents.blocks.attach(agent.id, block_id=persona_block.id)
Step 3: Update Persona Programmatically
After user answers questions:
def update_user_persona(agent_id, responses):
"""Update persona based on questionnaire responses."""
persona_text = "User Profile:\n"
for question, answer in responses.items():
persona_text += f"- {question}: {answer}\n"
# Update the block
client.blocks.update(
block_label="user_persona",
value=persona_text
)
return f"Updated persona based on {len(responses)} answers"
Step 4: Make Agent Reference Persona
In agent’s system prompt or instructions:
system_prompt = """
You are a personalized coding assistant. Your responses should be tailored to the user's preferences.
## User Persona
Always check the 'user_persona' memory block before responding.
Adapt your tone, depth, and examples based on what's stored there.
## Example:
If user_persona says:
- Languages: Python, JavaScript
- Level: Beginner
- Style: Code examples preferred
Then provide code snippets in Python. If it says:
- Languages: Go, Rust
- Level: Advanced
- Style: Text-only explanations
Then explain concepts clearly without code.
"""
Step 5: Implement the Questionnaire Flow
Your application code:
from letta_client import Letta
client = Letta(api_key="YOUR_KEY")
# Step 1: Present questionnaire
def present_questionnaire(user_id):
questions = [
"What programming languages do you know?",
"Do you prefer concise or detailed explanations?",
"What's your experience level?",
"What kind of projects do you work on?",
"Do you like code examples or text-only explanations?",
"What's your timezone?",
"Any specific topics to focus on?",
]
# Send to agent
response = client.agents.messages.create(
agent_id=user_id,
messages=[{
"role": "user",
"content": f"I need to learn about you to personalize my assistance. Please answer these questions:\n\n" + "\n".join(questions)
}]
)
return response
# Step 2: Collect answers
def collect_answers(user_id, conversation_id):
"""Wait for user to answer all questions."""
# In a real app, you'd collect these responses via UI
# For now, let's simulate getting answers
# Simulated answers
answers = [
{"question": "What programming languages do you know?", "answer": "Python, JavaScript"},
{"question": "Do you prefer concise or detailed explanations?", "answer": "Detailed with code examples"},
{"question": "What's your experience level?", "answer": "Intermediate"},
{"question": "What kind of projects do you work on?", "answer": "Web and mobile apps"},
{"question": "Do you like code examples or text-only explanations?", "answer": "Code examples preferred"},
{"question": "What's your timezone?", "answer": "UTC-5"},
{"question": "Any specific topics to focus on?", "answer": "React and Python"},
]
# Update persona
update_user_persona(user_id, answers)
return "Persona updated! I'll tailor my responses accordingly."
# Step 3: Use the persona
def chat_with_user(user_id, user_message):
"""Chat with user, referencing their persona."""
# Get current persona
agent = client.agents.retrieve(user_id)
persona_block = [b for b in agent.blocks if b.label == "user_persona"][0]
# Include persona in context
context = f"""
## User Persona
{persona_block.value}
## Current Task
{user_message}
## Instructions
Based on the user's persona above, provide a helpful response.
"""
# Send message with persona context
response = client.agents.messages.create(
agent_id=user_id,
messages=[{"role": "user", "content": user_message}]
)
return response.choices[0].message.content
Full Workflow Example
# Initial setup
agent = client.agents.create(...)
client.agents.blocks.attach(agent.id, block_id=persona_block.id)
# Onboarding flow
def onboarding_flow(user_id):
# Step 1: Present questions
present_questionnaire(user_id)
# Step 2: Collect answers (from UI or simulated)
answers = collect_answers(user_id)
# Step 3: Update persona
update_user_persona(user_id, answers)
# Step 4: Confirm ready
return "Setup complete! I'm ready to assist you based on your preferences."
# Chat with personalized responses
def personalized_chat(user_id, user_message):
# Get agent and persona
agent = client.agents.retrieve(user_id)
persona_block = [b for b in agent.blocks if b.label == "user_persona"][0]
# Context with persona
context = f"User Persona: {persona_block.value}\n\nYour message: {user_message}"
response = client.agents.messages.create(
agent_id=user_id,
messages=[{"role": "user", "content": context}]
)
return response.choices[0].message.content
# Example usage
user_id = "agent-123"
# Onboarding
print(onboarding_flow(user_id))
# Output: "I need to learn about you to personalize my assistance. Please answer these questions..."
# User answers (simulated)
answers = [...]
print(update_user_persona(user_id, answers))
# Output: "Persona updated! I'll tailor my responses accordingly."
# Now chat
print(personalized_chat(user_id, "Explain how to implement a binary search tree in Python"))
# Output: Uses persona to provide Python code examples for intermediate user
Key Best Practices
1. Start Simple
- Don’t ask too many questions initially (5-7 is good)
- Focus on high-impact preferences first (experience level, coding style)
2. Update Incrementally
- You don’t need all answers at once
- Update persona as you learn more about the user
3. Make Persona Clear and Structured
# Good structure
value = """
## Coding Style
- Language: Python, JavaScript
- Level: Intermediate
- Preferences: Detailed explanations with code examples
## Communication
- Tone: Friendly and patient
- Format: Clear explanations with examples
- Focus: Practical, working code
## Topics of Interest
- React, Python web development
- Algorithms and data structures
- Database design (PostgreSQL preferred)
## Constraints
- Timezone: UTC-5
- Availability: Weekdays 9am-5pm UTC
"""
4. Validate User Input
- Handle incomplete or invalid answers gracefully
- Ask follow-up questions if needed
5. Test Thoroughly
- Simulate different user personas
- Verify agent adapts its responses correctly
- Check that persona is being used consistently
Quick Start Template
If you want a working example right now, here’s a minimal version:
from letta_client import Letta
client = Letta(api_key="YOUR_KEY")
# Create simple agent
agent = client.agents.create(
name="coding-assistant",
model="anthropic/claude-haiku-4-5-20250514",
memory_blocks=[
{
"label": "user_persona",
"value": "User is a Python beginner. Provide clear explanations with simple code examples."
}
]
)
# Test it
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "Write a Python function to reverse a string."}]
)
print(response.choices[0].message.content)
# Should output Python code for a beginner
Summary
The pattern:
- Questionnaire → User answers → Update persona block
- Agent responses → Always check persona block → Tailor output
- Iterate → Update persona as you learn more
This gives you:
- Dynamic personalization without recreating agents
- Agents that “remember” user preferences across sessions
- Easy to extend (add more questions over time)
Want me to elaborate on any part of this? The questionnaire structure, persona updates, or how to make the agent reference it effectively?