Addresses @kartik-mem0's review on mem0#7340, verified against the live
staging profiles API on a neuron:
- generate_profile / sample_profiles accept a caller-supplied idempotency_key,
so retrying a lost request reuses the job instead of creating a second
billable one (Python sync+async and TS)
- TS uses the uuid dependency instead of the global crypto.randomUUID(), which
throws on the supported Node 18 target
- update_profile_settings distinguishes an omitted argument from an explicit
None, so schema / custom_instructions can be cleared (Python sentinel)
- export ProfileJobResponse and ProfileJobStatus; drop the deprecated
ProfileTriggerResponse / ProfileSamplesResponse aliases and the unpopulated
results field; correct usageUnits -> entityCountReserved; add error to
ProfileResponse
- openapi: nest schema / custom_instructions under entities in the settings
request and response, add capabilities, and mark entity_type required on the
job body
- docs sample example polls to a terminal job status with a timeout, then reads
the create response's entity_ids (status.results raised KeyError)
- notebook: include PARTIALLY_SUCCEEDED in terminal states, raise on timeout,
and snapshot/restore project settings so a shared env is left as found
- tests: real job_id create shape, idempotency-key reuse, and clear-with-None
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove leftover agent and regenerate references so the docs match the shipped
v1 SDK: drop the entity_type settings argument and the agent entities example
from the guide, and remove the regenerate demo section and cheat-sheet row from
the notebook.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Four bugs that made the profile SDK unusable against the live API, each
found by running the demo notebook end to end rather than by reading.
1. `update_profile_settings()` sent a flat body:
{"enabled": ..., "schema": ..., "custom_instructions": ...}
The API takes only `enabled` and `entities` at the top level and
answers 400 "Unsupported settings: custom_instructions, schema." to
anything else, so every call passing a schema failed.
`get_profile_settings()` already returned the nested shape, so the read
and the write disagreed and the method could not round-trip its own
settings. Both SDKs now nest `schema` and `custom_instructions` under
`entities.<entity_type>` while keeping the flat call signature;
`entity_type` is a new optional argument defaulting to "user".
2. `sample_profiles()` and `regenerate_profiles()` never sent
`entity_type`. Every profile job must name an entity kind, so both
failed with "entity_type must be one of: user, agent."
3. The TypeScript read path rewrote the customer's schema property names.
Once the schema moved under `entities`, `snakeToCamelKeys` camel-cased
the keys inside it, because only a top-level schema was restored
verbatim. A field named `favorite_topics` came back as `favoriteTopics`.
4. `ProfileStatus` declared `notEnabled` and `insufficientData`, but a
status is a value, not a key, so it is never camel-cased. tsc rejected
`status === "insufficient_data"`, which is true at runtime, and accepted
`status === "insufficientData"`, which can never fire. Branching on
status is the documented way to use a profile, so the type steered
every TypeScript caller into a dead branch.
Response-shape corrections found alongside them: sample returns
`entity_ids` on create and a richer `results` array on the job, so the TS
`results` field on the create response is marked deprecated and never set;
regenerate answers 409, not the 501 the docstrings claimed.
Verified against a live environment, from both SDKs: a settings write
followed by a read returns the schema property for property, a partial
update no longer blanks it, sample returns 202 with the entities it
picked, regenerate reaches the server and answers its real
not_yet_available, and a user with no profile returns "insufficient_data".
Adds a user-profiles demo notebook covering the whole loop: schema,
ingestion, generation, a before/after diff of a profile rewriting itself,
schema sampling, and a failure-scenario section for each way the API says
no. It polls the add event to a terminal status instead of sleeping, waits
for the extracted memory count to settle rather than trusting the first
page, and reports plainly when generation cannot finish instead of
presenting an empty profile as a result. Executed end to end: 0 failing
cells.
- python: 20 passed (tests/test_client_profiles.py)
- typescript: 203 passed (src/client/tests/)