ai-agent-inspector 1.0.0__py3-none-any.whl → 1.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.
- agent_inspector/__init__.py +30 -0
- agent_inspector/cli.py +22 -3
- agent_inspector/ui/static/app.css +1202 -629
- agent_inspector/ui/templates/index.html +452 -144
- {ai_agent_inspector-1.0.0.dist-info → ai_agent_inspector-1.1.0.dist-info}/METADATA +122 -26
- ai_agent_inspector-1.1.0.dist-info/RECORD +11 -0
- ai_agent_inspector-1.0.0.dist-info/RECORD +0 -11
- {ai_agent_inspector-1.0.0.dist-info → ai_agent_inspector-1.1.0.dist-info}/WHEEL +0 -0
- {ai_agent_inspector-1.0.0.dist-info → ai_agent_inspector-1.1.0.dist-info}/entry_points.txt +0 -0
- {ai_agent_inspector-1.0.0.dist-info → ai_agent_inspector-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {ai_agent_inspector-1.0.0.dist-info → ai_agent_inspector-1.1.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-agent-inspector
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Framework-agnostic observability for AI agents
|
|
5
5
|
Author-email: Agent Inspector Team <team@agentinspector.dev>
|
|
6
6
|
License: MIT
|
|
@@ -27,6 +27,7 @@ Requires-Dist: uvicorn[standard]>=0.24.0
|
|
|
27
27
|
Requires-Dist: cryptography>=41.0.0
|
|
28
28
|
Requires-Dist: jinja2>=3.1.0
|
|
29
29
|
Requires-Dist: python-dotenv>=1.0.0
|
|
30
|
+
Requires-Dist: openai>=2.16.0
|
|
30
31
|
Provides-Extra: langchain
|
|
31
32
|
Requires-Dist: langchain>=0.1.0; extra == "langchain"
|
|
32
33
|
Provides-Extra: otel
|
|
@@ -154,7 +155,7 @@ Traditional tools model systems as function calls and spans. Agent Inspector mod
|
|
|
154
155
|
|
|
155
156
|
### Storage
|
|
156
157
|
- **SQLite** – WAL mode for concurrent access; runs and steps tables; indexes on run_id and timestamp.
|
|
157
|
-
- **Pruning** – CLI `prune --retention-days N` and optional `--vacuum`; API/DB support for retention.
|
|
158
|
+
- **Pruning** – CLI `prune --retention-days N` and optional `--retention-max-bytes BYTES`, `--vacuum`; API/DB support for retention by age and by size.
|
|
158
159
|
- **Backup** – CLI `backup /path/to/backup.db` for full DB copy.
|
|
159
160
|
- **Export to JSON** – **API** `GET /v1/runs/{run_id}/export` returns run metadata + timeline with decoded event data; **CLI** `agent-inspector export <run_id> [--output file.json]` and `agent-inspector export --all [--limit N] [--output file.json]` for backup or migration.
|
|
160
161
|
|
|
@@ -506,6 +507,7 @@ export TRACE_ENCRYPTION_KEY=your-secret-key-here
|
|
|
506
507
|
# Storage
|
|
507
508
|
export TRACE_DB_PATH=agent_inspector.db
|
|
508
509
|
export TRACE_RETENTION_DAYS=30
|
|
510
|
+
export TRACE_RETENTION_MAX_BYTES=
|
|
509
511
|
|
|
510
512
|
# API
|
|
511
513
|
export TRACE_API_HOST=127.0.0.1
|
|
@@ -604,24 +606,78 @@ search_flights_agent("Find flights from SFO to JFK")
|
|
|
604
606
|
This example makes real LLM calls and runs multiple scenarios.
|
|
605
607
|
|
|
606
608
|
```bash
|
|
607
|
-
cp
|
|
609
|
+
cp examples/.env.example examples/.env
|
|
608
610
|
```
|
|
609
611
|
|
|
610
|
-
Set these in
|
|
611
|
-
- `
|
|
612
|
-
- `
|
|
613
|
-
- `OPENAI_MODEL`
|
|
612
|
+
Set these in `examples/.env`:
|
|
613
|
+
- `OPENAI_API_KEY` - Your API key
|
|
614
|
+
- `OPENAI_BASE_URL` - API endpoint (e.g., `https://api.openai.com/v1` or your custom provider)
|
|
615
|
+
- `OPENAI_MODEL` - Model name (e.g., `gpt-4o-mini`, `glm-4.7`)
|
|
616
|
+
- `OPENAI_TEMPERATURE` - Temperature setting (default: 0.2)
|
|
617
|
+
- `OPENAI_TIMEOUT` - Timeout in seconds (default: 120)
|
|
618
|
+
|
|
619
|
+
Install dependencies:
|
|
620
|
+
```bash
|
|
621
|
+
uv add openai python-dotenv
|
|
622
|
+
```
|
|
614
623
|
|
|
615
624
|
Run a single question:
|
|
616
625
|
```bash
|
|
617
|
-
python examples/real_agent.py "What is 13 * (7 + 5)?"
|
|
626
|
+
uv run python examples/real_agent.py "What is 13 * (7 + 5)?"
|
|
618
627
|
```
|
|
619
628
|
|
|
620
629
|
Run the full scenario suite:
|
|
621
630
|
```bash
|
|
622
|
-
python examples/real_agent.py --suite
|
|
631
|
+
uv run python examples/real_agent.py --suite
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
### Multi-Agent Example
|
|
635
|
+
|
|
636
|
+
This example demonstrates a realistic multi-agent customer support system with:
|
|
637
|
+
- **Agent spawning** with different models per agent
|
|
638
|
+
- **Intelligent routing** to specialized agents (billing, technical, triage, manager)
|
|
639
|
+
- **Tool execution** with realistic operations (profile lookup, billing history, system logs)
|
|
640
|
+
- **Agent communication** with handoffs for escalations
|
|
641
|
+
- **Detailed responses** with contextual, professional customer service replies
|
|
642
|
+
- **Escalation workflow** where complex issues get manager oversight
|
|
643
|
+
|
|
644
|
+
```bash
|
|
645
|
+
cp examples/.env.example examples/.env
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
Configure in `examples/.env`:
|
|
649
|
+
- `OPENAI_API_KEY` - Your API key
|
|
650
|
+
- `OPENAI_BASE_URL` - API endpoint
|
|
651
|
+
- `OPENAI_MODEL` - Default model for all agents
|
|
652
|
+
- `MODEL_TRIAGE` - Model for triage agent (optional, falls back to `OPENAI_MODEL`)
|
|
653
|
+
- `MODEL_BILLING` - Model for billing agent (optional)
|
|
654
|
+
- `MODEL_TECHNICAL` - Model for technical agent (optional)
|
|
655
|
+
- `MODEL_MANAGER` - Model for manager agent (optional)
|
|
656
|
+
|
|
657
|
+
Install dependencies:
|
|
658
|
+
```bash
|
|
659
|
+
uv add openai python-dotenv
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
Run in simulated mode (no API needed):
|
|
663
|
+
```bash
|
|
664
|
+
python examples/multi_agent.py
|
|
623
665
|
```
|
|
624
666
|
|
|
667
|
+
Run with real LLM calls:
|
|
668
|
+
```bash
|
|
669
|
+
uv run python examples/multi_agent.py
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
The example traces:
|
|
673
|
+
- Customer requests with routing analysis
|
|
674
|
+
- Agent-specific tool usage with realistic results
|
|
675
|
+
- Detailed, contextual responses for each customer issue
|
|
676
|
+
- Escalation flows with manager handoffs
|
|
677
|
+
- Task assignment and completion tracking
|
|
678
|
+
|
|
679
|
+
Note: Without `openai` package and valid API key, this example will use simulated responses with realistic agent behavior. Install `openai` with `uv add openai` and configure `OPENAI_API_KEY` in `examples/.env` for real LLM calls. Use `uv run python` to execute the script with uv's virtual environment.
|
|
680
|
+
|
|
625
681
|
### With LangChain (Automatic)
|
|
626
682
|
|
|
627
683
|
```python
|
|
@@ -716,6 +772,30 @@ with trace.run("planning_agent", user_id="user123") as main_ctx:
|
|
|
716
772
|
trace.final(answer="I've booked your flight. Confirmation: CONF-12345")
|
|
717
773
|
```
|
|
718
774
|
|
|
775
|
+
### Async / asyncio
|
|
776
|
+
|
|
777
|
+
Context is propagated via `contextvars`, so tracing works with asyncio as long as each task has its own `trace.run()` (one run per task). Do not share a single run across concurrent tasks.
|
|
778
|
+
|
|
779
|
+
```python
|
|
780
|
+
import asyncio
|
|
781
|
+
from agent_inspector import trace
|
|
782
|
+
|
|
783
|
+
async def agent_task(name: str, query: str):
|
|
784
|
+
with trace.run(name):
|
|
785
|
+
trace.llm(model="gpt-4", prompt=query, response=f"Processed: {query}")
|
|
786
|
+
trace.final(answer=f"Done: {query}")
|
|
787
|
+
return name
|
|
788
|
+
|
|
789
|
+
async def main():
|
|
790
|
+
results = await asyncio.gather(
|
|
791
|
+
agent_task("agent_1", "Query A"),
|
|
792
|
+
agent_task("agent_2", "Query B"),
|
|
793
|
+
)
|
|
794
|
+
return results
|
|
795
|
+
|
|
796
|
+
asyncio.run(main())
|
|
797
|
+
```
|
|
798
|
+
|
|
719
799
|
### Memory Operations
|
|
720
800
|
|
|
721
801
|
```python
|
|
@@ -836,35 +916,41 @@ result = chain.run("Your query", callbacks=callbacks)
|
|
|
836
916
|
|
|
837
917
|
### Creating Custom Adapters
|
|
838
918
|
|
|
839
|
-
|
|
919
|
+
Use the Trace SDK directly when your framework has no LangChain-style callback API. Checklist:
|
|
920
|
+
|
|
921
|
+
1. **Entry point** – Wrap agent execution in `trace.run("run_name")` so there is an active context.
|
|
922
|
+
2. **LLM calls** – Where your framework invokes the model, call `context.llm(model=..., prompt=..., response=...)`.
|
|
923
|
+
3. **Tool calls** – Where tools are executed, call `context.tool(tool_name=..., tool_args=..., tool_result=...)`.
|
|
924
|
+
4. **Final answer** – When the agent finishes, call `context.final(answer=...)`.
|
|
925
|
+
5. **Errors** – On failure, call `context.error(error_type=..., error_message=..., critical=...)`.
|
|
926
|
+
|
|
927
|
+
Template:
|
|
840
928
|
|
|
841
929
|
```python
|
|
842
|
-
from agent_inspector import
|
|
930
|
+
from agent_inspector import trace, get_trace
|
|
843
931
|
|
|
844
932
|
class CustomAdapter:
|
|
845
|
-
def __init__(self,
|
|
846
|
-
self.trace =
|
|
847
|
-
|
|
848
|
-
def on_llm_call(self, model, prompt, response):
|
|
849
|
-
"""Handle LLM calls in your framework."""
|
|
933
|
+
def __init__(self, trace_instance=None):
|
|
934
|
+
self.trace = trace_instance or get_trace()
|
|
935
|
+
|
|
936
|
+
def on_llm_call(self, model: str, prompt: str, response: str):
|
|
850
937
|
context = self.trace.get_active_context()
|
|
851
938
|
if context:
|
|
852
939
|
context.llm(model=model, prompt=prompt, response=response)
|
|
853
|
-
|
|
854
|
-
def on_tool_call(self, tool_name,
|
|
855
|
-
"""Handle tool calls in your framework."""
|
|
940
|
+
|
|
941
|
+
def on_tool_call(self, tool_name: str, tool_args: dict, tool_result: str):
|
|
856
942
|
context = self.trace.get_active_context()
|
|
857
943
|
if context:
|
|
858
|
-
context.tool(tool_name=tool_name, tool_args=
|
|
944
|
+
context.tool(tool_name=tool_name, tool_args=tool_args, tool_result=tool_result)
|
|
859
945
|
|
|
860
|
-
# Use
|
|
861
|
-
with trace.run("
|
|
946
|
+
# Use: always run inside trace.run() so get_active_context() returns a context
|
|
947
|
+
with trace.run("my_agent"):
|
|
862
948
|
adapter = CustomAdapter()
|
|
863
|
-
|
|
864
|
-
# Your framework code
|
|
865
949
|
adapter.on_llm_call("gpt-4", "Hello", "Hi there!")
|
|
866
950
|
```
|
|
867
951
|
|
|
952
|
+
For LangChain-like frameworks, extend `BaseCallbackHandler` and pass the handler into the framework's callback list; see the LangChain adapter source for the pattern.
|
|
953
|
+
|
|
868
954
|
---
|
|
869
955
|
|
|
870
956
|
## Development
|
|
@@ -952,8 +1038,12 @@ Releases are automated with [Release Please](https://github.com/googleapis/relea
|
|
|
952
1038
|
- **fix:** – bug fix (bumps patch version)
|
|
953
1039
|
- **feat!:** or **BREAKING CHANGE:** – breaking change (bumps major version)
|
|
954
1040
|
|
|
1041
|
+
To force a specific version, add `Release-As: X.Y.Z` in the commit message footer (e.g. `Release-As: 1.1.0`).
|
|
1042
|
+
|
|
955
1043
|
When you merge the Release PR, a tag is created and the [publish workflow](.github/workflows/publish.yml) publishes to PyPI (OIDC).
|
|
956
1044
|
|
|
1045
|
+
**First release:** Release Please only creates Release PRs for commits *since* the latest release. If you have no release yet, create the initial tag so it has a baseline: `git tag v1.0.0 && git push origin v1.0.0`. After that, new `feat:`/`fix:` commits (not `docs:` or `chore:`) will get Release PRs.
|
|
1046
|
+
|
|
957
1047
|
---
|
|
958
1048
|
|
|
959
1049
|
## Contributing
|
|
@@ -1011,8 +1101,8 @@ agent-inspector server [--host HOST] [--port PORT]
|
|
|
1011
1101
|
# View statistics
|
|
1012
1102
|
agent-inspector stats
|
|
1013
1103
|
|
|
1014
|
-
# Prune old traces
|
|
1015
|
-
agent-inspector prune [--retention-days N] [--vacuum]
|
|
1104
|
+
# Prune old traces (optionally by size: --retention-max-bytes BYTES)
|
|
1105
|
+
agent-inspector prune [--retention-days N] [--retention-max-bytes BYTES] [--vacuum]
|
|
1016
1106
|
|
|
1017
1107
|
# Vacuum database
|
|
1018
1108
|
agent-inspector vacuum
|
|
@@ -1047,6 +1137,12 @@ Agent Inspector is designed for minimal overhead:
|
|
|
1047
1137
|
- Background thread: ~5MB (batch processing)
|
|
1048
1138
|
- Database: Varies with trace volume
|
|
1049
1139
|
|
|
1140
|
+
### Scaling and alerting
|
|
1141
|
+
|
|
1142
|
+
- **Single process / moderate load** – Use the default SQLite storage with sampling and retention (e.g. `retention_days`, optional `retention_max_bytes`). Suitable for one or a few worker processes.
|
|
1143
|
+
- **High throughput or many writers** – Use an OTLP or custom exporter to send traces to a central backend (e.g. Jaeger, Tempo, Grafana). The built-in UI and API then serve only that process; aggregate viewing is in your backend.
|
|
1144
|
+
- **Alerting** – The SDK does not push alerts. Use the API from your own checks: e.g. `GET /v1/stats` for `failed_runs`, `recent_runs_24h`, or `queue.events_dropped` (when the default Trace is in use), and alert when thresholds are exceeded. Optionally run `agent-inspector prune` on a schedule to enforce retention.
|
|
1145
|
+
|
|
1050
1146
|
---
|
|
1051
1147
|
|
|
1052
1148
|
## Security
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
agent_inspector/__init__.py,sha256=q8PWgVL74QOWMsyE5aE6xKL8xr8u3tmThDJo1JIINyA,3928
|
|
2
|
+
agent_inspector/cli.py,sha256=tR3ui2jxSs6HVXXEVKGs8IqkPgCKgf4lYrBGUtkc2_g,15563
|
|
3
|
+
agent_inspector/ui/static/app.css,sha256=5THe9xG2n5TEgtp5ShwobwFce-ooMO3sWJLDPKmi7UM,25711
|
|
4
|
+
agent_inspector/ui/static/app.js,sha256=ne6syJFigqaN6sA-vIXgUTSAOwokleY05MwJRxhsk88,14295
|
|
5
|
+
agent_inspector/ui/templates/index.html,sha256=J3fXKyNtGGbGXCrNW7B1Kk0vzJkuN--s_QjVKAeqz70,33587
|
|
6
|
+
ai_agent_inspector-1.1.0.dist-info/licenses/LICENSE,sha256=fRG0znlBiye1MRIjV0JpD1hDVOiccO-9sjeOb48uxV8,1067
|
|
7
|
+
ai_agent_inspector-1.1.0.dist-info/METADATA,sha256=0v3ThZqcrkIfo6inDHHBwF8tmMkVmOU5gQ4Vx3LDw6o,34821
|
|
8
|
+
ai_agent_inspector-1.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
9
|
+
ai_agent_inspector-1.1.0.dist-info/entry_points.txt,sha256=LyvLcPfU8saSv9e890NSI3_FyhJswXudbQfVqchIz7E,61
|
|
10
|
+
ai_agent_inspector-1.1.0.dist-info/top_level.txt,sha256=LW8u7mUPBH1BjmzTlh7qKB7-A-QyLyLxxBy02k5cnS4,16
|
|
11
|
+
ai_agent_inspector-1.1.0.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
agent_inspector/__init__.py,sha256=7h5ivS0cDhosGYHe50te--n11CSuSHkXh7B4fiPMKxY,3256
|
|
2
|
-
agent_inspector/cli.py,sha256=oCnKFi0nn0fnPFMJPcNYZA6Y7CbyUEfes4mdN0X-aSE,14741
|
|
3
|
-
agent_inspector/ui/static/app.css,sha256=KDvffC-CHFk4pdnr8Cboy0xgprFXYZeKstV_8NIMgMw,16491
|
|
4
|
-
agent_inspector/ui/static/app.js,sha256=ne6syJFigqaN6sA-vIXgUTSAOwokleY05MwJRxhsk88,14295
|
|
5
|
-
agent_inspector/ui/templates/index.html,sha256=0Jq7wF1o6jGqS-15139yFEuG8rAWfb3XH7f-bHWXL9c,16630
|
|
6
|
-
ai_agent_inspector-1.0.0.dist-info/licenses/LICENSE,sha256=fRG0znlBiye1MRIjV0JpD1hDVOiccO-9sjeOb48uxV8,1067
|
|
7
|
-
ai_agent_inspector-1.0.0.dist-info/METADATA,sha256=2DElU-mbKAYMehScwMvYlYyO4Mzsc2OrQ3GI_xEZgRg,29982
|
|
8
|
-
ai_agent_inspector-1.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
9
|
-
ai_agent_inspector-1.0.0.dist-info/entry_points.txt,sha256=LyvLcPfU8saSv9e890NSI3_FyhJswXudbQfVqchIz7E,61
|
|
10
|
-
ai_agent_inspector-1.0.0.dist-info/top_level.txt,sha256=LW8u7mUPBH1BjmzTlh7qKB7-A-QyLyLxxBy02k5cnS4,16
|
|
11
|
-
ai_agent_inspector-1.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|