Metadata-Version: 2.4
Name: django-ag-ui
Version: 0.16.0
Summary: Django ↔ Pydantic-AI ↔ AG-UI integration: async view, tool registry, audit logger.
Project-URL: Homepage, https://github.com/Artui/django-ag-ui
Project-URL: Repository, https://github.com/Artui/django-ag-ui
Project-URL: Issues, https://github.com/Artui/django-ag-ui/issues
Author-email: Artur Veres <artur8118@gmail.com>
License: MIT
License-File: LICENSE
Keywords: ag-ui,agent,ai,django,llm,pydantic-ai
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: Django :: 5.2
Classifier: Framework :: Django :: 6.0
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: django>=4.2
Requires-Dist: pydantic-ai-slim[ag-ui]<3,>=2
Provides-Extra: anthropic
Requires-Dist: pydantic-ai-slim[anthropic]<3,>=2; extra == 'anthropic'
Provides-Extra: drf-mcp
Requires-Dist: djangorestframework-mcp-server<0.12,>=0.9; extra == 'drf-mcp'
Provides-Extra: google
Requires-Dist: pydantic-ai-slim[google]<3,>=2; extra == 'google'
Provides-Extra: openai
Requires-Dist: pydantic-ai-slim[openai]<3,>=2; extra == 'openai'
Provides-Extra: spec-tools
Requires-Dist: djangorestframework-pydantic-ai<0.6,>=0.5; extra == 'spec-tools'
Description-Content-Type: text/markdown

# django-ag-ui

