Backoffice API¶
kavalai.backoffice is the FastAPI service behind the management UI. It
exposes agents, sessions, runs, metrics, model-call statistics and RAG indexes,
and the project service that scopes them.
Copyright 2026 OÜ KAVAL AI (registry code 17393877)
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
- kavalai.backoffice.server.get_backoffice_session()[source]¶
Context manager to provide a session for the backoffice database. Handles connection errors gracefully.
- kavalai.backoffice.server.get_project_session(project: Project)[source]¶
Context manager to provide a session for a specific project’s agent database. Handles connection errors gracefully.
- kavalai.backoffice.server.required_setting(name: str) str[source]¶
A setting the backoffice cannot run without.
There is no development fallback on purpose: a cookie signed with a well-known key, or an OAuth client with no id, is a backoffice that looks as if it works right up to the moment it is exposed.
- async kavalai.backoffice.server.assert_is_owner(session: AsyncSession, request: Request, project_id: UUID)[source]¶
- async kavalai.backoffice.server.assert_is_admin_or_owner(session: AsyncSession, request: Request, project_id: UUID)[source]¶
- async kavalai.backoffice.server.assert_is_member(session: AsyncSession, request: Request, project_id: UUID)[source]¶
- async kavalai.backoffice.server.get_project_and_assert_access(request: Request, project_id: UUID) Project[source]¶
Fetch project and assert user is a member.
- async kavalai.backoffice.server.set_active_project(project_id: UUID, request: Request)[source]¶
-
async kavalai.backoffice.server.projects_create(request: Request, data: dict =
Body(PydanticUndefined))[source]¶
- async kavalai.backoffice.server.projects_get_by_id(project_id: UUID, request: Request)[source]¶
-
async kavalai.backoffice.server.projects_update(project_id: UUID, request: Request, data: dict =
Body(PydanticUndefined))[source]¶
- async kavalai.backoffice.server.projects_delete(project_id: UUID, request: Request)[source]¶
-
async kavalai.backoffice.server.users_create(request: Request, data: dict =
Body(PydanticUndefined))[source]¶
-
async kavalai.backoffice.server.users_update(user_id: UUID, request: Request, data: dict =
Body(PydanticUndefined))[source]¶
- async kavalai.backoffice.server.agents_get_by_id(project_id: UUID, agent_id: UUID, request: Request)[source]¶
-
async kavalai.backoffice.server.workflows_render_svg(request: Request, data: dict =
Body(PydanticUndefined))[source]¶ Render a workflow graph to an SVG diagram.
Accepts
{"workflow": {...}}(or a bare workflow dict) and returns animage/svg+xmldocument. The agents page uses this to show an agent’s workflow as a backend-generated diagram (replacing the client-side build).
- async kavalai.backoffice.server.agents_get_all(project_id: UUID, request: Request)[source]¶
Fetch all agents belonging to a specific project.
-
async kavalai.backoffice.server.agents_get_stats(project_id: UUID, request: Request, days: int =
7, agent_id: UUID | None =None)[source]¶ Fetch daily stats for agents in a specific project.
-
async kavalai.backoffice.server.agents_get_summary_stats(project_id: UUID, request: Request, agent_id: UUID | None =
None)[source]¶ Fetch summary stats (last 30 days) for agents in a specific project.
-
async kavalai.backoffice.server.agents_get_sessions(project_id: UUID, request: Request, agent_id: UUID | None =
None, search: str | None =None, external_id: str | None =None, start_date: datetime | None =None, end_date: datetime | None =None, limit: int =50, offset: int =0)[source]¶ Fetch session summaries for a specific project.
external_idmatches the session’s caller-supplied key as a prefix. Evaluation runs record their sessions aseval:{tag}:{case}, so this is the click-through from a failing case to the conversation that produced it.
- async kavalai.backoffice.server.agents_get_session_details(project_id: UUID, session_id: UUID, request: Request)[source]¶
Fetch all details (messages, runs, tasks) for a specific session.
-
async kavalai.backoffice.server.projects_get_llm_call_stats(project_id: UUID, request: Request, call_type: str | None =
None, limit: int =50, offset: int =0, agent_id: UUID | None =None, session_id: UUID | None =None, run_id: UUID | None =None)[source]¶ Fetch paginated model call stats for a specific project.
agent_id,session_idandrun_idnarrow the list to the calls attributed to that agent, conversation or run — the run’s own calls are what the task debugger shows beside its tasks.
-
kavalai.backoffice.server.rag_service_for_project(project: Project, model: str | None =
None, normalizer=None, session_factory=None) CollectionRagService[source]¶ The RAG service over the project’s agent database.
Both backends share one storage model, so the explorer endpoints only differ in how they reach the database: a SQLite project’s index lives in the same file as its agent tables, a PostgreSQL project’s in the project’s
rag_schema(its agent schema unless one is set), reached throughsession_factory(the project’s sessionmaker unless one is given).The service never provisions: the explorer only reads, and a registry or collection it would create is a write to a database that may be production. A read-only project’s SQLite file is opened with
PRAGMA query_onlybesides.
-
async kavalai.backoffice.server.projects_rag_query(project_id: UUID, request: Request, query_data: dict =
Body(PydanticUndefined))[source]¶ Execute a RAG query for a specific project.
modelis optional: an existing collection is embedded with the model recorded for it, so a query needs onlytext.
- async kavalai.backoffice.server.projects_rag_stats(project_id: UUID, request: Request)[source]¶
Fetch RAG statistics for a specific project.
- async kavalai.backoffice.server.projects_rag_collections(project_id: UUID, request: Request)[source]¶
List a project’s RAG collections with their model, dimension and size.
The explorer takes the model a query is embedded with from here.
- async kavalai.backoffice.server.projects_train_pca(project_id: UUID, collection_name: str, request: Request)[source]¶
Trigger PCA training for a specific project and collection.
-
async kavalai.backoffice.server.projects_test_connection(project_id: str, request: Request, data: dict =
Body({}))[source]¶ Test connection to the project database.
- async kavalai.backoffice.server.projects_get_members(project_id: UUID, request: Request)[source]¶
-
async kavalai.backoffice.server.projects_add_member(project_id: UUID, request: Request, data: dict =
Body(PydanticUndefined))[source]¶
-
async kavalai.backoffice.server.projects_update_member(project_id: UUID, request: Request, data: dict =
Body(PydanticUndefined))[source]¶
- async kavalai.backoffice.server.projects_remove_member(project_id: UUID, user_id: UUID, request: Request)[source]¶
Copyright 2026 OÜ KAVAL AI (registry code 17393877)
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-
kavalai.backoffice.project_service.PROJECT_FIELDS =
frozenset({'db_host', 'db_name', 'db_password', 'db_port', 'db_schema', 'db_type', 'db_user', 'description', 'name', 'rag_schema', 'read_only'})¶ its name, description and connection settings. Everything else a project row carries —
id, the timestamps, the caller’srolethe list endpoint adds — is the server’s.- Type:¶
The fields of a project a client may set
- kavalai.backoffice.project_service.project_fields(data: dict[str, Any]) dict[str, Any][source]¶
The part of a request body that may become project columns.
The projects page sends the whole project back as it listed it, so a body may carry
created_atas an ISO string, which the database refuses for a timestamp column; keys outsidePROJECT_FIELDSare dropped rather than written.
- class kavalai.backoffice.project_service.ProjectService(session_maker: async_sessionmaker[AsyncSession])[source]¶
Bases:
object- async delete_project(project_id: UUID) bool[source]¶
- kavalai.backoffice.project_service.project_db_uri(project: Project) str[source]¶
The URI of the agent database a project points at.
db_typedecides how the connection fields are read:sqlitetakesdb_nameas a file path, anything else builds a PostgreSQL URI from host, port, user, password and database.
- kavalai.backoffice.project_service.project_schema(project: Project) str | None[source]¶
The schema of the project’s agent database (
Nonefor SQLite).
- kavalai.backoffice.project_service.project_rag_schema(project: Project) str | None[source]¶
The schema of the project’s RAG collections:
rag_schemawhen set, otherwise the agent database’s own schema (Nonefor SQLite).
- kavalai.backoffice.project_service.project_read_only(project: Project) bool[source]¶
Whether the backoffice may only read the project’s agent database.
On unless the project says
False: a project built from a form (Project(**data)on the connection test) carries no column default, and the safe reading of “unsaid” is read-only.
- kavalai.backoffice.project_service.project_sessionmaker(project: Project) async_sessionmaker[AsyncSession][source]¶
A sessionmaker for the agent database the project points at.
A read-only project gets connections the database itself holds to reads (
get_sessionmaker()).