Metadata-Version: 2.5
Name: djangorestframework-pydantic-ai
Version: 0.31.0
Summary: Expose djangorestframework-services services and selectors as a Pydantic-AI toolset.
Project-URL: Homepage, https://github.com/Artui/djangorestframework-pydantic-ai
Project-URL: Repository, https://github.com/Artui/djangorestframework-pydantic-ai
Project-URL: Issues, https://github.com/Artui/djangorestframework-pydantic-ai/issues
Author-email: Artur Veres <artur8118@gmail.com>
License: MIT
License-File: LICENSE
Keywords: agent,ai,django,drf,llm,pydantic-ai,rest-framework,tools
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: djangorestframework-services>=0.54.0
Requires-Dist: djangorestframework>=3.14
Requires-Dist: pydantic-ai-slim<3,>=2.16
Provides-Extra: filter
Requires-Dist: django-filter>=23; extra == 'filter'
Description-Content-Type: text/markdown

# djangorestframework-pydantic-ai

[![CI](https://github.com/Artui/djangorestframework-pydantic-ai/workflows/tests/badge.svg)](https://github.com/Artui/djangorestframework-pydantic-ai/actions/workflows/tests.yml)
[![PyPI](https://img.shields.io/pypi/v/djangorestframework-pydantic-ai.svg)](https://pypi.org/project/djangorestframework-pydantic-ai/)
[![Python versions](https://img.shields.io/pypi/pyversions/djangorestframework-pydantic-ai.svg)](https://pypi.org/project/djangorestframework-pydantic-ai/)
[![Django versions](https://img.shields.io/pypi/djversions/djangorestframework-pydantic-ai.svg)](https://pypi.org/project/djangorestframework-pydantic-ai/)
[![Docs](https://img.shields.io/badge/docs-artui.github.io-blue.svg)](https://artui.github.io/djangorestframework-pydantic-ai/)
[![Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Artui/djangorestframework-pydantic-ai/gh-pages/coverage.json)](https://github.com/Artui/djangorestframework-pydantic-ai/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/djangorestframework-pydantic-ai.svg)](LICENSE)

Expose [`djangorestframework-services`](https://github.com/Artui/djangorestframework-services)
services and selectors as a [Pydantic-AI](https://ai.pydantic.dev) toolset, so a
plain `pydantic_ai.Agent` can call them as tools — **no MCP server and no AG-UI
bridge** in the path.

Every tool call routes through drf-services' transport-neutral surface
(`dispatch_spec` plus its off-HTTP helpers), so a tool call runs the same input
validation, the same `permission_classes` — both class-level `has_permission`
and object-level `has_object_permission` on the resolved row — and the same
serializer rendering your DRF views apply, just without the HTTP hop.

## Install

```bash
pip install djangorestframework-pydantic-ai
```

It depends only on `djangorestframework-services` and `pydantic-ai-slim`. A model
provider is pulled in separately, the usual Pydantic-AI way (e.g.
`pip install "pydantic-ai-slim[anthropic]"`).

## Quickstart

```python
from pydantic_ai import Agent
from rest_framework_pydantic_ai import AgentDeps, SpecToolset

toolset = SpecToolset(
    {
        "list_orders": orders_selector_spec,  # SelectorSpec -> read-only tool
        "create_order": create_order_spec,  # ServiceSpec  -> mutation tool
    }
)

agent = Agent("anthropic:claude-opus-4-8", deps_type=AgentDeps, toolsets=[toolset])

result = await agent.run(
    "create an order of 3 widgets",
    deps=AgentDeps(user=request.user),
)
```

The agent acts as `deps.user`: each call builds an off-HTTP request/view context,
**enforces the spec's `permission_classes`** (class- and object-level),
dispatches the spec, and renders the result through the spec's serializer. List
selectors gain `page` / `limit` / `order` tool args, and return **one page** —
`{"items": [...], "page": 1, "totalPages": N, "hasNext": bool}` — so a model
reading a collection can tell whether it saw all of it.

Failures map onto the model loop so the agent self-corrects: invalid input, a bad
`page` / `limit` / `order` value, and unexpected (hallucinated) arguments come
back as `ModelRetry`; a business error or missing row becomes a readable
`ToolFailed`, which the model sees as a failed call rather than a successful one
carrying prose, and a call an `Affordance` refuses names the rule as well as the
reason (`The books are closed. (code: books_closed)`); a denied permission raises `PermissionDenied`, which aborts
the run under a plain `pydantic_ai.Agent`. A host that installs a tool-failure
policy — `django-pydantic-agent`'s `build_agent` does by default — turns that
denial into a failed-tool result instead, so the run continues; the call is
still denied either way. Unexpected arguments are **rejected by default** — pass
`unknown_arguments=` to `SpecToolset` (`IGNORE` / `PASSTHROUGH`) to change that.

A tool whose `Affordance` condition is unmet right now, such as posting to a closed
period, is left out of that step's tool list, and the step's instructions name it
with its reason so the model can tell the user why. Permissions do not filter the
list: a denied tool is still offered, and the denial comes on the call.

See the [documentation](https://artui.github.io/djangorestframework-pydantic-ai/)
for the full reference.

## License

MIT
