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/)
Review feedback from Rudraj on the docs preview.
The sidebar icon made Profiles the only entry in platform/features with
one; every sibling page has no icon, so it read as a rendering accident.
The plan table stated Pro/Enterprise availability, which is not how the
feature is reaching customers: it is enabled per organization on request
while in beta. A table naming tiers invites a self-serve upgrade that
does not turn it on.
Keeps the two conditions that are not about pricing — schema configured
and an entity-scoped memory — and the note that a disabled project reads
back not_enabled rather than erroring.
Hide agent profiles for this release (backend exists but is gated off) and
sync the guide, api-reference, openapi, and llms.txt to the User Profiles
feature head.
Agent removal:
- Drop "users and agents" framing, the entity_type="agent" get_profile
example, and the "profiles for agents" FAQ from the guide.
- Reduce entity_type to user-only in the read path/param/response and the
jobs request body in openapi.json; drop "or agent" from the api-ref and
llms.txt descriptions.
Code sync (verified against the feature head):
- Read example + prose now include generation_count alongside profile,
status, entity_type, entity_id, updated_at.
- Sample flow corrected: sample_profiles returns a job; poll get_profile_job
and read each result's entity, instead of iterating a non-existent
results field on the create response.
- Bulk regenerate is gated off for v1 (FULL_REBUILD_ENABLED=False): remove
it from the guide, openapi operation enum, and the 501 note; keep only
sample and trigger. Idempotency-Key marked required to match the backend.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The ts-sdk CI Lint step (npx prettier --check .) failed on the three
profile client files, which also failed the aggregate CI Gate. Reformat
them with prettier 3.8.4 (the pinned devDependency); whitespace only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Four POST routes became one collection with the operation in the body, so the
three route pages collapse into one. samples became sample. Creates send an
Idempotency-Key and return a status_url to poll, which the client follows
rather than building the path.
Full rebuild is closed: regenerate_profiles answers 501 not_yet_available and
the docs say so instead of teaching a daily cadence that cannot run.
Live e2e against the feature neuron: the profile envelope has no generation_count, and the regenerate cooldown is once per day (86400s), not hourly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Model the profiles feature guide on the Dream guide: add a Plan availability table with eligibility criteria, a 'When profiles update' cadence section, a schema size-budget note, and an FAQ.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the profile surface to both SDKs and documents it.
Python (MemoryClient + AsyncMemoryClient) and TypeScript gain:
get/generate profile, get/update settings, sample, regenerate.
A profile's keys come from the customer's own JSON Schema, so the TS
client keeps `profile` opaque and passes `schema` through untouched in
both directions. Camel-casing them would return field names that do not
match the schema the customer wrote.
Reads use the v2 envelope, where a known entity with no profile yet is a
200 carrying a status rather than a 404, so an empty state is
distinguishable from an error.
Verified against a live environment running this API: settings
round-trip, a partial update leaves the schema intact, generation
produces a profile under the configured schema, and sample, regenerate,
cooldown and the 400/404 paths all answer as documented.