User Profile
Structured facts about users.
The User Profile Store captures structured fields about users: name, preferred name, and custom fields you define.
| Aspect | Value |
|---|---|
| Scope | Per user |
| Persistence | Forever (updated as new info is learned) |
| Default mode | Always |
| Supported modes | Always, Agentic |
Setup
pip install agno openai sqlalchemy "psycopg[binary]" pgvector
export OPENAI_API_KEY="your-api-key"The examples use a local PostgreSQL database on port 5532. With Docker running, start it using:
Run PgVector
docker run -d \
-e POSTGRES_DB=ai \
-e POSTGRES_USER=ai \
-e POSTGRES_PASSWORD=ai \
-e PGDATA=/var/lib/postgresql \
-v pgvolume:/var/lib/postgresql \
-p 5532:5432 \
--name pgvector \
agnohq/pgvector:18Later configuration fragments reuse the imports and db from the first complete example.
Basic Usage
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.learn import LearningMachine
from agno.models.openai import OpenAIResponses
db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai")
agent = Agent(
model=OpenAIResponses(id="gpt-5.2"),
db=db,
learning=LearningMachine(user_profile=True),
)
# Session 1: Share information
agent.print_response(
"Hi! I'm Alice Chen, but please call me Ali.",
user_id="alice@example.com",
session_id="session_1",
)
# Session 2: Profile is recalled automatically
agent.print_response(
"What's my name?",
user_id="alice@example.com",
session_id="session_2",
)Always Mode
Extraction starts concurrently with the main model call using the current input snapshot. No tools are visible to the agent.
from agno.learn import LearningMachine, LearningMode, UserProfileConfig
agent = Agent(
model=OpenAIResponses(id="gpt-5.2"),
db=db,
learning=LearningMachine(
user_profile=UserProfileConfig(mode=LearningMode.ALWAYS),
),
)The tradeoff is an extra LLM call per interaction.
Agentic Mode
The agent receives an update_profile tool and decides when to update.
from agno.learn import LearningMachine, LearningMode, UserProfileConfig
agent = Agent(
model=OpenAIResponses(id="gpt-5.2"),
db=db,
learning=LearningMachine(
user_profile=UserProfileConfig(mode=LearningMode.AGENTIC),
),
)
agent.print_response(
"Please remember that my name is Bob Smith.",
user_id="bob@example.com",
)The tradeoff is that the agent may miss implicit profile info.
Default Fields
| Field | Description |
|---|---|
name | Full name |
preferred_name | Name they prefer to be called |
Custom Schemas
Extend the base schema for your domain:
from dataclasses import dataclass, field
from typing import Optional
from agno.learn.schemas import UserProfile
@dataclass
class CustomerProfile(UserProfile):
company: Optional[str] = field(
default=None,
metadata={"description": "Company or organization"}
)
plan_tier: Optional[str] = field(
default=None,
metadata={"description": "Subscription tier: free | pro | enterprise"}
)
role: Optional[str] = field(
default=None,
metadata={"description": "Job title or role"}
)
timezone: Optional[str] = field(
default=None,
metadata={"description": "User's timezone"}
)
agent = Agent(
model=OpenAIResponses(id="gpt-5.2"),
db=db,
learning=LearningMachine(
user_profile=UserProfileConfig(schema=CustomerProfile),
),
)The metadata["description"] tells the LLM what each field captures.
Accessing Profile Data
lm = agent.learning_machine
# Get profile
profile = lm.user_profile_store.get(user_id="alice@example.com")
if profile is not None:
print(profile.name)
print(profile.preferred_name)
# Debug output
lm.user_profile_store.print(user_id="alice@example.com")Context Injection
Profiles are automatically injected into the system prompt:
<user_profile>
Name: Alice Chen
Preferred Name: Ali
Company: Acme Corp
Role: Data Scientist
</user_profile>No manual context building is needed.
User Profile vs User Memory
| User Profile | User Memory |
|---|---|
| Structured fields | Unstructured text |
| Fixed schema | Flexible observations |
| Updated in place | Appended over time |
| Keyed recall by user ID | Keyed recall of the user's memory entries |
Use User Profile for: name, company, role, preferences with defined values.
Use User Memory for: observations like "prefers detailed explanations" or "works on ML projects."