Skip to content

API reference

The public Python surface re-exported from django_admin_agent.

Package entry points

AdminAgentServer

Bases: AGUIServer

The admin sidebar's mount object — a :class:~django_ag_ui.AGUIServer pre-configured for the Django admin.

Construct it once and mount its namespaced :attr:~django_ag_ui.AGUIServer.urls the admin.site.urls way, alongside the admin::

from django.contrib import admin
from django.urls import path
from django_admin_agent import AdminAgentServer

urlpatterns = [
    path("admin/", admin.site.urls),
    path("admin-agent/", AdminAgentServer().urls),
]
# reverse("admin_agent:endpoint") · "admin_agent:tools" · "admin_agent:threads" · …

It mounts the agent endpoint and its tool catalog, plus the thread / attachment / transcription sub-views when their stores are passed (the same conditional mounting as AGUIServer). The sidebar reverses these names within namespace; pass the same value to the template tag if you use a non-default one::

{% django_admin_agent_sidebar namespace="internal-agent" %}

Fail-closed by default. Every mounted route requires an authenticated, active staff user: require_authenticated=True gives 401 for an anonymous request and authorize=staff_required gives 403 for a non-staff one (JSON, not an HTML login redirect), and the agent endpoint is CSRF-protected (csrf_exempt=False — the sidebar bootstrap already sends the token). Without this an unauthenticated visitor could drive the agent and stream model data (e.g. auth.User rows) back over SSE. Relax it deliberately — e.g. authorize=lambda r: r.user.is_superuser to tighten, or require_authenticated=False to open it — but the default is locked.

Defaults the registry to the built-in admin tool registry (:func:~django_admin_agent.build_default_registry). Extra keyword arguments (model, instructions, audit_logger, get_user, conversation_store, attachment_store, transcription_backend) pass straight through to :class:~django_ag_ui.AGUIServer.

staff_required

staff_required(request: HttpRequest) -> bool

The default authorization gate: an active, staff user.

The mounted routes are JSON / SSE endpoints, so this returns a bool the views turn into a 403 — unlike admin_view(), whose HTML login redirect would corrupt an SSE stream or a JSON fetch.

build_default_registry

build_default_registry() -> ToolRegistry

Build a fresh registry with the default server-side admin tools.

register_admin_tools

register_admin_tools(registry: ToolRegistry) -> None

Register the full server-side admin tool set on registry.

Combines the read-only shell.* (ORM) and introspect.* (Django + admin introspection) tools.

register_shell_tools

register_shell_tools(registry: ToolRegistry) -> None

Register the read-only ORM/shell tool set on registry.

register_introspect_tools

register_introspect_tools(registry: ToolRegistry) -> None

Register the read-only Django-introspection tool set on registry.

Settings

AdminAgentSettings dataclass

Snapshot of the user-configurable DJANGO_ADMIN_AGENT settings.

Built fresh on every read so test overrides take effect immediately. The agent model itself is configured separately via django-ag-ui's DJANGO_AG_UI["MODEL"].

title instance-attribute

title: str

Header text shown on the sidebar chat panel.

auto_confirm instance-attribute

auto_confirm: bool

When True, destructive UI tools run without a confirmation modal. Passed to the Web Component as autoConfirm.

tool_display instance-attribute

tool_display: str

How much detail tool-call cards show: "minimal", "compact", or "full". Passed to the Web Component as the data-tool-display attribute; defaults to "compact" for a dense admin sidebar.

skills instance-attribute

skills: list[dict[str, Any]] | None

Optional override for the skill catalog (client Skill dicts). None uses the built-in admin catalog (:func:build_skills).

theme instance-attribute

theme: str | None

Web Component theme: "light" / "dark" / "auto" / "code". None leaves the component default (light).

density instance-attribute

density: str | None

"comfortable" / "compact". None leaves the default.

placement instance-attribute

placement: str | None

"bottom-left" / "side" / "sidebar" / "full" / "embedded" (or unset for the default floating bottom-right). "sidebar" is a full-height docked panel that collapses to an icon rail; pair it with :attr:side.

text_animation instance-attribute

text_animation: str | None

Incoming-text animation: "none" / "fade" / "word". None leaves the default (none).

strings instance-attribute

strings: dict[str, Any] | None

Localized UI strings for the Web Component, passed through as its data-strings table (a partial override merged over the English defaults). Wrap values in gettext_lazy so the sidebar follows the admin's active language. None leaves the component's English defaults.

icon_url instance-attribute

icon_url: str | None

URL of a header/launcher icon image, passed through as data-icon-url. None leaves the sidebar icon-less.

side instance-attribute

side: str | None

For placement="sidebar": which edge it docks to — "left" / "right" (data-side). None leaves the component default (right).

theme_toggle instance-attribute

theme_toggle: bool

When True, show the Web Component's built-in light⇄dark header toggle (data-theme-toggle), which flips :attr:theme and persists per tab. Defaults to False — the admin's own theme usually governs.

shell_field_redaction instance-attribute

shell_field_redaction: bool | str

Sensitive-field redaction for the shell.query_model / shell.get_model_instance tools. True (default) redacts any field whose name matches the built-in denylist pattern (password|token|secret|key|hash, case-insensitive) before the row reaches the LLM — even legitimate staff use shouldn't stream auth.User password hashes to a third-party model. False disables redaction; a regex str replaces the built-in pattern with your own.

get_settings

