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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ai-agent-inspector
3
- Version: 1.0.0
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 .env.example .env
609
+ cp examples/.env.example examples/.env
608
610
  ```
609
611
 
610
- Set these in `.env`:
611
- - `OPENAI_BASE_URL`
612
- - `OPENAI_API_KEY`
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
- Create a new adapter by extending `BaseCallbackHandler` (for LangChain-like frameworks) or by using the Trace SDK directly:
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 Trace, get_trace
930
+ from agent_inspector import trace, get_trace
843
931
 
844
932
  class CustomAdapter:
845
- def __init__(self, trace: Trace = None):
846
- self.trace = trace or get_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, args, result):
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=args, tool_result=result)
944
+ context.tool(tool_name=tool_name, tool_args=tool_args, tool_result=tool_result)
859
945
 
860
- # Use your adapter
861
- with trace.run("custom_agent"):
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,,