/learnings REST endpoints for CRUD over the agno_learnings table, the table that backs every learning store (user_profile, user_memory, session_context, entity_memory, decision_log). Enable learning on an agent and serve it with AgentOS, and the endpoints are available automatically.
Prerequisites
- A supported database: PostgreSQL, SQLite, or MongoDB. Other databases return
501. - An agent with learning enabled (see the Learning quickstart).
Example
learnings_with_agentos.py
http://localhost:7777/docs.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /learnings | Paginated list with filters and sorting |
POST | /learnings | Create a record |
GET | /learnings/users | List users that own learnings, with last-activity timestamps |
DELETE | /learnings/users/{user_id} | Delete all of a user’s learnings (or one type) |
GET | /learnings/{learning_id} | Fetch a single record |
PATCH | /learnings/{learning_id} | Update content and/or metadata |
DELETE | /learnings/{learning_id} | Delete a record |
db_id and table query parameters to target a specific database or table. table requires db_id.
Listing and filtering
GET /learnings returns a paginated envelope: data holds the records and meta holds the pagination info (page, limit, total_pages, total_count).
| Parameter | Description |
|---|---|
learning_type | Filter by store (user_profile, user_memory, etc.) |
user_id, agent_id, team_id, session_id | Filter by owner |
namespace, entity_id, entity_type | Filter by scope or entity |
limit | Page size (1–1000, default 100) |
page | 1-indexed page number |
sort_by | created_at or updated_at (default). Unknown fields are ignored |
sort_order | asc or desc (default) |
GET /learnings/users, then drill into one with GET /learnings?user_id=....
Creating records
POST computes the same ID for the identity-keyed types, so a record created through the API reconciles with what the agent reads and writes. No orphan, no duplicate.
learning_type | Derived ID | Required identity fields |
|---|---|---|
user_profile | user_profile_{user_id} | user_id |
user_memory | memories_{user_id} | user_id |
session_context | session_context_{session_id} | session_id |
entity_memory | entity_{namespace}_{entity_type}_{entity_id} | namespace, entity_type, entity_id |
- Provide the required identity field(s), or the request returns
422. - Include the same identity fields inside
contentso the agent’s store can deserialize the record. - An existing record for that identity returns
409. UsePATCHto update it. - Other types (for example,
decision_log) get a generated ID, so a user can have many.
Updating records
PATCH replaces content and/or metadata. Identity fields are immutable.
Deleting records
204, and never touch records with no owner.
Authorization and isolation
Scoping follows the framework’s opt-in user isolation contract (AuthorizationConfig(user_isolation=True)). Admins, requests with isolation disabled, and requests without a JWT are unscoped and have full access. For a scoped (non-admin) caller:
| Operation | Behavior |
|---|---|
| List / list users | Bound to the caller. List also includes records with no owner (user_id IS NULL). A different user_id returns 403 |
| Create | Body user_id must be omitted/null or match the caller, otherwise 403 |
| Delete user | Only the caller’s own learnings; a different user_id returns 403 |
| Get single record | A cross-user record returns 404 (no existence leak) |
| Patch / delete single record | Cross-user returns 404. Shared records (user_id IS NULL) are readable but admin-only to mutate, so a regular user gets 403 |
learnings:read, learnings:write, or learnings:delete scopes.