Skip to content

Content folder service

Knowledge-base folders are content scopes: they have a scopeId (exposed in the toolkit as scope_id on :class:~unique_toolkit.experimental.resources.content_folder.schemas.CreatedFolder and related models). The :class:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder wraps create, read, access changes, and delete calls so you can use the same credentials as the rest of the toolkit (see Getting started).

This page focuses on a short manual test loop: create a folder, confirm it exists (API + optional UI), optionally stop in a debugger, then delete it again.

Environment

Use a working UniqueSettings / SDK setup (UNIQUE_API_KEY, UNIQUE_APP_ID, user and company context) as in other examples. The runnable script below calls :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.from_settings.

Ways to create folders

:meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.create accepts exactly one of these shapes per call (mixing them raises TypeError):

Style When to use
paths= One or more absolute paths from the KB root—pass a str for a single path or a list[str] for several in one API call.
parent_scope_id= + relative_path_segments= You already know the parent folder’s scope id and want to create one or more nested segments by name (not full paths).

Segments are folder names only—e.g. ["2026", "Inbox"] creates Inbox under 2026 under the given parent—not a second absolute path string.

Several absolute paths

#folder-mgmt-constants-multi
DEMO_MULTI_A = "/EntangledToolkitDocs/MultiA"
DEMO_MULTI_B = "/EntangledToolkitDocs/MultiB"
#folder-mgmt-create-multi-paths
created = folder_service.create(paths=[DEMO_MULTI_A, DEMO_MULTI_B])
for folder in created:
    print(folder.id, folder.name)
#folder-mgmt-main-multi / file: docs/.python_files/folder_create_multiple_abs_paths.py
<<example-script-deps>>

<<folder-mgmt-imports>>

<<folder-mgmt-init>>

<<folder-mgmt-constants-multi>>

<<folder-mgmt-create-multi-paths>>
Multiple absolute paths (full script)
# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "unique-toolkit>=2026.22.0",
#   "unique-sdk>=2026.22.0",
# ]
# ///

# %%

from __future__ import annotations

from unique_toolkit.experimental.resources.content_folder import ContentFolder

folder_service = ContentFolder.from_settings()

DEMO_MULTI_A = "/EntangledToolkitDocs/MultiA"
DEMO_MULTI_B = "/EntangledToolkitDocs/MultiB"

created = folder_service.create(paths=[DEMO_MULTI_A, DEMO_MULTI_B])
for folder in created:
    print(folder.id, folder.name)

Under a parent you know by scope id

Typical sources for parent_scope_id:

  • The id on :class:~unique_toolkit.experimental.resources.content_folder.schemas.CreatedFolder after an earlier create (often created[-1].id for the leaf of a chain).
  • The id on :class:~unique_toolkit.experimental.resources.content_folder.schemas.FolderInfo from :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.read (by scope_id or folder_path).
  • Any scope id you already store from the product UI or another API.

Then pass path segments (child folder names) to create under that parent:

#folder-mgmt-constants-nested
PARENT_ROOT = "/EntangledToolkitDocs/ParentRoot"
#folder-mgmt-create-nested-under-parent
parent_chain = folder_service.create(paths=PARENT_ROOT)
parent_scope_id = parent_chain[-1].id

nested_chain = folder_service.create(
    parent_scope_id=parent_scope_id,
    relative_path_segments=["Projects", "Scratch"],
)
leaf = nested_chain[-1]
print("parent_scope_id=", parent_scope_id)
print("leaf id=", leaf.id, "name=", leaf.name)
#folder-mgmt-main-nested / file: docs/.python_files/folder_create_under_parent.py
<<example-script-deps>>

<<folder-mgmt-imports>>

<<folder-mgmt-init>>

<<folder-mgmt-constants-nested>>

<<folder-mgmt-create-nested-under-parent>>
Create under parent by scope id (full script)
# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "unique-toolkit>=2026.22.0",
#   "unique-sdk>=2026.22.0",
# ]
# ///

# %%

from __future__ import annotations

from unique_toolkit.experimental.resources.content_folder import ContentFolder

folder_service = ContentFolder.from_settings()

PARENT_ROOT = "/EntangledToolkitDocs/ParentRoot"

parent_chain = folder_service.create(paths=PARENT_ROOT)
parent_scope_id = parent_chain[-1].id

nested_chain = folder_service.create(
    parent_scope_id=parent_scope_id,
    relative_path_segments=["Projects", "Scratch"],
)
leaf = nested_chain[-1]
print("parent_scope_id=", parent_scope_id)
print("leaf id=", leaf.id, "name=", leaf.name)

Under a parent you only know by path

If you have the parent’s absolute path but not its id, resolve it once, then create by scope id and segments:

#folder-mgmt-create-nested-after-path-lookup
parent_meta = folder_service.read(folder_path=PARENT_ROOT)
nested = folder_service.create(
    parent_scope_id=parent_meta.id,
    relative_path_segments=["FromPathLookup"],
)
print("leaf", nested[-1].id, nested[-1].name)

This is the same API shape as above; only the parent id comes from :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.read instead of a previous create result.

Create, verify, delete

Typical flow:

  1. Create with an absolute path from the knowledge-base root (one of the supported shapes on :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.create).
  2. Verify with :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.read using the leaf folder’s scope_id (last entry returned from create when the path has multiple segments).
  3. Pause on a breakpoint or breakpoint() after step 2, reload the knowledge-base tree in the product UI, and confirm the folder appears.
  4. Delete with :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.delete using the same scope_id (or the absolute folder_path). Inspect success_folders / failed_folders on the :class:~unique_toolkit.experimental.resources.content_folder.schemas.DeleteResult if something does not match expectations.
