# What changed

On 2026-10-24 Vector DB, AI Memory, the AI Gateway and Agents moved to one set of words: `userId` names your end user everywhere, a text is `text`, lists page with `nextCursor`, every refusal carries a `code` (and `param` for the field at fault), and any text over 2,000 characters is refused with `input_too_long` rather than cut. Code written against the old answers may need the changes below.

The old names listed last keep working until 2026-11-23, then they are removed. SDK 0.4.0 and the CLI 0.4.0 already use the new ones.

## Vector DB

- A text over 2,000 characters is refused with 400 `input_too_long` (`param` names it), also when sent with `values`. Metadata keys that start with `_hk_` are refused, and metadata plus text over 10,240 bytes is 400 `metadata_too_large`.
- A namespace written to must be 1–64 letters, digits and . _ - : @ + = (an id or an email fits). Writes into an older namespace with a space or a slash are refused with 400 `invalid_request`; reading from it still works.
- Filters with `$or`, `$and`, `$exists` or an unknown operator are refused with 400 `filter_operator_unsupported`, and filter errors carry `code` and `param`.
- Visitor chat searches only collections opened to it (`visitorChat: true`). Every existing collection starts closed. A visitor's chat run searches by text across the whole collection, every namespace included, with at most 10 matches: open only a collection whose every vector may be shown to anyone.
- A collection's `endpoint` is its own address (`/api/vectors/:id`), and it has `visitor_chat`. Deleting vectors by id no longer lowers `vector_count` at once; `GET /api/vectors/:id` reads the current count.
- The connector's query_vectors no longer takes `returnMetadata` and caps `topK` at 50.

## AI Memory

- A store created without `kind` is kind "memory" (it used to be "kv"), and every data call on it needs `userId` (400 `user_id_required`). Stores created before keep their kind and work as before.
- Store answers (`GET`/`POST /api/projects/:id/memory`, `GET /api/memory/:id`, `/api/resources/memory`) no longer carry `provider`, `endpoint` or `seq`; they gain `searchable`, `edge_fallback`, `user_id_required`, `created_at` and `quota`.
- Changing a memory's text gives it a new id: use the `id` in the answer (`previous_id` is the old one). 409 `already_exists` when the user already has that text.
- Refusals carry `code` and `param`: a bad user id is 400 `invalid_user_id`, a call the store's kind does not have is 409 `wrong_store_kind`. HTTP statuses are unchanged.
- The connector's search_memory sends `scope` as given; with `userId` too and the two different, it is 400 `conflicting_param`.

## AI Gateway

- An unknown model is 404 `model_not_found` (it was 400), on `/api/ai/chat` and `/api/ai/v1`.
- A model you name that cannot be reached is 503 `model_unavailable`, with nothing charged, instead of being answered by Llama. Use `harakumo-1` to fail over.
- `/api/ai/v1/chat/completions` refuses unknown fields and the parameters it does not honour with 400 `unsupported_parameter`; parameters with no effect are accepted only at their no-effect values. The native `POST /api/ai/chat` refuses `tools`, `tool_choice` and `response_format` other than text (other unknown fields are still ignored).
- Output defaults to each model's own: 4,096 tokens on vendor models, 1,024 on Llama, up to 32,000. A `max_tokens` over a model's most is a 400 naming the model.
- Tools and JSON output (`json_object`, `json_schema`) work only on the models whose `supported_parameters` list them, once the model has passed a live check through the gateway; elsewhere they are 400 `unsupported_parameter`. `json_object` needs the word JSON in a message, and a conversation with tool calls must send `tools`.
- Every cheap and mid-price model is on by default for a workspace that never saved its model settings; Claude Opus stays off, and so does Kimi K2.6 until it is confirmed.
- Added, nothing removed: OpenAI error objects carry `param` and `metadata`, `usage` has `cost`, and `harakumo` has `request_id`.

## Agents

- Agents and runs have one shape: `tools` is a list (it may hold function tools), `allow_writes` is true or false, `trigger` is `{ kind, label }`, a run has `cost_usd` only, `stop_reason` is null when it completed, `started_by` is `api` when someone asked, and a step has `tool`, parsed `arguments` and `ok` true or false.
- `GET /api/agents/:id` answers `recent_runs` (the 5 newest, without steps) instead of `runs` (20 with steps). `GET /api/agents/runs/:runId` has one run with its steps, and `GET /api/agents/:id/runs` pages through them.
- A run you ask for starts at once in the background and gets its id at once (`POST /api/agents/:id/runs`); `wait` (0 to 60 seconds) counts from when the request arrives. A run that finished answers 200 (it was 202). The `queued` answer is gone.
- `maxSteps` counts model calls, each with up to 8 tool calls. A run has 5 minutes (`timeLimitSeconds` 10 to 300), and a cost cap of $0.25 on Hobby and $1 on paid plans unless the agent or the run sets one (stop_reason `budget`).
- A run with no sign of life for 5 minutes is marked failed (`stale`) and frees its slot. A run that could not start is 503 `run_not_started`, nothing done or charged.
- A schedule, app events and visitor chat can be on together: setting one no longer turns the others off, and `trigger.kind` is a label only.
- An agent whose tools are function tools only is offered only those; list tool names beside them to keep them.
- SDK: `agents.run` resolves to the run itself (not `{ run }`), and waits for it to end.

## Old names kept until 2026-11-23

| Old | Use instead |
| --- | --- |
| `POST /api/agents/:id` to start a run (answers `Deprecation` and `Sunset` headers) | `POST /api/agents/:id/runs { input, wait? }` |
| SDK `memory.forget(storeId, scope)` (one conversation only) | `memory.forgetUser(storeId, userId)`, or `DELETE /api/memory/:id/users/:userId`: everything kept for the user |
| SDK `vectors.indexMetadata` and `POST /api/vectors/:id { action: "index-metadata" }` | `vectors.update(id, { metadataIndexes })`, or `PATCH /api/vectors/:id { metadataIndexes }` |

> `userId` on vector calls (the same field as `namespace`), `memory` for a memory's `text`, and `user_id` or `scope` for `userId` are accepted names, not old ones: they stay.
