Skip to main content
An assistant is what answers your customers. Its behaviour is not one prompt string: it is an ordered list of blocks, each one a named piece of the system prompt, plus the functions it is allowed to call while it answers. This API edits that configuration. Everything the portal’s assistant editor does to prompts, block ordering and webhook functions, you can do here — which is what makes it possible to version your assistants in git, provision them per client, or let an agent tune them.

The data model

Assistant

Name, model, knowledge nodes, and an ordered list of references to blocks.

Block

One named piece of the prompt, with a type that decides where it lands.

Version

An immutable snapshot of a block’s content. Saving never overwrites.

Function

An HTTPS webhook the assistant can call mid-conversation.
A block is not owned by an assistant. It lives in the project’s catalogue and any number of assistants can reference it, each pinning a different version if they want to. Attaching and detaching is wiring, not creation — detaching a block leaves it in the catalogue, and deleting an assistant leaves all of its blocks behind.

The three-step drill-down

The read path is deliberately three calls, because the second one is the cheap one you will make most:
Step 2 never returns content, and that is structural rather than a filter we apply: a block document genuinely holds no content. The text lives in its versions, which is why reading it is a separate call and why saving it creates history for free.

Block types

There is one creation endpoint per type, because the type is what decides where the block lands in the prompt and what it is expected to say. family is derived from the type and is read-only. It decides which section of the prompt the block is composed into, so it is not something a caller gets to choose.
One identity block of each type per assistant. Attaching a second personification, objective or response_format to the same assistant fails with ASSISTANT_DUPLICATE_IDENTITY_BLOCK. Instruction blocks have no such limit — an assistant can hold several steps blocks.

Catalogue blocks are read-only here

Five more types exist and you will see them in GET /v1/blocks and in an assistant’s block list: product_info, store_info, reservation_info, tables_info and tags. You can read their content, rename them and archive them, but saving their content returns 409 BLOCK_TYPE_NOT_WRITABLE.
This is not an arbitrary restriction. Saving a product_info block has to rebuild up to eleven ecommerce functions on the assistant, keyed to the store and product ids inside the payload; store_info rebuilds the branch lookup function. That rebuild lives in the portal. If the API accepted the write without it, the block would save cleanly and the assistant would silently lose its ecommerce toolset — which is worse than a refusal. Configure those five in the portal.Every block field also tells you directly: content_writable is true for the seven types above and false for these five.

Content is text

Blocks written through this API are free blocks: their content is plain text, not a structured object. Three markdown conventions are recognised, because the portal editor renders them as real list and heading elements rather than literal characters: Everything else is a paragraph. Reading the content back returns the same text.
Rich formatting authored in the portal flattens. Bold, italics, colours and inline function chips do not survive a round trip through this API: reading gives you the text, and writing replaces the document with a plain-text rendering. If an assistant was carefully styled in the portal, prefer editing it there.

Saving content never overwrites

PUT /v1/blocks/{id}/content appends an immutable version and points the block at it. The previous one stays in the history and can be restored, which also appends rather than overwrites. Nothing in this API destroys a version. The same is true of deletes at the block level: DELETE /v1/blocks/{id} archives. Assistants that still reference an archived block keep using it — archiving hides it from the catalogue, it does not switch it off. To take a block out of an assistant, detach it.

Functions

A function is an HTTPS webhook the assistant can call while it answers. You describe what it does, the model decides when to call it, and Keebai makes the request. Placeholders written {{name}} in the path, the query string or the body are filled at call time from the arguments the model chose, so https://erp.example.com/stock/{{sku}} with a sku parameter is the normal shape.
Functions are company-wide, not project-scoped. Unlike assistants and blocks, a function is visible to every project in the company. A name collision is a company-level collision.
Two things about them are worth reading before your first write: how secret values are masked and which URLs are rejected.

Scoping

Two tokens on two projects of the same company see different assistants and different blocks, and neither can read the other’s by id. They see the same functions.

Endpoints

Assistants

Wiring blocks to an assistant

Blocks

Functions

A full round trip

Next steps

Create an assistant

The first call, and what it gives you for free.

Save block content

Writing prompts as text, and which types refuse.

Webhook security

Which URLs are rejected, and how secrets are masked.

Scopes

assistants:read and assistants:write, and what each unlocks.