Introspection - NinjaStack Docs
Description: Schema-first agentic backend framework documentation

Skip to content

# Introspection API

## `` ninja_introspect

ninja-introspect — Polyglot database introspection engine for Ninja Stack.

### `` __all__ `module-attribute`

    __all__ = [
        "GraphProvider",
        "IntrospectionEngine",
        "IntrospectionProvider",
        "IntrospectionResult",
        "MongoProvider",
        "SQLProvider",
        "VectorProvider",
    ]

### `` IntrospectionEngine

    IntrospectionEngine(project_name: str = 'untitled')

Orchestrates multiple introspection providers and merges their results.

Usage::

    engine = IntrospectionEngine(project_name="my-project")
    schema = await engine.run([
        "sqlite+aiosqlite:///path/to/db.sqlite",
        "mongodb://localhost:27017/mydb",
    ])

Source code in `libs/ninja-introspect/src/ninja_introspect/engine.py`

    68
    69
    def __init__(self, project_name: str = "untitled") -> None:
        self.project_name = project_name

#### `` project_name `instance-attribute`

    project_name = project_name

#### `` run `async`

    run(
        connection_strings: list[str],
        *,
        providers: dict[str, IntrospectionProvider]
        | None = None,
    ) -> AgenticSchema

Run introspection across all connection strings and merge results.

PARAMETER | DESCRIPTION
--- | ---
`connection_strings` | List of database connection URIs. TYPE: `list[str]`
`providers` | Optional mapping of connection string → provider override. TYPE: `dict[str, IntrospectionProvider] | None` DEFAULT: `None`

RETURNS | DESCRIPTION
--- | ---
`AgenticSchema` | A merged AgenticSchema containing entities and relationships from all sources.

Source code in `libs/ninja-introspect/src/ninja_introspect/engine.py`

     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    async def run(
        self,
        connection_strings: list[str],
        *,
        providers: dict[str, IntrospectionProvider] | None = None,
    ) -> AgenticSchema:
        """Run introspection across all connection strings and merge results.

        Args:
            connection_strings: List of database connection URIs.
            providers: Optional mapping of connection string → provider override.

        Returns:
            A merged AgenticSchema containing entities and relationships from all sources.
        """
        all_entities: list[EntitySchema] = []
        all_relationships: list[RelationshipSchema] = []

        for conn_str in connection_strings:
            if providers and conn_str in providers:
                provider = providers[conn_str]
            else:
                provider = _detect_provider(conn_str)

            result: IntrospectionResult = await provider.introspect(conn_str)
            all_entities.extend(result.entities)
            all_relationships.extend(result.relationships)

        return AgenticSchema(
            project_name=self.project_name,
            entities=all_entities,
            relationships=all_relationships,
        )

### `` IntrospectionProvider

Bases: `ABC`

Protocol for database introspection providers.

Each provider connects to a specific database type, reads its schema, and produces EntitySchema + RelationshipSchema objects.

#### `` introspect `abstractmethod` `async`

    introspect(connection_string: str) -> IntrospectionResult

Connect to the database and extract schema information.

PARAMETER | DESCRIPTION
--- | ---
`connection_string` | Database connection URI. TYPE: `str`

RETURNS | DESCRIPTION
--- | ---
`IntrospectionResult` | IntrospectionResult containing discovered entities and relationships.

Source code in `libs/ninja-introspect/src/ninja_introspect/providers/base.py`

    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    @abstractmethod
    async def introspect(self, connection_string: str) -> IntrospectionResult:
        """Connect to the database and extract schema information.

        Args:
            connection_string: Database connection URI.

        Returns:
            IntrospectionResult containing discovered entities and relationships.
        """

### `` IntrospectionResult `dataclass`

    IntrospectionResult(
        entities: list[EntitySchema] = list(),
        relationships: list[RelationshipSchema] = list(),
    )

Result from a single provider's introspection run.

#### `` entities `class-attribute` `instance-attribute`

    entities: list[EntitySchema] = field(default_factory=list)

