Skip to content

Commit 4b70e4f

Browse files
authored
Merge pull request #22 from vstorm-co/feat/guardrails-capabilities
feat: migrate to capabilities, add build-in guardrails, rename from pydantic-ai-middleware to pydantic-ai-shields
2 parents 398719f + 3a4e96e commit 4b70e4f

File tree

138 files changed

+3068
-23263
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

138 files changed

+3068
-23263
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
run: uv run pyright
5858

5959
- name: MyPy
60-
run: uv run mypy src/pydantic_ai_middleware tests
60+
run: uv run mypy src/pydantic_ai_shields tests
6161

6262
test:
6363
name: Test Python ${{ matrix.python-version }}

.github/workflows/publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
environment:
1212
name: pypi
13-
url: https://pypi.org/project/pydantic-ai-middleware/
13+
url: https://pypi.org/project/pydantic-ai-shields/
1414
permissions:
1515
id-token: write
1616

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
notes/
12
# Byte-compiled / optimized / DLL files
23
__pycache__/
34
*.py[cod]

AGENTS.md

Lines changed: 24 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,83 +4,50 @@ Instructions for AI coding assistants working on this repository.
44

55
## Project Overview
66

7-
**pydantic-ai-middleware** is a simple middleware library for [pydantic-ai](https://ai.pydantic.dev/) agents. It provides clean before/after hooks at every lifecycle stage without imposing a guardrails structure - you decide what to do (logging, guardrails, metrics, transformations).
7+
**pydantic-ai-shields** provides guardrail capabilities for [pydantic-ai](https://ai.pydantic.dev/) agents. Built on pydantic-ai's native capabilities API (v1.71+). No middleware wrappers — pure capabilities.
88

99
## Quick Reference
1010

1111
| Task | Command |
1212
|------|---------|
13-
| Install | `make install` |
14-
| Test | `make test` |
15-
| Test + Coverage | `uv run coverage run -m pytest && uv run coverage report` |
16-
| Lint | `uv run ruff check .` |
17-
| Format | `uv run ruff format .` |
18-
| Typecheck | `uv run pyright` and `uv run mypy .` |
19-
| All checks | `make all` |
20-
| Build docs | `make docs-serve` |
13+
| Test | `uv run pytest tests/ -v` |
14+
| Test + Coverage | `uv run coverage run -m pytest tests/ && uv run coverage report --fail-under=100` |
15+
| Lint | `uv run ruff check src/ tests/` |
16+
| Typecheck | `uv run pyright src/` |
2117

2218
## Architecture
2319

2420
```
25-
pydantic_ai_middleware/
26-
├── base.py # AgentMiddleware - base class with lifecycle hooks
27-
├── agent.py # MiddlewareAgent - wraps agents with middleware
28-
├── toolset.py # MiddlewareToolset - wraps toolsets for tool call interception
29-
├── decorators.py # @before_run, @after_run, etc. - function decorators
30-
├── exceptions.py # InputBlocked, ToolBlocked, OutputBlocked
31-
└── __init__.py # Public API exports
21+
src/pydantic_ai_shields/
22+
__init__.py — Package exports
23+
guardrails.py — 5 capability implementations + exceptions + CostInfo
24+
tests/
25+
test_guardrails.py — All tests
3226
```
3327

34-
### Key Design: Middleware Chain
28+
### Capabilities
3529

36-
Middleware executes in order for `before_*` hooks and reverse order for `after_*` hooks:
37-
38-
```python
39-
agent = MiddlewareAgent(
40-
agent=base_agent,
41-
middleware=[mw1, mw2, mw3],
42-
)
43-
# before_run: mw1 -> mw2 -> mw3 -> [Agent]
44-
# after_run: [Agent] -> mw3 -> mw2 -> mw1
45-
```
46-
47-
### Lifecycle Hooks
48-
49-
| Hook | When Called | Can Modify |
50-
|------|-------------|------------|
51-
| `before_run` | Before agent starts | Prompt |
52-
| `after_run` | After agent finishes | Output |
53-
| `before_model_request` | Before each model call | Messages |
54-
| `before_tool_call` | Before tool execution | Tool arguments |
55-
| `after_tool_call` | After tool execution | Tool result |
56-
| `on_error` | When error occurs | Exception |
30+
| Capability | Hooks Used | Purpose |
31+
|------------|-----------|---------|
32+
| `CostTracking` | `before_run`, `after_run` | Token/USD tracking, budget enforcement |
33+
| `ToolGuard` | `prepare_tools`, `before_tool_execute` | Block tools, require approval |
34+
| `InputGuard` | `before_run` | Validate user input |
35+
| `OutputGuard` | `after_run` | Validate model output |
36+
| `AsyncGuardrail` | `wrap_run` | Concurrent guardrail + LLM |
5737

5838
## Code Standards
5939

60-
- **Coverage**: 100% required - check with `uv run coverage report`
61-
- **Types**: Pyright and mypy - all functions need type annotations
62-
- **Style**: ruff handles formatting and linting
40+
- **Coverage**: 100% required
41+
- **Types**: Pyright strict on src/
42+
- **Style**: ruff for formatting and linting
6343

6444
## Testing
6545

66-
Tests are in `tests/` directory. Use pytest-asyncio for async tests:
67-
6846
```python
6947
from pydantic_ai import Agent
7048
from pydantic_ai.models.test import TestModel
71-
from pydantic_ai_middleware import MiddlewareAgent, AgentMiddleware
49+
from pydantic_ai_shields import CostTracking, ToolGuard
7250

73-
async def test_middleware():
74-
model = TestModel()
75-
model.custom_output_text = "test"
76-
agent = Agent(model, output_type=str)
77-
middleware_agent = MiddlewareAgent(agent, middleware=[...])
78-
result = await middleware_agent.run("test")
51+
agent = Agent(TestModel(), capabilities=[CostTracking()])
52+
result = await agent.run("test")
7953
```
80-
81-
## When Modifying
82-
83-
1. Run tests after changes: `make test`
84-
2. Check coverage stays at 100%
85-
3. Run `uv run pyright` for type errors
86-
4. Format with `uv run ruff format .`

0 commit comments

Comments
 (0)