Skip to main content
Decorator to authorize and optionally sanitize a shared (read-only) thread before it is displayed to another authenticated user. Requires that thread sharing is enabled via: If any of these are missing, the decorator won’t be invoked. A thread is viewable when either of the following is true:
  • The callback returns True, or
  • The thread metadata has is_shared = true
This means the callback can grant access to threads that have not been explicitly shared (e.g. for admin users), and conversely, threads marked as shared are viewable even if the callback is not defined.
Behavior change in 2.8.1: In 2.8.0 the thread was viewable only when both the callback returned True and is_shared was true in metadata. Since 2.8.1, either condition is sufficient. This allows use cases like admin access to any thread without requiring it to be shared first.
This hook runs on every attempt to view a shared thread. You can mutate the thread dict in-place to redact or filter content.

Usage

import chainlit as cl
from typing import Any, Dict


@cl.on_shared_thread_view
async def on_shared_thread_view(thread: Dict[str, Any], current_user: cl.User) -> bool:
    # Deny if user not on same team
    owner_team = thread.get("metadata", {}).get("team")
    user_team = current_user.metadata.get("team")
    if owner_team != user_team:
        return False

    # Remove messages created after it was shared (freeze at share time)
    shared_at = thread.get("metadata", {}).get("shared_at")
    if shared_at:
        thread["steps"] = [
            s for s in thread.get("steps", []) if s.get("created_at") <= shared_at
        ]

    # Redact sensitive outputs
    for step in thread.get("steps", []):
        if step.get("metadata", {}).get("sensitive"):
            step["output"] = "[REDACTED]"

    return True
# Simpler example: allow if the thread is marked as shared
@cl.on_shared_thread_view
async def on_shared_thread_view(thread, current_user: cl.User) -> bool:
    return bool(thread.get("metadata", {}).get("is_shared"))

Parameters

thread
ThreadDict
The serialized thread (including messages/steps, elements and metadata). Mutate in-place to sanitize.
current_user
User
The authenticated user requesting access to the shared thread.

Return Value

Return True to allow the sanitized (or unmodified) thread to be returned. Return False (or raise) to deny with a 404 (the thread appears non-existent to the requester).

Common Patterns

  • Role gate: allow administrators regardless of team.
  • Expiry: compare shared_at with now() and deny after a duration.
  • Partial visibility: trim messages beyond a timestamp or with specific labels.
  • Redaction: scrub PII using regex before returning.
  • Audit: log each successful access (user id, thread id, time).

Minimal Example (Allow All)

@cl.on_shared_thread_view
async def on_shared_thread_view(thread, current_user: cl.User) -> bool:
    return True  # Accept every view (demo only)