meta
Type
External
Status
Published
Created
Mar 17, 2026
Updated
Mar 17, 2026

Every scope accessor has two metadata properties: source and query. They describe where a scope comes from.

aui.thread.source; // "root" | "parentScope" | null
aui.thread.query; // {} | { index: 0 } | null

Root scopes#

When you fill a scope directly via useAui({ ... }), it gets source: "root" and an empty query:

const aui = useAui({ thread: ThreadResource() });

aui.thread.source; // "root"
aui.thread.query; // {}

This is the default — the scope was provided directly, not derived from another scope.

Derived scopes#

When a scope is created via Derived, its source points to the parent scope it was derived from, and query carries the lookup parameters:

const aui = useAui({
  message: Derived({
    source: "thread",
    query: { index: 0 },
    get: (aui) => aui.thread().message({ index: 0 }),
  }),
});

aui.message.source; // "thread"
aui.message.query; // { index: 0 }

You can declare the expected meta shape in ScopeRegistry:

declare module "@assistant-ui/store" {
  interface ScopeRegistry {
    message: {
      methods: {
        getState: () => { role: string; content: string };
      };
      meta: { source: "thread"; query: { index: number } };
    };
  }
}

This makes the source and query types precise — TypeScript will enforce that any Derived providing the message scope uses the correct source and query shape.

Unavailable scopes#

When a scope hasn't been provided by any AuiProvider above the current component, its accessor has source: null and query: null:

aui.message.source; // null — no message scope in context
aui.message.query; // null

This is how you check whether a scope is available.

Summary#

sourceMeaning
"root"Scope was filled directly via useAui({ ... })
"parentScope"Scope was derived from another scope via Derived
nullScope is not available in the current context