#### `` relationships `class-attribute` `instance-attribute`

    relationships: list[RelationshipSchema] = field(
        default_factory=list
    )

### `` GraphProvider

    GraphProvider(sample_size: int = DEFAULT_SAMPLE_SIZE)

Bases: `IntrospectionProvider`

Introspects Neo4j graph databases — reads node labels, relationship types, and properties.

Source code in `libs/ninja-introspect/src/ninja_introspect/providers/graph.py`

    51
    52
    def __init__(self, sample_size: int = DEFAULT_SAMPLE_SIZE) -> None:
        self.sample_size = sample_size

#### `` sample_size `instance-attribute`

    sample_size = sample_size

#### `` introspect `async`

    introspect(connection_string: str) -> IntrospectionResult

Source code in `libs/ninja-introspect/src/ninja_introspect/providers/graph.py`

    54
    55
    56
    57
    58
    59
    async def introspect(self, connection_string: str) -> IntrospectionResult:
        driver = AsyncGraphDatabase.driver(connection_string)
        try:
            return await self._run_introspection(driver)
        finally:
            await driver.close()

### `` MongoProvider

    MongoProvider(sample_size: int = DEFAULT_SAMPLE_SIZE)

Bases: `IntrospectionProvider`

Introspects MongoDB databases by sampling documents to infer schema.

Source code in `libs/ninja-introspect/src/ninja_introspect/providers/mongo.py`

    64
    65
    def __init__(self, sample_size: int = DEFAULT_SAMPLE_SIZE) -> None:
        self.sample_size = sample_size

#### `` sample_size `instance-attribute`

    sample_size = sample_size

#### `` introspect `async`

    introspect(connection_string: str) -> IntrospectionResult

Source code in `libs/ninja-introspect/src/ninja_introspect/providers/mongo.py`

    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    async def introspect(self, connection_string: str) -> IntrospectionResult:
        client: AsyncIOMotorClient = AsyncIOMotorClient(connection_string)  # type: ignore[type-arg]
        try:
            db_name = client.get_default_database().name  # type: ignore[union-attr]
            db = client[db_name]

            collection_names: list[str] = await db.list_collection_names()
            # Filter out system collections
            collection_names = [c for c in collection_names if not c.startswith("system.")]

            entities: list[EntitySchema] = []
            for coll_name in sorted(collection_names):
                entity = await self._introspect_collection(db, coll_name)
                if entity is not None:
                    entities.append(entity)

            return IntrospectionResult(entities=entities)
        finally:
            client.close()

### `` SQLProvider

Bases: `IntrospectionProvider`

Introspects SQL databases (Postgres, MySQL, SQLite) via SQLAlchemy.

#### `` introspect `async`

    introspect(connection_string: str) -> IntrospectionResult

Source code in `libs/ninja-introspect/src/ninja_introspect/providers/sql.py`

    58
    59
    60
    61
    62
    63
    async def introspect(self, connection_string: str) -> IntrospectionResult:
        engine = create_async_engine(connection_string)
        try:
            return await self._run_introspection(engine)
        finally:
            await engine.dispose()

### `` VectorProvider

Bases: `IntrospectionProvider`

Introspects vector databases (Chroma) — reads collection metadata.

#### `` introspect `async`

    introspect(connection_string: str) -> IntrospectionResult

Introspect a Chroma vector database.

PARAMETER | DESCRIPTION
--- | ---
`connection_string` | For Chroma, this is the persist directory path or an HTTP URL like `http://host:port`. TYPE: `str`

Source code in `libs/ninja-introspect/src/ninja_introspect/providers/vector.py`

    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    async def introspect(self, connection_string: str) -> IntrospectionResult:
        """Introspect a Chroma vector database.

        Args:
            connection_string: For Chroma, this is the persist directory path
                or an HTTP URL like ``http://host:port``.
        """
        client = self._create_client(connection_string)
        collections = client.list_collections()

        entities: list[EntitySchema] = []
        for collection in collections:
            entity = self._introspect_collection(collection)
            entities.append(entity)

        return IntrospectionResult(entities=entities)