agentharnessapi 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentharnessapi-0.1.0.dist-info/METADATA +854 -0
- agentharnessapi-0.1.0.dist-info/RECORD +124 -0
- agentharnessapi-0.1.0.dist-info/WHEEL +4 -0
- agentharnessapi-0.1.0.dist-info/entry_points.txt +2 -0
- agentharnessapi-0.1.0.dist-info/licenses/LICENSE +21 -0
- agenticapi/__init__.py +159 -0
- agenticapi/_compat.py +12 -0
- agenticapi/app.py +1716 -0
- agenticapi/application/__init__.py +11 -0
- agenticapi/application/pipeline.py +164 -0
- agenticapi/cli/__init__.py +0 -0
- agenticapi/cli/console.py +136 -0
- agenticapi/cli/dev.py +54 -0
- agenticapi/cli/eval.py +119 -0
- agenticapi/cli/init.py +237 -0
- agenticapi/cli/main.py +143 -0
- agenticapi/cli/replay.py +394 -0
- agenticapi/dependencies/__init__.py +56 -0
- agenticapi/dependencies/depends.py +81 -0
- agenticapi/dependencies/scanner.py +306 -0
- agenticapi/dependencies/solver.py +271 -0
- agenticapi/evaluation/__init__.py +52 -0
- agenticapi/evaluation/judges.py +322 -0
- agenticapi/evaluation/runner.py +413 -0
- agenticapi/exceptions.py +164 -0
- agenticapi/harness/__init__.py +107 -0
- agenticapi/harness/approval/__init__.py +23 -0
- agenticapi/harness/approval/notifiers.py +63 -0
- agenticapi/harness/approval/rules.py +76 -0
- agenticapi/harness/approval/workflow.py +306 -0
- agenticapi/harness/audit/__init__.py +30 -0
- agenticapi/harness/audit/exporters.py +200 -0
- agenticapi/harness/audit/recorder.py +177 -0
- agenticapi/harness/audit/sqlite_store.py +442 -0
- agenticapi/harness/audit/trace.py +59 -0
- agenticapi/harness/engine.py +514 -0
- agenticapi/harness/policy/__init__.py +59 -0
- agenticapi/harness/policy/autonomy_policy.py +360 -0
- agenticapi/harness/policy/base.py +143 -0
- agenticapi/harness/policy/budget_policy.py +345 -0
- agenticapi/harness/policy/code_policy.py +161 -0
- agenticapi/harness/policy/data_policy.py +237 -0
- agenticapi/harness/policy/evaluator.py +271 -0
- agenticapi/harness/policy/pii_policy.py +460 -0
- agenticapi/harness/policy/pricing.py +179 -0
- agenticapi/harness/policy/prompt_injection_policy.py +347 -0
- agenticapi/harness/policy/resource_policy.py +138 -0
- agenticapi/harness/policy/runtime_policy.py +105 -0
- agenticapi/harness/sandbox/__init__.py +50 -0
- agenticapi/harness/sandbox/base.py +105 -0
- agenticapi/harness/sandbox/monitors.py +184 -0
- agenticapi/harness/sandbox/process.py +236 -0
- agenticapi/harness/sandbox/static_analysis.py +288 -0
- agenticapi/harness/sandbox/validators.py +166 -0
- agenticapi/interface/__init__.py +65 -0
- agenticapi/interface/a2a/__init__.py +18 -0
- agenticapi/interface/a2a/capability.py +93 -0
- agenticapi/interface/a2a/protocol.py +83 -0
- agenticapi/interface/a2a/trust.py +122 -0
- agenticapi/interface/approval_registry.py +167 -0
- agenticapi/interface/compat/__init__.py +24 -0
- agenticapi/interface/compat/fastapi.py +84 -0
- agenticapi/interface/compat/mcp.py +188 -0
- agenticapi/interface/compat/rest.py +211 -0
- agenticapi/interface/endpoint.py +84 -0
- agenticapi/interface/htmx.py +130 -0
- agenticapi/interface/intent.py +685 -0
- agenticapi/interface/response.py +276 -0
- agenticapi/interface/session.py +201 -0
- agenticapi/interface/stream.py +688 -0
- agenticapi/interface/stream_store.py +277 -0
- agenticapi/interface/tasks.py +90 -0
- agenticapi/interface/transports/__init__.py +0 -0
- agenticapi/interface/transports/ndjson.py +201 -0
- agenticapi/interface/transports/sse.py +231 -0
- agenticapi/interface/upload.py +54 -0
- agenticapi/mesh/__init__.py +16 -0
- agenticapi/mesh/context.py +125 -0
- agenticapi/mesh/mesh.py +176 -0
- agenticapi/observability/__init__.py +80 -0
- agenticapi/observability/metrics.py +340 -0
- agenticapi/observability/propagation.py +131 -0
- agenticapi/observability/semconv.py +115 -0
- agenticapi/observability/tracing.py +285 -0
- agenticapi/openapi.py +431 -0
- agenticapi/ops/__init__.py +10 -0
- agenticapi/ops/base.py +146 -0
- agenticapi/params.py +40 -0
- agenticapi/py.typed +0 -0
- agenticapi/routing.py +136 -0
- agenticapi/runtime/__init__.py +50 -0
- agenticapi/runtime/code_cache.py +286 -0
- agenticapi/runtime/code_generator.py +206 -0
- agenticapi/runtime/context.py +149 -0
- agenticapi/runtime/envelope.py +195 -0
- agenticapi/runtime/llm/__init__.py +35 -0
- agenticapi/runtime/llm/anthropic.py +234 -0
- agenticapi/runtime/llm/base.py +187 -0
- agenticapi/runtime/llm/gemini.py +317 -0
- agenticapi/runtime/llm/mock.py +276 -0
- agenticapi/runtime/llm/openai.py +234 -0
- agenticapi/runtime/llm/retry.py +96 -0
- agenticapi/runtime/memory/__init__.py +36 -0
- agenticapi/runtime/memory/base.py +250 -0
- agenticapi/runtime/memory/sqlite_store.py +321 -0
- agenticapi/runtime/prompts/__init__.py +11 -0
- agenticapi/runtime/prompts/code_generation.py +209 -0
- agenticapi/runtime/prompts/intent_parsing.py +113 -0
- agenticapi/runtime/tools/__init__.py +28 -0
- agenticapi/runtime/tools/base.py +70 -0
- agenticapi/runtime/tools/cache.py +152 -0
- agenticapi/runtime/tools/database.py +155 -0
- agenticapi/runtime/tools/decorator.py +273 -0
- agenticapi/runtime/tools/http_client.py +151 -0
- agenticapi/runtime/tools/queue.py +143 -0
- agenticapi/runtime/tools/registry.py +127 -0
- agenticapi/security.py +319 -0
- agenticapi/testing/__init__.py +29 -0
- agenticapi/testing/agent_test_case.py +151 -0
- agenticapi/testing/assertions.py +100 -0
- agenticapi/testing/benchmark.py +144 -0
- agenticapi/testing/fixtures.py +64 -0
- agenticapi/testing/mocks.py +151 -0
- agenticapi/types.py +38 -0
|
@@ -0,0 +1,854 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentharnessapi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agent-native web framework with harness engineering for Python
|
|
5
|
+
Project-URL: Homepage, https://github.com/shibuiwilliam/AgenticAPI
|
|
6
|
+
Project-URL: Documentation, https://shibuiwilliam.github.io/AgenticAPI/
|
|
7
|
+
Project-URL: Repository, https://github.com/shibuiwilliam/AgenticAPI
|
|
8
|
+
Project-URL: Issues, https://github.com/shibuiwilliam/AgenticAPI/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/shibuiwilliam/AgenticAPI/blob/main/IMPLEMENTATION_LOG.md
|
|
10
|
+
Author-email: shibuiwilliam <shibuiyusuke@gmail.com>
|
|
11
|
+
License: Apache-2.0
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: agent,ai,async,fastapi,framework,harness,llm,openapi
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Framework :: AsyncIO
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.13
|
|
23
|
+
Requires-Dist: anthropic>=0.89.0
|
|
24
|
+
Requires-Dist: google-genai>=1.70.0
|
|
25
|
+
Requires-Dist: httpx>=0.28.1
|
|
26
|
+
Requires-Dist: openai>=2.30.0
|
|
27
|
+
Requires-Dist: pydantic>=2.12.5
|
|
28
|
+
Requires-Dist: python-multipart>=0.0.20
|
|
29
|
+
Requires-Dist: starlette>=1.0.0
|
|
30
|
+
Requires-Dist: structlog>=25.5.0
|
|
31
|
+
Provides-Extra: mcp
|
|
32
|
+
Requires-Dist: mcp>=1.27.0; extra == 'mcp'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# AgenticAPI
|
|
36
|
+
|
|
37
|
+
**The agent-native web framework for Python.** Build APIs where endpoints understand natural language, generate code on the fly, and execute it safely behind a multi-layered harness -- all with the developer ergonomics you know from FastAPI.
|
|
38
|
+
|
|
39
|
+
[](https://www.python.org/downloads/)
|
|
40
|
+
[](./LICENSE)
|
|
41
|
+
[]()
|
|
42
|
+
[](./examples)
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from agenticapi import AgenticApp, AgentResponse, Intent
|
|
46
|
+
from agenticapi.runtime.context import AgentContext
|
|
47
|
+
|
|
48
|
+
app = AgenticApp(title="Hello Agent")
|
|
49
|
+
|
|
50
|
+
@app.agent_endpoint(name="greeter", autonomy_level="auto")
|
|
51
|
+
async def greeter(intent: Intent, context: AgentContext) -> AgentResponse:
|
|
52
|
+
return AgentResponse(
|
|
53
|
+
result={"message": f"Hello! You said: {intent.raw}"},
|
|
54
|
+
reasoning="Direct greeting response",
|
|
55
|
+
)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
agenticapi dev --app myapp:app
|
|
60
|
+
curl -X POST http://127.0.0.1:8000/agent/greeter \
|
|
61
|
+
-H "Content-Type: application/json" \
|
|
62
|
+
-d '{"intent": "Hello, how are you?"}'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
You instantly get Swagger UI at `/docs`, ReDoc at `/redoc`, an OpenAPI 3.1 spec at `/openapi.json`, and `/health` + `/capabilities` endpoints -- no extra wiring.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Table of Contents
|
|
70
|
+
|
|
71
|
+
- [AgenticAPI](#agenticapi)
|
|
72
|
+
- [Table of Contents](#table-of-contents)
|
|
73
|
+
- [Why AgenticAPI?](#why-agenticapi)
|
|
74
|
+
- [Installation](#installation)
|
|
75
|
+
- [Quick Start](#quick-start)
|
|
76
|
+
- [Quick Tour](#quick-tour)
|
|
77
|
+
- [1. Minimal endpoint (no LLM needed)](#1-minimal-endpoint-no-llm-needed)
|
|
78
|
+
- [2. With an LLM and the safety harness](#2-with-an-llm-and-the-safety-harness)
|
|
79
|
+
- [3. Typed intents](#3-typed-intents)
|
|
80
|
+
- [4. Dependency injection](#4-dependency-injection)
|
|
81
|
+
- [5. Programmatic usage (no HTTP)](#5-programmatic-usage-no-http)
|
|
82
|
+
- [How It Maps to FastAPI](#how-it-maps-to-fastapi)
|
|
83
|
+
- [Features at a Glance](#features-at-a-glance)
|
|
84
|
+
- [Safety: The Harness System](#safety-the-harness-system)
|
|
85
|
+
- [Policies](#policies)
|
|
86
|
+
- [Agent Memory](#agent-memory)
|
|
87
|
+
- [Code Cache](#code-cache)
|
|
88
|
+
- [Streaming](#streaming)
|
|
89
|
+
- [Cost Budgeting](#cost-budgeting)
|
|
90
|
+
- [Sandbox \& Audit](#sandbox--audit)
|
|
91
|
+
- [Native Function Calling](#native-function-calling)
|
|
92
|
+
- [Multi-Agent Orchestration](#multi-agent-orchestration)
|
|
93
|
+
- [Authentication](#authentication)
|
|
94
|
+
- [LLM Backends](#llm-backends)
|
|
95
|
+
- [Tools](#tools)
|
|
96
|
+
- [Custom Responses, HTMX \& File Handling](#custom-responses-htmx--file-handling)
|
|
97
|
+
- [MCP, REST Compatibility \& Middleware](#mcp-rest-compatibility--middleware)
|
|
98
|
+
- [Observability](#observability)
|
|
99
|
+
- [Extensions](#extensions)
|
|
100
|
+
- [Examples](#examples)
|
|
101
|
+
- [CLI Reference](#cli-reference)
|
|
102
|
+
- [Development](#development)
|
|
103
|
+
- [Common Commands](#common-commands)
|
|
104
|
+
- [Running Tests](#running-tests)
|
|
105
|
+
- [Code Quality](#code-quality)
|
|
106
|
+
- [Pre-commit Hooks](#pre-commit-hooks)
|
|
107
|
+
- [Project Structure](#project-structure)
|
|
108
|
+
- [Requirements](#requirements)
|
|
109
|
+
- [Documentation](#documentation)
|
|
110
|
+
- [Where everything lives](#where-everything-lives)
|
|
111
|
+
- [Contributing](#contributing)
|
|
112
|
+
- [License](#license)
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Why AgenticAPI?
|
|
117
|
+
|
|
118
|
+
> **FastAPI is for type-safe REST APIs. AgenticAPI is for harnessed agent APIs.**
|
|
119
|
+
|
|
120
|
+
Traditional web frameworks expect structured request bodies. AgenticAPI endpoints accept natural-language **intents** instead. Under the hood an LLM can parse those intents into Pydantic schemas, choose tools via native function calling, or even generate Python code -- and a multi-layered **harness** evaluates, sandboxes, budgets, and audits every execution before it ever touches your data.
|
|
121
|
+
|
|
122
|
+
The best part: **you can use it with or without an LLM.**
|
|
123
|
+
|
|
124
|
+
- **Without an LLM** -- a clean decorator-based ASGI framework with FastAPI-like ergonomics: dependency injection, `response_model` validation, authentication, OpenAPI docs, HTMX support, file upload/download, streaming (SSE + NDJSON), background tasks, and more.
|
|
125
|
+
- **With an LLM** -- a complete agent execution platform: typed structured outputs, native function calling across Anthropic/OpenAI/Gemini with retry and backoff, policy enforcement (code, data, resources, budget, prompt-injection, PII), AST analysis, process sandboxing, approval workflows, persistent audit trails, agent memory, code caching, autonomy escalation, multi-agent orchestration, and full observability.
|
|
126
|
+
|
|
127
|
+
Either way you get **27 runnable examples** to copy from, **1,310 passing tests** that prove every feature works, and a production-ready observability story (OpenTelemetry spans, Prometheus metrics, W3C trace propagation -- all optional, all graceful no-ops when unused).
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Installation
|
|
132
|
+
|
|
133
|
+
**Python 3.13+** is required. The framework uses `match`, `type` aliases, `StrEnum`, and other modern features.
|
|
134
|
+
|
|
135
|
+
For development:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
git clone https://github.com/shibuiwilliam/AgenticAPI.git
|
|
139
|
+
cd AgenticAPI
|
|
140
|
+
uv sync --group dev # or: pip install -e ".[dev]"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Optional extras:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pip install agenticapi[mcp] # MCP server support
|
|
147
|
+
pip install agenticapi-claude-agent-sdk # Full Claude Agent SDK loop (separate package)
|
|
148
|
+
|
|
149
|
+
# Observability -- all optional, all graceful no-ops when missing
|
|
150
|
+
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
|
|
151
|
+
pip install prometheus-client
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Quick Start
|
|
157
|
+
|
|
158
|
+
The fastest way to create a new project:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
agenticapi init my-agent
|
|
162
|
+
cd my-agent
|
|
163
|
+
agenticapi dev --app app:app
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
This generates a ready-to-run project with a handler, tools, harness, and an eval set -- all wired together. It works immediately with `MockBackend` (no API key needed). Set `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `GOOGLE_API_KEY` to switch to a real provider.
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
my-agent/
|
|
170
|
+
app.py # AgenticApp with one endpoint + harness + tools
|
|
171
|
+
tools.py # Two @tool-decorated functions
|
|
172
|
+
evals/golden.yaml # Three eval cases for regression testing
|
|
173
|
+
.env.example # API key placeholders
|
|
174
|
+
pyproject.toml # Dependencies
|
|
175
|
+
README.md # Run instructions + curl walkthrough
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Test it:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
curl -X POST http://localhost:8000/agent/ask \
|
|
182
|
+
-H "Content-Type: application/json" \
|
|
183
|
+
-d '{"intent": "hello world"}'
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Run evals:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
agenticapi eval --set evals/golden.yaml --app app:app
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Quick Tour
|
|
195
|
+
|
|
196
|
+
### 1. Minimal endpoint (no LLM needed)
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
from agenticapi import AgenticApp, AgentResponse, Intent
|
|
200
|
+
from agenticapi.runtime.context import AgentContext
|
|
201
|
+
|
|
202
|
+
app = AgenticApp(title="My Service")
|
|
203
|
+
|
|
204
|
+
@app.agent_endpoint(name="orders", autonomy_level="auto")
|
|
205
|
+
async def order_agent(intent: Intent, context: AgentContext) -> AgentResponse:
|
|
206
|
+
return AgentResponse(result={"order_count": 42})
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
agenticapi dev --app myapp:app
|
|
211
|
+
curl -X POST http://127.0.0.1:8000/agent/orders \
|
|
212
|
+
-H "Content-Type: application/json" \
|
|
213
|
+
-d '{"intent": "How many orders do we have?"}'
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Every app automatically registers `/health`, `/capabilities`, `/docs`, `/redoc`, and `/openapi.json`.
|
|
217
|
+
|
|
218
|
+
### 2. With an LLM and the safety harness
|
|
219
|
+
|
|
220
|
+
Add an LLM backend and harness engine to generate and safely execute code from natural language:
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
from agenticapi import AgenticApp, CodePolicy, DataPolicy, HarnessEngine
|
|
224
|
+
from agenticapi.runtime.llm.anthropic import AnthropicBackend
|
|
225
|
+
|
|
226
|
+
app = AgenticApp(
|
|
227
|
+
title="Harnessed Agent",
|
|
228
|
+
llm=AnthropicBackend(), # reads ANTHROPIC_API_KEY from env
|
|
229
|
+
harness=HarnessEngine(
|
|
230
|
+
policies=[
|
|
231
|
+
CodePolicy(denied_modules=["os", "subprocess"], deny_eval_exec=True),
|
|
232
|
+
DataPolicy(readable_tables=["orders", "products"], deny_ddl=True),
|
|
233
|
+
],
|
|
234
|
+
),
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
@app.agent_endpoint(name="analytics", autonomy_level="supervised")
|
|
238
|
+
async def analytics(intent, context):
|
|
239
|
+
pass # The harness pipeline takes over from here
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The pipeline: **parse intent -> generate code via LLM -> evaluate policies -> AST analysis -> approval check -> process sandbox -> monitors/validators -> audit trace -> response**.
|
|
243
|
+
|
|
244
|
+
### 3. Typed intents
|
|
245
|
+
|
|
246
|
+
Constrain the LLM's output to a Pydantic schema -- full validation before the handler runs:
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
from pydantic import BaseModel, Field
|
|
250
|
+
from agenticapi import Intent
|
|
251
|
+
|
|
252
|
+
class OrderSearch(BaseModel):
|
|
253
|
+
status: str | None = None
|
|
254
|
+
limit: int = Field(default=10, ge=1, le=100)
|
|
255
|
+
|
|
256
|
+
@app.agent_endpoint(name="orders.search")
|
|
257
|
+
async def search(intent: Intent[OrderSearch], context):
|
|
258
|
+
query = intent.params # already validated, fully typed, autocomplete works
|
|
259
|
+
return {"status": query.status, "limit": query.limit}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
See [example 17](./examples/17_typed_intents) for the full pattern.
|
|
263
|
+
|
|
264
|
+
### 4. Dependency injection
|
|
265
|
+
|
|
266
|
+
FastAPI-style `Depends()` with generator-based teardown:
|
|
267
|
+
|
|
268
|
+
```python
|
|
269
|
+
from agenticapi import Depends
|
|
270
|
+
|
|
271
|
+
async def get_db():
|
|
272
|
+
async with engine.connect() as conn:
|
|
273
|
+
yield conn # teardown after handler runs
|
|
274
|
+
|
|
275
|
+
@app.agent_endpoint(name="orders")
|
|
276
|
+
async def list_orders(intent, context, db=Depends(get_db)):
|
|
277
|
+
return {"orders": await db.fetch("SELECT * FROM orders")}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
See [example 14](./examples/14_dependency_injection) for nested deps, route-level deps, and `@tool`.
|
|
281
|
+
|
|
282
|
+
### 5. Programmatic usage (no HTTP)
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
response = await app.process_intent(
|
|
286
|
+
"Show me last month's orders",
|
|
287
|
+
endpoint_name="orders.query",
|
|
288
|
+
session_id="session-123",
|
|
289
|
+
)
|
|
290
|
+
print(response.result)
|
|
291
|
+
print(response.generated_code)
|
|
292
|
+
print(response.reasoning)
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## How It Maps to FastAPI
|
|
298
|
+
|
|
299
|
+
If you know FastAPI, you already know the patterns:
|
|
300
|
+
|
|
301
|
+
| FastAPI | AgenticAPI | Notes |
|
|
302
|
+
|---|---|---|
|
|
303
|
+
| `FastAPI()` | `AgenticApp()` | Main app, ASGI-compatible |
|
|
304
|
+
| `@app.get("/path")` | `@app.agent_endpoint(name=...)` | Endpoint registration |
|
|
305
|
+
| `APIRouter` | `AgentRouter` | Grouping with prefix and tags |
|
|
306
|
+
| `Request` | `Intent` / `Intent[T]` | Input (natural language instead of typed params) |
|
|
307
|
+
| `Response` | `AgentResponse` | Output with result, reasoning, trace |
|
|
308
|
+
| `BackgroundTasks` | `AgentTasks` | Post-response task execution |
|
|
309
|
+
| `Depends()` | `Depends()` | Dependency injection (same name, same shape) |
|
|
310
|
+
| `response_model=` | `response_model=` | Pydantic validation + OpenAPI schema |
|
|
311
|
+
| `app.add_middleware()` | `app.add_middleware()` | Starlette middleware (CORS, etc.) |
|
|
312
|
+
| `UploadFile` | `UploadedFiles` | File upload via multipart |
|
|
313
|
+
| `FileResponse` | `FileResult` | File download |
|
|
314
|
+
| `HTMLResponse` | `HTMLResult` | HTML response |
|
|
315
|
+
| Security schemes | `Authenticator` | API key, Bearer, Basic auth |
|
|
316
|
+
| `/docs` | `/docs` | Swagger UI (auto-generated) |
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Features at a Glance
|
|
321
|
+
|
|
322
|
+
| Category | What you get |
|
|
323
|
+
|---|---|
|
|
324
|
+
| **Agent endpoints** | Decorator-based registration, natural-language intents, routers with prefix/tags |
|
|
325
|
+
| **Typed intents** | Constrain LLM output to a Pydantic schema with `Intent[T]` -- full validation, IDE autocompletion |
|
|
326
|
+
| **Multi-LLM** | Anthropic Claude, OpenAI GPT, Google Gemini, deterministic Mock -- swap with one line |
|
|
327
|
+
| **Native function calling** | First-class `ToolCall` + `finish_reason` + `tool_choice` across every backend, with retry and backoff |
|
|
328
|
+
| **Multi-agent orchestration** | `AgentMesh` with `@mesh.role` / `@mesh.orchestrator`, budget propagation, cycle detection |
|
|
329
|
+
| **Safety harness** | 8 policy types, static AST analysis, process sandbox, monitors, validators, audit trail |
|
|
330
|
+
| **Prompt-injection & PII** | `PromptInjectionPolicy` detects injection attacks; `PIIPolicy` + `redact_pii` catch and mask sensitive data |
|
|
331
|
+
| **Persistent audit** | In-memory for dev or `SqliteAuditRecorder` for production -- stdlib only, zero new deps |
|
|
332
|
+
| **Cost budgeting** | Pre-call enforcement via `BudgetPolicy` and `PricingRegistry` with 4 independent scopes |
|
|
333
|
+
| **Agent memory** | `MemoryStore` with SQLite and in-memory backends -- persist facts, preferences, and conversation history |
|
|
334
|
+
| **Code cache** | `CodeCache` skips the LLM entirely when an identical intent has an approved cached answer |
|
|
335
|
+
| **Streaming** | `AgentStream` with SSE and NDJSON transports, mid-stream approval pauses, replay after completion |
|
|
336
|
+
| **Autonomy policy** | `AutonomyPolicy` with `EscalateWhen` rules for live escalation during agent execution |
|
|
337
|
+
| **Approval workflows** | Human-in-the-loop for sensitive operations with HTTP 202 + async resolve |
|
|
338
|
+
| **Authentication** | API key, Bearer token, Basic auth -- per-endpoint, per-router, or app-wide |
|
|
339
|
+
| **Dependency injection** | FastAPI-style `Depends()` with sync/async generators, caching, route-level deps |
|
|
340
|
+
| **Response validation** | Pydantic `response_model` validates handler returns and publishes the schema in OpenAPI |
|
|
341
|
+
| **Custom responses** | `HTMLResult`, `PlainTextResult`, `FileResult`, or any Starlette `Response` subclass |
|
|
342
|
+
| **HTMX support** | `HtmxHeaders` auto-injection, `htmx_response_headers()`, partial page updates |
|
|
343
|
+
| **File handling** | Upload via multipart, download via `FileResult`, streaming responses |
|
|
344
|
+
| **MCP support** | Expose endpoints as MCP tools for Claude Desktop, Cursor, and other LLM clients |
|
|
345
|
+
| **`@tool` decorator** | Turn plain functions into registered tools with auto-generated JSON schemas |
|
|
346
|
+
| **Project scaffolding** | `agenticapi init` generates a ready-to-run project with tools, harness, and evals |
|
|
347
|
+
| **Background tasks** | `AgentTasks` for post-response work (like FastAPI's `BackgroundTasks`) |
|
|
348
|
+
| **Middleware** | Full Starlette middleware (CORS, compression, custom) |
|
|
349
|
+
| **Dynamic pipelines** | Agent-level processing stages composed at runtime |
|
|
350
|
+
| **Agent-to-Agent** | Capability discovery, trust scoring, inter-agent communication |
|
|
351
|
+
| **Sessions** | Multi-turn conversations with context accumulation and TTL expiration |
|
|
352
|
+
| **REST compatibility** | Mount FastAPI inside AgenticAPI, or expose agent endpoints as REST routes |
|
|
353
|
+
| **Extensions** | Independent packages like `agenticapi-claude-agent-sdk` for heavyweight integrations |
|
|
354
|
+
| **Observability** | OpenTelemetry spans + Prometheus metrics + W3C trace propagation, graceful no-op when absent |
|
|
355
|
+
| **Eval harness** | Regression-test agent endpoints with deterministic assertion suites |
|
|
356
|
+
| **OpenAPI docs** | Auto-generated Swagger UI, ReDoc, and OpenAPI 3.1.0 schema |
|
|
357
|
+
| **ASGI-native** | Built on Starlette -- runs with uvicorn, Daphne, Hypercorn |
|
|
358
|
+
|
|
359
|
+
**Current scale:** 118 source modules, ~25,000 lines of code, **1,310 tests** (+38 in extensions), 27 runnable examples, 1 published extension.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Safety: The Harness System
|
|
364
|
+
|
|
365
|
+
Every piece of LLM-generated code passes through a multi-layered safety pipeline before it executes:
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
Generated Code
|
|
369
|
+
-> Policy Evaluation (Code, Data, Resource, Runtime, Budget, PromptInjection, PII)
|
|
370
|
+
-> Static AST Analysis (forbidden imports, eval/exec, file I/O, getattr)
|
|
371
|
+
-> Approval Check (human-in-the-loop for sensitive operations)
|
|
372
|
+
-> Process Sandbox (isolated subprocess with timeout + resource limits)
|
|
373
|
+
-> Post-Execution Monitors + Validators
|
|
374
|
+
-> Audit Trail Recording (in-memory or SQLite-backed)
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Policies
|
|
378
|
+
|
|
379
|
+
```python
|
|
380
|
+
from agenticapi import (
|
|
381
|
+
CodePolicy, DataPolicy, ResourcePolicy, RuntimePolicy,
|
|
382
|
+
BudgetPolicy, PricingRegistry, PromptInjectionPolicy, PIIPolicy,
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
CodePolicy(denied_modules=["os", "subprocess"], deny_eval_exec=True, max_code_lines=500)
|
|
386
|
+
DataPolicy(readable_tables=["orders"], deny_ddl=True)
|
|
387
|
+
ResourcePolicy(max_cpu_seconds=30, max_memory_mb=512)
|
|
388
|
+
RuntimePolicy(max_code_complexity=500)
|
|
389
|
+
BudgetPolicy(pricing=PricingRegistry.default(), max_per_request_usd=0.10)
|
|
390
|
+
PromptInjectionPolicy() # detects injection attacks in user input
|
|
391
|
+
PIIPolicy() # catches email, phone, SSN patterns
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Agent Memory
|
|
395
|
+
|
|
396
|
+
Agents can persist facts, preferences, and conversation history across sessions:
|
|
397
|
+
|
|
398
|
+
```python
|
|
399
|
+
from agenticapi import AgenticApp, SqliteMemoryStore
|
|
400
|
+
|
|
401
|
+
app = AgenticApp(
|
|
402
|
+
title="Personal Assistant",
|
|
403
|
+
memory=SqliteMemoryStore(path="./memory.sqlite"),
|
|
404
|
+
)
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Memories are typed (`MemoryKind`: fact, preference, conversation, system) and stored with timestamps for retrieval and relevance scoring. See [example 21](./examples/21_persistent_memory).
|
|
408
|
+
|
|
409
|
+
### Code Cache
|
|
410
|
+
|
|
411
|
+
Skip the LLM entirely when an identical intent already has an approved answer:
|
|
412
|
+
|
|
413
|
+
```python
|
|
414
|
+
from agenticapi import AgenticApp, InMemoryCodeCache
|
|
415
|
+
|
|
416
|
+
app = AgenticApp(title="Cached Agent", code_cache=InMemoryCodeCache())
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
See [example 24](./examples/24_code_cache).
|
|
420
|
+
|
|
421
|
+
### Streaming
|
|
422
|
+
|
|
423
|
+
Handlers can emit events over SSE or NDJSON, pause for mid-stream approval, and support replay after completion:
|
|
424
|
+
|
|
425
|
+
```python
|
|
426
|
+
@app.agent_endpoint(name="deploy", streaming="sse")
|
|
427
|
+
async def deploy(intent, context, stream: AgentStream):
|
|
428
|
+
await stream.emit(AgentEvent(kind="progress", data={"step": 1}))
|
|
429
|
+
decision = await stream.request_approval(reason="Continue deploy?")
|
|
430
|
+
await stream.emit(AgentEvent(kind="complete", data={"approved": decision}))
|
|
431
|
+
return {"status": "deployed"}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
See [example 20](./examples/20_streaming_release_control) for the full pattern with SSE, NDJSON, resume, and replay routes.
|
|
435
|
+
|
|
436
|
+
### Cost Budgeting
|
|
437
|
+
|
|
438
|
+
`BudgetPolicy` enforces cost ceilings **before** the LLM call with 4 independent scopes (per-request, per-session, per-user-per-day, per-endpoint-per-day). When a request would exceed any limit the harness raises `BudgetExceeded` (HTTP 402) **before any tokens are spent**. See [example 15](./examples/15_budget_policy).
|
|
439
|
+
|
|
440
|
+
### Sandbox & Audit
|
|
441
|
+
|
|
442
|
+
Generated code runs in an isolated subprocess with timeout, resource metrics, and stdout/stderr capture. Every execution is recorded as an `ExecutionTrace`. Choose `InMemoryAuditRecorder` for dev or `SqliteAuditRecorder` for production -- zero new dependencies (stdlib `sqlite3`). See [example 16](./examples/16_observability).
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Native Function Calling
|
|
447
|
+
|
|
448
|
+
All three LLM backends support native function calling with automatic retry and exponential backoff:
|
|
449
|
+
|
|
450
|
+
```python
|
|
451
|
+
from agenticapi import tool
|
|
452
|
+
from agenticapi.runtime.tools import ToolRegistry
|
|
453
|
+
from agenticapi.runtime.llm import AnthropicBackend, LLMPrompt, LLMMessage
|
|
454
|
+
|
|
455
|
+
@tool(description="Look up current weather for a city")
|
|
456
|
+
async def get_weather(city: str) -> dict:
|
|
457
|
+
return {"city": city, "temp": 22, "condition": "sunny"}
|
|
458
|
+
|
|
459
|
+
# The LLM decides when to call tools -- you get structured ToolCall objects back
|
|
460
|
+
backend = AnthropicBackend() # also OpenAIBackend(), GeminiBackend()
|
|
461
|
+
response = await backend.generate(
|
|
462
|
+
LLMPrompt(
|
|
463
|
+
system="You are a helpful assistant.",
|
|
464
|
+
messages=[LLMMessage(role="user", content="What's the weather in Tokyo?")],
|
|
465
|
+
tools=[get_weather.tool.definition.to_dict()],
|
|
466
|
+
tool_choice="auto", # "auto", "required", "none", or {"type": "tool", "name": "..."}
|
|
467
|
+
)
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
if response.finish_reason == "tool_calls":
|
|
471
|
+
for call in response.tool_calls:
|
|
472
|
+
print(f"Tool: {call.name}, Args: {call.arguments}")
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
Every backend automatically retries on transient errors (rate limits, timeouts, 5xx) with configurable `RetryConfig`. See [example 19](./examples/19_native_function_calling) for a multi-turn tool-use loop.
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## Multi-Agent Orchestration
|
|
480
|
+
|
|
481
|
+
Compose multiple agent roles into governed pipelines with `AgentMesh`. Budget, trace, and approval propagate across hops:
|
|
482
|
+
|
|
483
|
+
```python
|
|
484
|
+
from agenticapi import AgenticApp, AgentMesh
|
|
485
|
+
|
|
486
|
+
app = AgenticApp(title="Research Pipeline")
|
|
487
|
+
mesh = AgentMesh(app=app, name="research")
|
|
488
|
+
|
|
489
|
+
@mesh.role(name="researcher")
|
|
490
|
+
async def researcher(payload, ctx):
|
|
491
|
+
return {"topic": payload, "points": ["finding 1", "finding 2"]}
|
|
492
|
+
|
|
493
|
+
@mesh.role(name="reviewer")
|
|
494
|
+
async def reviewer(payload, ctx):
|
|
495
|
+
return {"approved": True, "feedback": "Looks good"}
|
|
496
|
+
|
|
497
|
+
@mesh.orchestrator(name="pipeline", roles=["researcher", "reviewer"], budget_usd=1.00)
|
|
498
|
+
async def pipeline(intent, mesh_ctx):
|
|
499
|
+
research = await mesh_ctx.call("researcher", intent.raw)
|
|
500
|
+
review = await mesh_ctx.call("reviewer", str(research))
|
|
501
|
+
return {"research": research, "review": review}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
curl -X POST http://localhost:8000/agent/pipeline \
|
|
506
|
+
-H "Content-Type: application/json" \
|
|
507
|
+
-d '{"intent": "quantum computing"}'
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
The mesh provides:
|
|
511
|
+
- **In-process routing** -- `MeshContext.call()` resolves roles locally (no HTTP overhead)
|
|
512
|
+
- **Budget propagation** -- sub-agent calls debit the orchestrator's ceiling
|
|
513
|
+
- **Cycle detection** -- role A calling role B calling role A raises `MeshCycleError`
|
|
514
|
+
- **Standalone endpoints** -- every role is also exposed at `/agent/{role_name}`
|
|
515
|
+
|
|
516
|
+
See [example 27](./examples/27_multi_agent_pipeline) for a 3-role research pipeline.
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## Authentication
|
|
521
|
+
|
|
522
|
+
```python
|
|
523
|
+
from agenticapi.security import APIKeyHeader, Authenticator, AuthUser
|
|
524
|
+
|
|
525
|
+
api_key = APIKeyHeader(name="X-API-Key")
|
|
526
|
+
|
|
527
|
+
async def verify(credentials):
|
|
528
|
+
if credentials.credentials == "secret-key":
|
|
529
|
+
return AuthUser(user_id="user-1", username="alice", roles=("admin",))
|
|
530
|
+
return None
|
|
531
|
+
|
|
532
|
+
auth = Authenticator(scheme=api_key, verify=verify)
|
|
533
|
+
|
|
534
|
+
@app.agent_endpoint(name="orders", auth=auth)
|
|
535
|
+
async def orders(intent, context):
|
|
536
|
+
print(context.user_id) # "user-1"
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Available schemes: `APIKeyHeader`, `APIKeyQuery`, `HTTPBearer`, `HTTPBasic`. See [example 9](./examples/09_auth_agent).
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
## LLM Backends
|
|
544
|
+
|
|
545
|
+
| Backend | Provider | Default Model | Env Variable | Function Calling | Retry |
|
|
546
|
+
|---|---|---|---|---|---|
|
|
547
|
+
| `AnthropicBackend` | Anthropic | `claude-sonnet-4-6` | `ANTHROPIC_API_KEY` | `tool_use` blocks | RateLimitError, Timeout, 5xx |
|
|
548
|
+
| `OpenAIBackend` | OpenAI | `gpt-5.4-mini` | `OPENAI_API_KEY` | `tool_calls` on message | RateLimitError, Timeout |
|
|
549
|
+
| `GeminiBackend` | Google | `gemini-2.5-flash` | `GOOGLE_API_KEY` | `function_call` parts | ResourceExhausted, Unavailable |
|
|
550
|
+
| `MockBackend` | (Testing) | `mock` | -- | Queued `ToolCall` objects | -- |
|
|
551
|
+
|
|
552
|
+
All backends implement the `LLMBackend` protocol and return `LLMResponse` with populated `tool_calls`, `finish_reason`, and `usage`. Bring your own by implementing `generate()`, `generate_stream()`, and `model_name`.
|
|
553
|
+
|
|
554
|
+
---
|
|
555
|
+
|
|
556
|
+
## Tools
|
|
557
|
+
|
|
558
|
+
Four built-in tools plus a `@tool` decorator for plain functions:
|
|
559
|
+
|
|
560
|
+
```python
|
|
561
|
+
from agenticapi import tool
|
|
562
|
+
from agenticapi.runtime.tools import ToolRegistry, DatabaseTool, CacheTool
|
|
563
|
+
|
|
564
|
+
@tool(description="Search the documentation index")
|
|
565
|
+
async def search_docs(query: str, limit: int = 10) -> list[dict]:
|
|
566
|
+
return await index.search(query, limit=limit)
|
|
567
|
+
|
|
568
|
+
registry = ToolRegistry()
|
|
569
|
+
registry.register(search_docs)
|
|
570
|
+
registry.register(DatabaseTool(name="db", execute_fn=my_query_fn, read_only=True))
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
The `@tool` decorator auto-generates the JSON schema from your type hints and infers capabilities from the function name. See [example 19](./examples/19_native_function_calling) for the native function-calling pattern with a multi-turn tool-use loop.
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
## Custom Responses, HTMX & File Handling
|
|
578
|
+
|
|
579
|
+
```python
|
|
580
|
+
from agenticapi import HTMLResult, PlainTextResult, FileResult, HtmxHeaders
|
|
581
|
+
|
|
582
|
+
@app.agent_endpoint(name="dashboard")
|
|
583
|
+
async def dashboard(intent, context):
|
|
584
|
+
return HTMLResult(content="<h1>Dashboard</h1>")
|
|
585
|
+
|
|
586
|
+
@app.agent_endpoint(name="items")
|
|
587
|
+
async def items(intent, context, htmx: HtmxHeaders):
|
|
588
|
+
if htmx.is_htmx:
|
|
589
|
+
return HTMLResult(content="<li>Item 1</li>") # Fragment
|
|
590
|
+
return HTMLResult(content="<html>Full page</html>") # Full page
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
File upload via multipart, download via `FileResult`, streaming via Starlette. See examples [10](./examples/10_file_handling), [11](./examples/11_html_responses), [12](./examples/12_htmx).
|
|
594
|
+
|
|
595
|
+
---
|
|
596
|
+
|
|
597
|
+
## MCP, REST Compatibility & Middleware
|
|
598
|
+
|
|
599
|
+
```python
|
|
600
|
+
# Expose endpoints as MCP tools (pip install agenticapi[mcp])
|
|
601
|
+
from agenticapi.interface.compat.mcp import expose_as_mcp
|
|
602
|
+
expose_as_mcp(app, path="/mcp")
|
|
603
|
+
|
|
604
|
+
# Expose as REST GET/POST routes
|
|
605
|
+
from agenticapi.interface.compat import expose_as_rest
|
|
606
|
+
app.add_routes(expose_as_rest(app, prefix="/rest"))
|
|
607
|
+
|
|
608
|
+
# Starlette middleware
|
|
609
|
+
from starlette.middleware.cors import CORSMiddleware
|
|
610
|
+
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"])
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## Observability
|
|
616
|
+
|
|
617
|
+
Structured logging via structlog is on by default. OpenTelemetry tracing and Prometheus metrics are auto-detected -- install the packages and call `configure_tracing()` / `configure_metrics()`:
|
|
618
|
+
|
|
619
|
+
```python
|
|
620
|
+
from agenticapi.observability import configure_tracing, configure_metrics
|
|
621
|
+
|
|
622
|
+
configure_tracing(service_name="my-service", otlp_endpoint="http://tempo:4317")
|
|
623
|
+
configure_metrics(service_name="my-service", enable_prometheus=True)
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
W3C trace propagation, request/latency/cost/denial metrics, graceful no-ops when not installed. See [example 16](./examples/16_observability).
|
|
627
|
+
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
## Extensions
|
|
631
|
+
|
|
632
|
+
Heavyweight integrations are released as separate packages under `extensions/`:
|
|
633
|
+
|
|
634
|
+
```bash
|
|
635
|
+
pip install agenticapi-claude-agent-sdk
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
```python
|
|
639
|
+
from agenticapi_claude_agent_sdk import ClaudeAgentRunner
|
|
640
|
+
|
|
641
|
+
runner = ClaudeAgentRunner(
|
|
642
|
+
system_prompt="You are a coding assistant.",
|
|
643
|
+
allowed_tools=["Read", "Glob", "Grep"],
|
|
644
|
+
policies=[CodePolicy(denied_modules=["os", "subprocess"])],
|
|
645
|
+
)
|
|
646
|
+
|
|
647
|
+
@app.agent_endpoint(name="assistant", autonomy_level="manual")
|
|
648
|
+
async def assistant(intent, context):
|
|
649
|
+
return await runner.run(intent=intent, context=context)
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
See [example 13](./examples/13_claude_agent_sdk).
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
## Examples
|
|
657
|
+
|
|
658
|
+
Twenty-seven example apps, from minimal hello-world to multi-agent pipelines with budget propagation:
|
|
659
|
+
|
|
660
|
+
| # | Example | LLM | Highlights |
|
|
661
|
+
|---|---|---|---|
|
|
662
|
+
| 01 | [hello_agent](./examples/01_hello_agent) | -- | Minimal single endpoint |
|
|
663
|
+
| 02 | [ecommerce](./examples/02_ecommerce) | -- | Routers, policies, approval, tools |
|
|
664
|
+
| 03 | [openai_agent](./examples/03_openai_agent) | OpenAI | Full harness pipeline with GPT |
|
|
665
|
+
| 04 | [anthropic_agent](./examples/04_anthropic_agent) | Anthropic | Claude with `ResourcePolicy` |
|
|
666
|
+
| 05 | [gemini_agent](./examples/05_gemini_agent) | Gemini | Sessions and multi-turn |
|
|
667
|
+
| 06 | [full_stack](./examples/06_full_stack) | Configurable | Pipeline, ops, A2A, REST compat, monitors |
|
|
668
|
+
| 07 | [comprehensive](./examples/07_comprehensive) | Configurable | DevOps platform, multi-feature per endpoint |
|
|
669
|
+
| 08 | [mcp_agent](./examples/08_mcp_agent) | -- | MCP server with selective endpoint exposure |
|
|
670
|
+
| 09 | [auth_agent](./examples/09_auth_agent) | -- | API key auth with role-based access |
|
|
671
|
+
| 10 | [file_handling](./examples/10_file_handling) | -- | Upload, download, streaming |
|
|
672
|
+
| 11 | [html_responses](./examples/11_html_responses) | -- | HTML, plain text, custom responses |
|
|
673
|
+
| 12 | [htmx](./examples/12_htmx) | -- | Interactive todo app with partial updates |
|
|
674
|
+
| 13 | [claude_agent_sdk](./examples/13_claude_agent_sdk) | Extension | Full Claude Agent SDK loop |
|
|
675
|
+
| 14 | [dependency_injection](./examples/14_dependency_injection) | -- | Bookstore with every `Depends()` pattern |
|
|
676
|
+
| 15 | [budget_policy](./examples/15_budget_policy) | Mock | Cost governance, 4 budget scopes |
|
|
677
|
+
| 16 | [observability](./examples/16_observability) | -- | OTel tracing, Prometheus, SQLite audit |
|
|
678
|
+
| 17 | [typed_intents](./examples/17_typed_intents) | Mock | `Intent[T]` with Pydantic schemas |
|
|
679
|
+
| 18 | [rest_interop](./examples/18_rest_interop) | -- | `response_model`, `expose_as_rest`, mounted sub-app |
|
|
680
|
+
| 19 | [native_function_calling](./examples/19_native_function_calling) | Mock | `ToolCall` dispatch, multi-turn loop |
|
|
681
|
+
| 20 | [streaming_release_control](./examples/20_streaming_release_control) | -- | SSE, NDJSON, approval resume, replay |
|
|
682
|
+
| 21 | [persistent_memory](./examples/21_persistent_memory) | -- | Agent memory with SQLite persistence |
|
|
683
|
+
| 22 | [safety_policies](./examples/22_safety_policies) | -- | Prompt-injection detection, PII protection |
|
|
684
|
+
| 23 | [eval_harness](./examples/23_eval_harness) | -- | Regression-test agent endpoints |
|
|
685
|
+
| 24 | [code_cache](./examples/24_code_cache) | -- | Skip LLM with approved-code cache |
|
|
686
|
+
| 25 | [harness_playground](./examples/25_harness_playground) | -- | Full harness with autonomy, safety, streaming |
|
|
687
|
+
| 26 | [dynamic_pipeline](./examples/26_dynamic_pipeline) | -- | Middleware-like stage composition |
|
|
688
|
+
| 27 | [multi_agent_pipeline](./examples/27_multi_agent_pipeline) | -- | 3-role `AgentMesh` with budget propagation |
|
|
689
|
+
|
|
690
|
+
Every example is a standalone ASGI app -- `agenticapi dev --app examples.NN_name.app:app` and you're running. See the [examples README](./examples/README.md) for curl commands and per-endpoint documentation.
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
## CLI Reference
|
|
695
|
+
|
|
696
|
+
```bash
|
|
697
|
+
agenticapi init <name> [--template default|chat|tool-calling] # Scaffold a new project
|
|
698
|
+
agenticapi dev --app myapp:app [--host 0.0.0.0] [--port 8000] # Development server
|
|
699
|
+
agenticapi console --app myapp:app # Interactive REPL
|
|
700
|
+
agenticapi replay <trace_id> --app myapp:app # Re-run audit trace
|
|
701
|
+
agenticapi eval --set evals/golden.yaml --app myapp:app # Regression gate
|
|
702
|
+
agenticapi version # Show version
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
---
|
|
706
|
+
|
|
707
|
+
## Development
|
|
708
|
+
|
|
709
|
+
```bash
|
|
710
|
+
git clone https://github.com/shibuiwilliam/AgenticAPI.git
|
|
711
|
+
cd AgenticAPI
|
|
712
|
+
uv sync --group dev
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
### Common Commands
|
|
716
|
+
|
|
717
|
+
```bash
|
|
718
|
+
make test # Run all 1,310 tests
|
|
719
|
+
make test-cov # Tests with coverage
|
|
720
|
+
make check # Format + lint + typecheck
|
|
721
|
+
make fix # Auto-fix formatting and lint issues
|
|
722
|
+
make dev # Start dev server (hello agent example)
|
|
723
|
+
make docs # Live-reloading documentation
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
### Running Tests
|
|
727
|
+
|
|
728
|
+
```bash
|
|
729
|
+
uv run pytest # All tests
|
|
730
|
+
uv run pytest tests/unit/ -xvs # Unit tests, stop on first failure
|
|
731
|
+
uv run pytest tests/e2e/ -v # E2E tests for all 27 examples
|
|
732
|
+
uv run pytest -m "not requires_llm" # Skip tests needing API keys
|
|
733
|
+
uv run pytest --cov=src/agenticapi # With coverage
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### Code Quality
|
|
737
|
+
|
|
738
|
+
```bash
|
|
739
|
+
uv run ruff format src/ tests/ examples/ # Format
|
|
740
|
+
uv run ruff check src/ tests/ examples/ # Lint
|
|
741
|
+
uv run mypy src/agenticapi/ # Type check (strict mode)
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
### Pre-commit Hooks
|
|
745
|
+
|
|
746
|
+
```bash
|
|
747
|
+
pip install pre-commit && pre-commit install
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
Hooks run `ruff format`, `ruff check`, and `mypy` automatically before each commit.
|
|
751
|
+
|
|
752
|
+
---
|
|
753
|
+
|
|
754
|
+
## Project Structure
|
|
755
|
+
|
|
756
|
+
```
|
|
757
|
+
src/agenticapi/
|
|
758
|
+
__init__.py # 73 public exports
|
|
759
|
+
app.py # AgenticApp -- main ASGI application
|
|
760
|
+
routing.py # AgentRouter -- endpoint grouping
|
|
761
|
+
security.py # Authentication (APIKeyHeader, HTTPBearer, Authenticator)
|
|
762
|
+
exceptions.py # Exception hierarchy with HTTP status mapping
|
|
763
|
+
openapi.py # OpenAPI schema, Swagger UI, ReDoc
|
|
764
|
+
types.py # AutonomyLevel, Severity, TraceLevel
|
|
765
|
+
dependencies/ # Depends(), InjectionPlan, solver
|
|
766
|
+
interface/
|
|
767
|
+
intent.py # Intent, Intent[T], IntentParser, IntentScope
|
|
768
|
+
response.py # AgentResponse, FileResult, HTMLResult, PlainTextResult
|
|
769
|
+
stream.py # AgentStream, AgentEvent -- SSE/NDJSON streaming
|
|
770
|
+
stream_store.py # Replayable event storage
|
|
771
|
+
upload.py # UploadFile, UploadedFiles
|
|
772
|
+
htmx.py # HtmxHeaders, htmx_response_headers
|
|
773
|
+
tasks.py # AgentTasks (background tasks)
|
|
774
|
+
session.py # SessionManager with TTL
|
|
775
|
+
transports/ # SSE and NDJSON framing helpers
|
|
776
|
+
compat/ # REST, FastAPI, MCP compatibility
|
|
777
|
+
a2a/ # Agent-to-Agent protocol, capability, trust
|
|
778
|
+
harness/
|
|
779
|
+
engine.py # HarnessEngine -- safety pipeline orchestrator
|
|
780
|
+
policy/ # Code, Data, Resource, Runtime, Budget, PromptInjection, PII, Autonomy
|
|
781
|
+
sandbox/ # ProcessSandbox, static AST analysis, monitors, validators
|
|
782
|
+
approval/ # ApprovalWorkflow, ApprovalRule
|
|
783
|
+
audit/ # AuditRecorder, SqliteAuditRecorder, ExecutionTrace
|
|
784
|
+
runtime/
|
|
785
|
+
code_generator.py # LLM-powered code generation
|
|
786
|
+
code_cache.py # CodeCache, InMemoryCodeCache, CachedCode
|
|
787
|
+
context.py # AgentContext, ContextWindow
|
|
788
|
+
memory/ # MemoryStore, SqliteMemoryStore, InMemoryMemoryStore
|
|
789
|
+
llm/ # Anthropic, OpenAI, Gemini, Mock -- with ToolCall + RetryConfig
|
|
790
|
+
tools/ # Database, Cache, HTTP, Queue, @tool decorator
|
|
791
|
+
prompts/ # Prompt templates
|
|
792
|
+
mesh/ # AgentMesh, MeshContext -- multi-agent orchestration
|
|
793
|
+
observability/ # OpenTelemetry tracing, Prometheus metrics, W3C propagation
|
|
794
|
+
evaluation/ # EvalSet, judges, runner
|
|
795
|
+
application/ # DynamicPipeline
|
|
796
|
+
ops/ # OpsAgent, OpsHealthStatus
|
|
797
|
+
testing/ # mock_llm, MockSandbox, assertions, fixtures
|
|
798
|
+
cli/ # dev, console, replay, eval, init, version
|
|
799
|
+
|
|
800
|
+
extensions/
|
|
801
|
+
agenticapi-claude-agent-sdk/ # Independent package -- full Claude Agent SDK loop
|
|
802
|
+
|
|
803
|
+
examples/
|
|
804
|
+
01_hello_agent/ .. 27_multi_agent_pipeline/ # 27 runnable example apps
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
---
|
|
808
|
+
|
|
809
|
+
## Requirements
|
|
810
|
+
|
|
811
|
+
- **Python** >= 3.13
|
|
812
|
+
- **[Starlette](https://www.starlette.io/)** >= 1.0 -- ASGI foundation
|
|
813
|
+
- **[Pydantic](https://docs.pydantic.dev/)** >= 2.12 -- Validation and schemas
|
|
814
|
+
- **[structlog](https://www.structlog.org/)** >= 25.0 -- Structured logging
|
|
815
|
+
- **[httpx](https://www.python-httpx.org/)** >= 0.28 -- Async HTTP client
|
|
816
|
+
- **[python-multipart](https://github.com/Kludex/python-multipart)** >= 0.0.20 -- File upload parsing
|
|
817
|
+
- LLM SDKs: [anthropic](https://github.com/anthropics/anthropic-sdk-python) >= 0.89, [openai](https://github.com/openai/openai-python) >= 2.30, [google-genai](https://github.com/googleapis/python-genai) >= 1.70
|
|
818
|
+
|
|
819
|
+
Everything else (OpenTelemetry, Prometheus, MCP) is optional and degrades gracefully to a no-op when absent.
|
|
820
|
+
|
|
821
|
+
---
|
|
822
|
+
|
|
823
|
+
## Documentation
|
|
824
|
+
|
|
825
|
+
Full documentation lives at [`docs/`](./docs/) and is published with MkDocs:
|
|
826
|
+
|
|
827
|
+
```bash
|
|
828
|
+
make docs # Live-reloading docs at http://127.0.0.1:8001
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
- **[Getting Started](./docs/getting-started/)** -- Installation, quick start, all 27 examples
|
|
832
|
+
- **[Guides](./docs/guides/)** -- Architecture, typed intents, DI, safety policies, streaming, memory, eval harness, observability, and more
|
|
833
|
+
- **[API Reference](./docs/api/)** -- Every public class and function
|
|
834
|
+
- **[Internals](./docs/internals/)** -- Module reference, extending the framework, implementation notes
|
|
835
|
+
|
|
836
|
+
### Where everything lives
|
|
837
|
+
|
|
838
|
+
| File | Purpose |
|
|
839
|
+
|---|---|
|
|
840
|
+
| [`PROJECT.md`](./PROJECT.md) | Stable product vision, design principles, architecture pillars |
|
|
841
|
+
| [`CLAUDE.md`](./CLAUDE.md) | Developer guide -- commands, conventions, module map |
|
|
842
|
+
| [`CONTRIBUTING.md`](./CONTRIBUTING.md) | Contributor onboarding |
|
|
843
|
+
|
|
844
|
+
---
|
|
845
|
+
|
|
846
|
+
## Contributing
|
|
847
|
+
|
|
848
|
+
Contributions are very welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup, code conventions, and the PR workflow. If you're not sure where to start, a new example app or an improvement to an existing one is always a great first PR.
|
|
849
|
+
|
|
850
|
+
Found a bug or have an idea? [Open an issue](https://github.com/shibuiwilliam/AgenticAPI/issues) -- we'd love to hear from you.
|
|
851
|
+
|
|
852
|
+
## License
|
|
853
|
+
|
|
854
|
+
[MIT](./LICENSE)
|