#folder-mgmt-imports
from __future__ import annotations

from unique_toolkit.experimental.resources.content_folder import ContentFolder
#folder-mgmt-constants
# Absolute path from the KB root; change if this collides with real data.
DEMO_FOLDER_PATH = "/EntangledToolkitDocsDemo"
#folder-mgmt-init
folder_service = ContentFolder.from_settings()
#folder-mgmt-create
created = folder_service.create(paths=DEMO_FOLDER_PATH)
leaf = created[-1]
print(f"Created folder id={leaf.id!r} name={leaf.name!r}")
#folder-mgmt-verify
info = folder_service.read(scope_id=leaf.id)
print(
    f"Verified id={info.id!r} name={info.name!r} parent_id={info.parent_id!r} "
    f"(created as {DEMO_FOLDER_PATH!r}; compare in the UI)"
)
# Set a breakpoint here (IDE or `breakpoint()`) to inspect `info` and confirm in the UI.
#folder-mgmt-delete
delete_result = folder_service.delete(scope_id=leaf.id)
print("Deleted:", delete_result.success_folders, "Failed:", delete_result.failed_folders)

Run this example

Fetch the script at the latest released unique-toolkit tag and execute it with uv (requires network access to resolve dependencies).

Trust and dependencies

uv run may install packages declared in the script's inline metadata (PEP 723). Set RELEASE=unique-toolkit-v<version> to lock to a specific release for a fully reproducible run; otherwise the snippet always picks the newest non-prerelease unique-toolkit-v* tag from Unique-AG/ai. We deliberately fetch from an immutable release tag instead of a mutable branch tip.

# Optional: pin to a specific release, e.g.
#   RELEASE=unique-toolkit-v2026.22.0
RELEASE="${RELEASE:-}"

if [ -z "$RELEASE" ]; then
  # Unauthenticated GitHub API allows 60 req/hr/IP — export GH_TOKEN for higher limits.
  RELEASE=$(
    curl -fsSL ${GH_TOKEN:+-H "Authorization: Bearer $GH_TOKEN"} \
      "https://api.github.com/repos/Unique-AG/ai/releases?per_page=100" \
    | python3 -c '
import json, sys
for r in json.load(sys.stdin):
    if r.get("prerelease") or r.get("draft"):
        continue
    tag = r.get("tag_name", "")
    if tag.startswith("unique-toolkit-v"):
        print(tag); break
'
  )
fi

if [ -z "$RELEASE" ]; then
  echo "Could not resolve latest unique-toolkit release; set RELEASE=unique-toolkit-v<version>." >&2
  exit 1
fi

echo "Using release: $RELEASE"

curl -fsSL -o example.py \
  "https://raw.githubusercontent.com/Unique-AG/ai/${RELEASE}/unique_toolkit/docs/examples_from_docs/folder_create_verify_delete.py"

uv run example.py
rm -f example.py

Environment variables

Set UNIQUE_APP_KEY, UNIQUE_APP_ID, UNIQUE_AUTH_USER_ID, and UNIQUE_AUTH_COMPANY_ID (and other UNIQUE_* values your tenant needs) in the environment or a .env file before running. See Getting started for details.

Assembled runnable script

The block below is tangled to docs/.python_files/ and copied to examples_from_docs when you run generate_examples.sh in the unique_toolkit package root.

#folder-mgmt-main / file: docs/.python_files/folder_create_verify_delete.py
<<example-script-deps>>

<<folder-mgmt-imports>>

<<folder-mgmt-constants>>

<<folder-mgmt-init>>

<<folder-mgmt-create>>

<<folder-mgmt-verify>>

<<folder-mgmt-delete>>
Full example (click to expand)
# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "unique-toolkit>=2026.22.0",
#   "unique-sdk>=2026.22.0",
# ]
# ///

# %%

from __future__ import annotations

from unique_toolkit.experimental.resources.content_folder import ContentFolder

# Absolute path from the KB root; change if this collides with real data.
DEMO_FOLDER_PATH = "/EntangledToolkitDocsDemo"

folder_service = ContentFolder.from_settings()

created = folder_service.create(paths=DEMO_FOLDER_PATH)
leaf = created[-1]
print(f"Created folder id={leaf.id!r} name={leaf.name!r}")

info = folder_service.read(scope_id=leaf.id)
print(
    f"Verified id={info.id!r} name={info.name!r} parent_id={info.parent_id!r} "
    f"(created as {DEMO_FOLDER_PATH!r}; compare in the UI)"
)
# Set a breakpoint here (IDE or `breakpoint()`) to inspect `info` and confirm in the UI.

delete_result = folder_service.delete(scope_id=leaf.id)
print(
    "Deleted:", delete_result.success_folders, "Failed:", delete_result.failed_folders
)

Delete by path

If you prefer to address the folder by path instead of id, pass folder_path= (still exactly one of scope_id or folder_path):

#folder-mgmt-delete-by-path
folder_service.delete(folder_path=DEMO_FOLDER_PATH)

Behaviour notes

  • Creator access: By default, :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.create grants the acting user READ and WRITE on created scopes when inherit_access is false. See the class docstring for details.
  • Recursive delete: Pass recursive=True to :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.delete when the API should remove nested content according to platform rules.
  • Async: Use :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.create_async, :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.read_async, and :meth:~unique_toolkit.experimental.resources.content_folder.service.ContentFolder.delete_async in async code paths.

For uploading and searching documents inside a scope, continue with the Knowledge Base service examples.