[![CI](https://github.com/Artui/django-ag-ui/workflows/tests/badge.svg)](https://github.com/Artui/django-ag-ui/actions/workflows/tests.yml)
[![PyPI](https://img.shields.io/pypi/v/django-ag-ui.svg)](https://pypi.org/project/django-ag-ui/)
[![Python versions](https://img.shields.io/pypi/pyversions/django-ag-ui.svg)](https://pypi.org/project/django-ag-ui/)
[![Django versions](https://img.shields.io/pypi/djversions/django-ag-ui.svg)](https://pypi.org/project/django-ag-ui/)
[![Docs](https://img.shields.io/badge/docs-artui.github.io-blue.svg)](https://artui.github.io/django-ag-ui/)
[![Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Artui/django-ag-ui/gh-pages/coverage.json)](https://github.com/Artui/django-ag-ui/actions/workflows/tests.yml)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![License](https://img.shields.io/pypi/l/django-ag-ui.svg)](LICENSE)

Wire a [Pydantic-AI](https://ai.pydantic.dev) agent into any Django project and
speak the [AG-UI](https://docs.ag-ui.com) protocol to a browser — a streaming
agent endpoint, a typed tool registry, and the plumbing in between. No admin
specifics; that lives in the downstream
[`django-admin-agent`](https://github.com/Artui/django-admin-agent), and the
browser half is
[`@artooi/ag-ui-web-component`](https://github.com/Artui/ag-ui-web-component).

- **Async AG-UI endpoint** — `DjangoAGUIView` wraps Pydantic-AI's `AGUIAdapter`
  and returns a `StreamingHttpResponse` of AG-UI events (SSE). Conversation
  state rides in each request, so there's no cross-request session store and
  multi-worker deployments are safe by default.
- **Typed tool registry** — register plain callables with `@tool`; JSON Schema
  is derived from their signatures. `destructive=` / `category=` / `confirm=` /
  `summary=` metadata surface as `x-destructive` / `x-category` / `x-confirm` /
  `x-summary` extensions for client-side gating.
- **Configurable agent** — `AgentConfig` + the `DJANGO_AG_UI` settings cover the
  model, `MODEL_SETTINGS`, `RETRIES`, external `TOOLSETS` / `CAPABILITIES`, an
  explicit `API_KEY` / `PROVIDER` credential path, and an `AGENT_FACTORY` escape
  hatch for full control of construction.
- **Authentication hooks** — `require_authenticated=True` fails closed (`401`)
  for anonymous requests, and a `get_user(request)` hook establishes the user
  tools, the drf-mcp bridge, and conversation ownership act as.
- **One-object mounting** — an `AGUIServer(registry, …)` config object exposing a
  namespaced `.urls`, mounted the `admin.site` way with
  `path("agent/", server.urls)`. It builds the agent view and every sub-view from
  the registry passed **once**, and forwards one auth policy to all of them.
- **Skills** — a `SkillRegistry` / `SkillSpec` catalog of pre-defined prompts
  served at `<prefix>skills/` (via `AGUIServer(..., skills=...)`), surfaced by the
  web component as chips and a `/`-command palette.
- **Tool metadata catalog** — a read-only `ToolsView` served at `<prefix>tools/`
  (mounted automatically by `AGUIServer`), giving the web component
  (`data-tools-url`) friendly card labels for server-side tools whose schema never
  reaches the browser.
- **Audit boundary** — an `AuditLogger` Protocol (`Null` / `Logging` shipped,
  pluggable by dotted path) records every server-side tool call.
- **Opt-in conversation persistence** — a `ConversationStore` Protocol with a
  no-op default, a session-backed store, and an abstract model-backed base.
- **Thread history** — the store can `list` and `rename` a user's threads, and a
  `ThreadsView` served at `<prefix>threads/` (mounted by `AGUIServer` when a store
  is active) backs a chat-history drawer (owner-scoped GET list / GET messages / PATCH
  rename / DELETE). An opt-in `django_ag_ui.contrib.store` app ships a ready-made
  durable model + `DefaultConversationStore` (add it to `INSTALLED_APPS` and
  `migrate`); the base package still ships no model.
- **File uploads** — an `AttachmentStore` Protocol (owner-scoped, off by default)
  with an `AttachmentsView` served at `<prefix>attachments/` (mounted by
  `AGUIServer` when a store is active; server-validated POST upload / owner-checked
  GET download / DELETE). Uploads travel as lightweight refs, and a per-request
  `read_attachment` tool lets the agent read the bytes server-side. The same
  `contrib.store` app ships a `Storage`-backed `DefaultAttachmentStore`.
- **Voice input** — a `TranscriptionBackend` Protocol (off by default) with a
  `TranscribeView` served at `<prefix>transcribe/` (mounted by `AGUIServer` when a
  backend is active; multipart audio in, `{"text"}` out). An
  opt-in `OpenAITranscriptionBackend` works against any OpenAI-compatible
  `/audio/transcriptions` endpoint (the `[openai]` extra).
- **Model reasoning** — when a reasoning model is configured to think (via
  `MODEL_SETTINGS`), its chain-of-thought streams to the client as standard
  AG-UI reasoning events (pure pass-through); `FORWARD_REASONING = False` keeps
  it server-side.
- **Reach external tools** — compose any Pydantic-AI toolset, including an
  in-process [`drf-mcp`](https://github.com/Artui/djangorestframework-mcp-server)
  bridge (the `[drf-mcp]` extra) so the agent can query DRF-exposed data.
- **drf-services specs as tools, no MCP hop** — point `SERVICE_SPECS` at a
  `name → spec` mapping and the agent calls them in-process via
  [`djangorestframework-pydantic-ai`](https://github.com/Artui/djangorestframework-pydantic-ai)'s
  `SpecCapability` (the `[spec-tools]` extra) — permission-checked, acting as the
  logged-in user, with the spec conventions taught to the model.
- **100% test coverage**, type-checked, Python 3.10–3.14, Django 4.2–6.0.

📖 **Full documentation:** <https://artui.github.io/django-ag-ui/>

```bash
pip install "django-ag-ui[anthropic]"   # or [openai], or [google]
# or, with uv:
uv add "django-ag-ui[anthropic]"
```

> The core dep is `pydantic-ai-slim[ag-ui]`, which ships no model-provider
> library — pick one via a provider extra (`anthropic` / `openai` / `google`).

> **ASGI required.** The agent endpoint streams Server-Sent Events, which the
> sync WSGI worker can't serve — deploy under Daphne / Uvicorn.

---

## Quick start

Register a read-only tool, mount the endpoint, and point a browser AG-UI client
at it.

```python
# tools.py
from django_ag_ui import ToolRegistry, tool

registry = ToolRegistry()


@tool(registry)
def count_active_users() -> int:
    """How many users are currently active."""
    from django.contrib.auth import get_user_model

    return get_user_model().objects.filter(is_active=True).count()
```

```python
# urls.py
from django.urls import path

from django_ag_ui import AGUIServer

from .tools import registry

urlpatterns = [
    path("agent/", AGUIServer(registry).urls),
]
```

```python
# settings.py
DJANGO_AG_UI = {
    "MODEL": "anthropic:claude-sonnet-4.6",   # any Pydantic-AI model string
    # "API_KEY": os.environ["ANTHROPIC_API_KEY"],  # else inferred from env
    # "MODEL_SETTINGS": {"temperature": 0.2},
    # "AUDIT_LOGGER": "django_ag_ui.LoggingAuditLogger",
    # "CONVERSATION_STORE": "django_ag_ui.DjangoSessionConversationStore",
}
```

`POST`ing an AG-UI `RunAgentInput` to `/agent/` now streams the agent's run.
Frontend-declared tools in the request are merged into the agent's catalog
automatically; server-side tools run in-process. See the
[docs](https://artui.github.io/django-ag-ui/) for the full settings reference,
the persistence stores, and the `drf-mcp` bridge.

## License

MIT — see [LICENSE](LICENSE).