get_settings() -> AdminAgentSettings

Read the active DJANGO_ADMIN_AGENT settings dict.

Admin wiring

build_sidebar_context

build_sidebar_context(namespace: str = DEFAULT_URL_NAMESPACE) -> dict[str, Any]

Build the context the sidebar template needs.

namespace names the mounted :class:~django_admin_agent.AdminAgentServer to reverse against — the one it was constructed with. It is an argument rather than a setting because a project may mount more than one sidebar, and because the server already knows its own namespace: a setting made you say it twice and get it wrong.

Reverses the AG-UI endpoint URL, resolves the bootstrap module's static URL, reads the title / auto-confirm flag from settings, and resolves the admin index URL so the frontend nav.* tools can build changelist / changeform URLs without reversing named routes in the browser. Shared by the {% django_admin_agent_sidebar %} template tag and the :class:~django_admin_agent.admin.sidebar_admin_site.SidebarAdminSite each_context hook.

build_route_map

build_route_map() -> list[dict[str, Any]]

Build the agent's navigable-route manifest from the admin registry.

One changelist route (and one add route, when available) per registered model, shaped for the Web Component's routeMap{id, path, title, group}. The agent calls list_routes to discover destinations and navigate_to_route to jump to one, instead of guessing admin URLs.

build_skills

build_skills() -> list[dict[str, Any]]

The built-in admin skill catalog (client Skill dicts).

SidebarAdminSite

Bases: AdminSite

A drop-in AdminSite that exposes the sidebar config to every page.

Adds django_admin_agent (the sidebar context) to each_context so a base template can render the chat without the template tag. Using the {% django_admin_agent_sidebar %} tag in admin/base_site.html is the more common path and does not require swapping the admin site.

sidebar_namespace names the mounted :class:~django_admin_agent.AdminAgentServer to reverse against, matching the namespace= it was built with — the class attribute mirrors the tag's argument, so a project running two admin sites can point each at its own server::

class InternalAdminSite(SidebarAdminSite):
    sidebar_namespace = "internal-agent"

Server-side tools

shell.*

query_model

query_model(
    app_label: str,
    model: str,
    filter: dict[str, Any] | None = None,
    exclude: dict[str, Any] | None = None,
    order_by: list[str] | None = None,
    select_related: list[str] | None = None,
    prefetch_related: list[str] | None = None,
    fields: list[str] | None = None,
    limit: int = 50,
    offset: int = 0,
) -> list[dict[str, Any]]

Query a Django model and return matching rows as JSON-safe dicts.

filter and exclude accept ORM lookup kwargs (e.g. {"email__icontains": "@foo"}). fields projects via .values(); if omitted, every concrete field is returned. limit is hard-capped at 1000 to keep responses bounded. Sensitive fields (name matching the SHELL_FIELD_REDACTION denylist) are redacted.

get_model_instance

get_model_instance(
    app_label: str,
    model: str,
    pk: Any,
    select_related: list[str] | None = None,
    fields: list[str] | None = None,
) -> dict[str, Any] | None

Fetch a single row by primary key. Returns None when not found.

Sensitive fields (name matching the SHELL_FIELD_REDACTION denylist) are redacted before the row is returned.

count_model

count_model(
    app_label: str,
    model: str,
    filter: dict[str, Any] | None = None,
    exclude: dict[str, Any] | None = None,
) -> int

Return the row count for a model, optionally filtered.

inspect_model_schema

inspect_model_schema(app_label: str, model: str) -> dict[str, Any]

Return a JSON-safe description of a model's schema.

Includes concrete fields with types, nullability, relations, indexes, db_table, and Meta ordering — a good first step before writing queries.

introspect.*

list_installed_apps

list_installed_apps() -> list[dict[str, Any]]

Return the configured Django apps with labels, names, and model counts.

list_models

list_models(app_label: str | None = None) -> list[dict[str, Any]]

List installed Django models, optionally filtered to one app.

Each entry carries the app label, model name, DB table, and Meta-derived flags. Use inspect_model_schema for the full field-level shape.

list_urls

list_urls(prefix: str | None = None) -> list[dict[str, Any]]

Walk the root URL configuration and return every registered route.

Each entry includes the rendered pattern, view identifier, and URL name. prefix filters by string-containment against the pattern.

list_signals

list_signals() -> list[dict[str, Any]]

Enumerate Django's built-in signals and their connected receivers.

Returns one row per signal with the count and identifier of each connected receiver. Custom third-party signals are not enumerated — there is no central registry for them.

get_settings_summary

get_settings_summary() -> dict[str, Any]

Return a curated, JSON-safe subset of Django settings.

Sensitive keys (SECRET_KEY, DB passwords, raw OPTIONS) are excluded or redacted, so the result is safe to surface to an agent.

list_admin_models

list_admin_models() -> list[dict[str, Any]]

List every model registered with the default admin site.

Each entry carries the model's admin metadata (list_display, list_filter, search_fields) and the reverse-resolved admin URLs (changelist + add) so the agent can navigate without guessing URL shapes. Works for both vanilla ModelAdmin and subclasses (Unfold) because every attribute is read defensively.

inspect_modeladmin

inspect_modeladmin(app_label: str, model: str) -> dict[str, Any]

Describe the ModelAdmin registered for a model.

Reads options via getattr so it transparently surfaces both standard Django options and the additive attributes that subclasses (Unfold) add. Raises LookupError if the model is not registered.